Made with Lisp
Ogamita ALPM · Free & open source

AutoLISP finally gets a package manager.

ALPM is a system definition and loading facility for AutoLISP, in the spirit of ASDF: describe your libraries as systems with declared dependencies, and load them in the right order, every time, on AutoCAD, BricsCAD, or clautolisp.

AutoLISP has no defsystem, no defpackage, and no load-order safety net. Multi-file libraries are held together by hand-written (load ...) forms copy-pasted between projects, or by VLISP .prj/.prv files that record a linear compile order but no dependency graph at all. ALPM makes the system, not the file, the unit you manage: name it, declare what it depends on and what it exports, and let ALPM compute the load order, verify every path before touching any of them, and load it identically whether the engine underneath is AutoCAD, BricsCAD, or a headless clautolisp process.

The same definition can also generate a self-locating standalone loader, a pre-converted distribution tree, or a single concatenated file — so a system built and tested against ALPM still reaches a machine that has never heard of ALPM.

Why It Matters

Built for AutoLISP code bases that have outgrown one folder of loose .lsp files and a prayer about load order.

No more load-order folklore

System- and file-level depends-on, resolved transitively and loaded exactly once. Circular dependencies are refused with the cycle spelled out, not a mysterious undefined-function error three files later.

One definition, three engines

The same .alpm system loads identically on AutoCAD, BricsCAD, and headless clautolisp — so your library, and its tests, run wherever your pipeline needs them to.

Encoding stops being a gamble

Declare ascii/utf-8/utf-8-bom/cp1252/mac-roman per system or per file. A mismatch with what the running engine expects is handled or converted — never silently mangled accents.

A declared public interface

AutoLISP has no defpackage. ALPM's exports declaration is checked against the sources, and generates the vl-doc-export calls a VLX or DEScoder separate-namespace module needs to publish anything at all.

Deploy without ALPM installed

Generate a self-locating standalone loader, a pre-converted distribution tree, or one concatenated file. End users need nothing but the sources you hand them.

Bridges to VLISP projects

alpm-import-project reads an existing .prj into a serial system; alpm-export-project writes one back — a round trip verified against real VLIDE samples.

The Numbers

Current state of the 1.0.0 release.

1.0.0First stable release; definition format 1.
56Tests, all green, run headless under clautolisp on every commit.
3Engines: AutoCAD, BricsCAD, clautolisp.
5Source encodings actively converted: ascii, utf-8, utf-8-bom, cp1252, mac-roman.
1File to install — alpm.lsp, concatenated by itself, one load.
0External dependencies: pure AutoLISP, no registry to ask permission of.

How It Works

Describe a system once. Load it by name, on any engine, forever after.

1. Describe a system in geometry.alpm

(alpm-define-system 1
 '(name        "geometry"
   version     "1.0.0"
   description "2D geometry entities and predicates."
   files       ("points"
                (file "lines"   depends-on ("points"))
                (file "circles" depends-on ("points" "lines")))))

2. Load it, in the right order

(load "/opt/local/share/autolisp/alpm.lsp")
(alpm-register-directory "/home/pjb/lisp" nil)
(alpm-load-system "geometry" nil)
;; => "geometry"   -- points, then lines, then circles

Ship it to a machine that has no ALPM at all:

(alpm-generate-loader "geometry" "geometry-loader.lsp" nil)
;; -- self-locating; (load "geometry-loader.lsp") loads the whole system

(alpm-concatenate-system "geometry" "geometry-all.lsp" nil nil)
;; -- one file, dependency order, nothing else required

What You Get

One implementation file, seven coordinated capabilities.

Registry & discovery Register directories or whole trees, symlink-safe. A read-only alpm-find-systems-in-tree shows what is there before you register anything; automatic import of the engine's own search path and TRUSTEDPATHS.
Definitions & dependencies System- and file-level depends-on, transitive and loaded exactly once; a serial shortcut for files that simply load in listed order; every path checked before anything loads.
Encodings Declare a system's or a file's encoding; ALPM matches it against the running engine's own expectation, sets the load encoding where the engine supports that, or converts a scratch copy — a declaration it cannot honor is a plan-time error, never a mojibake string constant.
Exports A checked public-interface declaration (alpm-check-exports, alpm-scan-exports) and generation of the vl-doc-export calls a VLX or DEScoder separate-namespace module needs.
Distribution & deployment Self-locating standalone loaders, pre-converted distribution trees, and single concatenated files (with or without dependencies inlined) — three ways to hand a system to a machine that has never heard of ALPM.
VLISP bridge alpm-import-project and alpm-export-project read and write .prj/.prv files, round-trip verified against real VLIDE samples.
Introspection Query registered and loaded systems, computed load plans, per-file load state and last value; build and save definitions programmatically instead of by hand.

How ALPM Compares

AutoLISP libraries have always shipped somehow. ALPM's bet is to make the "somehow" a declared, checked, portable definition instead of a convention held together by memory.

ALPM Hand-written load forms VLISP .prj / .prv project
Dependency ordering automatic, file + system, cycles detected manual, by convention linear order only, no dependencies
Runs on AutoCAD, BricsCAD, clautolisp whatever you wrote it for AutoCAD & BricsCAD, as a compiled module
Declared public interface yes, checked against sources no separate-namespace toggle, undeclared
Encoding handled declared and converted not addressed not addressed
Works with no tool installed yes — generated loader, distribution, or single file yes, by hand yes, as an opaque compiled artifact
Definition is a diffable text file yes (.alpm) yes (.lsp) no — IDE-managed

ALPM does not replace .prj/.prv projects where a compiled, separate-namespace module is what you actually need — it imports and exports them, and generates the vl-doc-export calls those modules rely on. What it replaces is the folklore in between: the load order nobody wrote down.

Get Started

Build from source and install into any prefix.

1. Install

$ git clone https://gitlab.com/ogamita/alpm.git
$ cd alpm
$ make install   # PREFIX=/opt/local by default
$ make test       # 56 tests, headless under clautolisp

2. Use it

(load "/opt/local/share/autolisp/alpm.lsp")
(alpm-register-directory "/home/pjb/lisp" nil)
(alpm-load-system "geometry" nil)

The complete walkthrough — exports, encodings, .prj import/export, and the full function reference — is the user manual: read it here as a single page or paginated, one section per page. It also installs as an Info page (info alpm) and ships as HTML and PDF alongside the sources. Prefer a packaged download to a checkout? Get it from the releases page.

Part of the Toolchain

ALPM is a building block, not an island.

clautolisp

Load and test your ALPM systems headlessly, with no CAD installed — alpm-load-system behaves identically there as on AutoCAD or BricsCAD, which is what makes an ALPM system's CI story possible at all.

ergo

Ogamita's git-native package manager drives its AutoLISP builder through ALPM: point ergo at a repository, and it fetches the sources and hands them to ALPM to load in dependency order.

Licensing

ALPM is free software, free to use, study, modify, and redistribute.

GPL-3.0

Released under the GNU General Public License, version 3. No dual licensing, no commercial tier — the full text ships as LICENSE in the repository.

Questions & consulting

Bug reports and merge requests are welcome on GitLab. For integration help, AutoLISP tooling work, or a support arrangement, write to Ogamita.