Skip to content

Update for libquil on modern sbcl-librarian - #68

Draft
BatmanAoD wants to merge 8 commits into
mainfrom
sbcl-librarian-runtime
Draft

Update for libquil on modern sbcl-librarian#68
BatmanAoD wants to merge 8 commits into
mainfrom
sbcl-librarian-runtime

Conversation

@BatmanAoD

@BatmanAoD BatmanAoD commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Resolves #69

libquil no longer ships a core the caller initializes explicitly; the libsbcl_librarian runtime brings Lisp up from a constructor when it loads, and libquil is the generated bindings on top. The core-file search and the init(core) call are gone, along with LIBQUIL_CORE_PATH and the CoreFileNotFound error; init_libquil now only makes libquil's symbols globally visible, which the Python extension still needs.

Errors move to the runtime's API: lisp_err_t and get_error_message replace libquil_error_t and libquil_error. The generated header declares real functions rather than function pointers, so bindgen no longer wraps them in Option and the .unwrap() calls on binding functions are dropped.

build.rs links libsbcl_librarian alongside libquil, feeds bindgen the runtime's header and include directory (libquil.h now includes sbcl_librarian_err.h), and accepts LIBQUIL_LIB_PATH for installs that keep headers and libraries in separate directories.

The macOS __PAGEZERO link argument is dropped: the Lisp image is mapped by the runtime library now, not by the consumer executable.

@BatmanAoD
BatmanAoD force-pushed the sbcl-librarian-runtime branch from a1d4b5d to e323a96 Compare August 12, 2026 03:00
libquil no longer ships a core the caller initializes explicitly; the
libsbcl_librarian runtime brings Lisp up from a constructor when it loads, and
libquil is the generated bindings on top. The core-file search and the init(core)
call are gone, along with LIBQUIL_CORE_PATH and the CoreFileNotFound error;
init_libquil now only makes libquil's symbols globally visible, which the Python
extension still needs.

Errors move to the runtime's API: lisp_err_t and get_error_message replace
libquil_error_t and libquil_error. The generated header declares real functions
rather than function pointers, so bindgen no longer wraps them in Option and the
.unwrap() calls on binding functions are dropped.

build.rs links libsbcl_librarian alongside libquil, feeds bindgen the runtime's
header and include directory (libquil.h now includes sbcl_librarian_err.h), and
accepts LIBQUIL_LIB_PATH for installs that keep headers and libraries in separate
directories. It also reports its own errors, since Cargo prints a build script's
error with Debug, and says plainly when it finds a libquil too old to carry the
runtime headers.

CI installs $LIBQUIL_VERSION, which has to be a libquil release from after this
change, and the macOS job moves off the Intel runner: libquil no longer publishes
Intel macOS binaries.

The macOS __PAGEZERO link argument is dropped: the Lisp image is mapped by the
runtime library now, not by the consumer executable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@BatmanAoD
BatmanAoD force-pushed the sbcl-librarian-runtime branch 2 times, most recently from 6f68ec1 to 5237131 Compare August 12, 2026 03:28
Author/email change that was present in the working copy; separated out so it is
not mixed into unrelated CI work.
@BatmanAoD
BatmanAoD force-pushed the sbcl-librarian-runtime branch 3 times, most recently from 8ede176 to 585c154 Compare August 12, 2026 03:33
libquil-sys is only usable with a matching libquil, so an ABI change has to be
published somewhere testable before either side can be released for real. There was
no way to do that: knope.toml defined only a 'release' workflow, and the dispatch
input listing it was not a choice input, so its options list was inert.

Add a 'prerelease' knope workflow that cuts an -rc version and marks the GitHub
release as a prerelease, which still triggers the existing crates.io publish. Cargo
never resolves a prerelease unless asked for by name, so it is safe to publish
alongside stable versions. Verified with knope 0.10.0 and 0.11.0: the config
validates and the workflow dry-runs to 0.5.0-rc.0.

The test workflow now takes the libquil release to install, and the repository and
ref to fetch install.sh from -- they have to move together, because the installer
that ships with a release knows which files that release contains, and the move to
modern sbcl-librarian added the runtime directory. They currently point at
v0.4.0-rc.0 in a fork, since the libquil change is not merged; revert to
rigetti/libquil and a stable version once it lands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@BatmanAoD
BatmanAoD force-pushed the sbcl-librarian-runtime branch from 585c154 to a3d2917 Compare August 12, 2026 04:13
BatmanAoD and others added 2 commits August 12, 2026 04:29
Cutting a prerelease from a branch produced a tag pointing at the wrong code.
knope 0.10/0.11 create the GitHub release against the default branch, so the
version bump landed on the branch while the tag landed on main -- and the publish
job, which checks out whatever that tag resolves to, then tried to republish main's
already-released version:

    error: crate libquil-sys@0.4.2 already exists on crates.io index

Adopt the setup rigetti-pyo3 arrived at (36a1850, 9b5235c, 3505971):

- knope 0.23, which tags the ref being released and takes --prerelease-label, so
  the separate prerelease workflow in knope.toml is no longer needed;
- the ref decides what gets cut: main releases, anything else prereleases;
- check out ${{ github.ref }} so a release acts on the dispatched branch;
- pass the token to the Release step through GITHUB_TOKEN, which is how it
  authenticates;
- dry-run the release on pull requests, so a broken config is visible before it is
  dispatched.

The publish job now checks out the release tag explicitly, so it always publishes
exactly what was tagged rather than whatever the target commitish points at.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@BatmanAoD
BatmanAoD force-pushed the sbcl-librarian-runtime branch from 350b6e1 to 545d05d Compare August 12, 2026 05:12
BatmanAoD and others added 3 commits August 12, 2026 05:12
get_header_path and get_lib_search_paths read LIBQUIL_SRC_PATH, LIBQUIL_LIB_PATH and
C_INCLUDE_PATH with option_env!, which resolves when the build script is *compiled*.
The chosen paths were baked into the compiled build script, and nothing told cargo the
values mattered, so pointing the build at a different libquil after the first build
silently kept linking the old one until a manual cargo clean.

Read them with env::var at runtime and emit cargo:rerun-if-env-changed for each, so a
changed value re-runs the build script.

Also fix the rerun-on-header-change directive, which was spelled
cargo:rustc-rerun-if-changed -- not a directive cargo recognizes, so a modified
libquil.h did not trigger a rebuild of the bindings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Get this crate working on Apple Silicon (aarch64/arm64 macos)

1 participant