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.
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.
Built for AutoLISP code bases that have outgrown one folder of loose .lsp files and a prayer about load order.
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.
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.
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.
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.
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.
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.
Current state of the 1.0.0 release.
alpm.lsp, concatenated by itself, one load.Describe a system once. Load it by name, on any engine, forever after.
(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")))))
(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
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. |
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.
Build from source and install into any prefix.
$ git clone https://gitlab.com/ogamita/alpm.git $ cd alpm $ make install # PREFIX=/opt/local by default $ make test # 56 tests, headless under clautolisp
(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.
ALPM is a building block, not an island.
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.
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.
ALPM is free software, free to use, study, modify, and redistribute.
Released under the GNU General Public License, version 3. No dual licensing, no commercial tier — the full text ships as LICENSE in the repository.
Bug reports and merge requests are welcome on GitLab. For integration help, AutoLISP tooling work, or a support arrangement, write to Ogamita.