Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ jobs:
- name: root suid tar
run: sudo chown root /bin/tar && sudo chmod u+s /bin/tar

- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
path: "libquil"

- name: Cache SBCL
id: cache-sbcl
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
/usr/local/lib/libsbcl.so
Expand Down Expand Up @@ -49,14 +49,17 @@ jobs:

- name: Pull Lisp dependencies
run: |
git clone https://github.com/notmgsk/quilc.git $GITHUB_WORKSPACE/quilc && cd $GITHUB_WORKSPACE/quilc && git checkout bffea7fdb972cc9b3a50b790246b6a3143c88c7a
git clone https://github.com/quil-lang/quilc.git $GITHUB_WORKSPACE/quilc && cd $GITHUB_WORKSPACE/quilc && git checkout 3d83b665b3addc33be2f696b1cdebc0c4c5a04f9
git clone https://github.com/quil-lang/qvm.git $GITHUB_WORKSPACE/qvm && cd $GITHUB_WORKSPACE/qvm && git checkout 4617625cb6053b1adfd3f7aea9cd2be328b225f6
git clone https://github.com/quil-lang/magicl.git $GITHUB_WORKSPACE/magicl
git clone https://github.com/stylewarning/cl-permutation $GITHUB_WORKSPACE/cl-permutation
git clone https://github.com/quil-lang/sbcl-librarian.git $GITHUB_WORKSPACE/sbcl-librarian && cd $GITHUB_WORKSPACE/sbcl-librarian && git checkout 04f7e390c777084ac43b8df9e90593a041da2381

- name: Install quilc dependencies
run: sudo apt update && sudo apt install -y libblas-dev libffi-dev libffi7 liblapack-dev libz-dev gfortran
# libffi-dev pulls in whichever libffi runtime the image ships; naming
# it explicitly breaks whenever the runner image moves (libffi7 does not
# exist on ubuntu 24.04, which ubuntu-latest now resolves to).
run: sudo apt update && sudo apt install -y libblas-dev libffi-dev liblapack-dev libz-dev gfortran

- name: Build libquil.so
run: |
Expand All @@ -76,32 +79,34 @@ jobs:
mkdir -p $GITHUB_WORKSPACE/artifacts/libquil && cp $GITHUB_WORKSPACE/libquil/libquil.h $GITHUB_WORKSPACE/libquil/libquil.so $GITHUB_WORKSPACE/libquil/libquil.core /usr/local/lib/libsbcl.so $GITHUB_WORKSPACE/artifacts/libquil

- name: Store artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: linux-amd64
path: ${{ github.workspace }}/artifacts/*
# A directory (not a glob): upload-artifact v4 preserves structure
# relative to it, keeping the libquil/ prefix the release job unzips.
path: ${{ github.workspace }}/artifacts

build-macos:
name: Build libquil.dylib
build-macos-arm:
name: Build Apple-Silicon libquil.dylib
runs-on: macos-latest

steps:

- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
path: "libquil"

- name: Cache SBCL
id: cache-sbcl-macos
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
/usr/local/lib/libsbcl.so
/usr/local/lib/sbcl
/usr/local/bin/sbcl
~/quicklisp
~/.sbclrc
key: ${{ runner.os }}-build-${{ hashFiles('**/macos-versions' )}}
key: ${{ runner.os }}-${{ runner.arch }}-build-${{ hashFiles('**/macos-versions' )}}

- uses: Homebrew/actions/setup-homebrew@master
name: Setup homebrew
Expand All @@ -110,7 +115,7 @@ jobs:
name: Install SBCL, libraries, and quicklisp
run: |
brew install sbcl git
git clone --branch x86-null-tn https://git.code.sf.net/p/sbcl/sbcl /tmp/sbcl
git clone --branch sbcl-2.2.4 https://git.code.sf.net/p/sbcl/sbcl /tmp/sbcl
cd /tmp/sbcl && sudo sh make.sh --without-compact-instance-header --without-immobile-space --without-immobile-code && sudo sh make-shared-library.sh
brew remove -f sbcl
sudo sh install.sh
Expand All @@ -126,7 +131,7 @@ jobs:

- name: Pull Lisp dependencies
run: |
git clone https://github.com/notmgsk/quilc.git $GITHUB_WORKSPACE/quilc && cd $GITHUB_WORKSPACE/quilc && git checkout bffea7fdb972cc9b3a50b790246b6a3143c88c7a
git clone https://github.com/quil-lang/quilc.git $GITHUB_WORKSPACE/quilc && cd $GITHUB_WORKSPACE/quilc && git checkout 3d83b665b3addc33be2f696b1cdebc0c4c5a04f9
git clone https://github.com/quil-lang/qvm.git $GITHUB_WORKSPACE/qvm && cd $GITHUB_WORKSPACE/qvm && git checkout 4617625cb6053b1adfd3f7aea9cd2be328b225f6
git clone https://github.com/quil-lang/magicl.git $GITHUB_WORKSPACE/magicl
git clone https://github.com/stylewarning/cl-permutation $GITHUB_WORKSPACE/cl-permutation
Expand Down Expand Up @@ -157,7 +162,10 @@ jobs:
mkdir -p $GITHUB_WORKSPACE/artifacts/libquil && cp $GITHUB_WORKSPACE/libquil/libquil.h $GITHUB_WORKSPACE/libquil/libquil.dylib $GITHUB_WORKSPACE/libquil/libquil.core /usr/local/lib/libsbcl.so $GITHUB_WORKSPACE/artifacts/libquil

- name: Store artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: macos
path: ${{ github.workspace }}/artifacts/*
name: macos-arm64
# A directory (not a glob): upload-artifact v4 preserves structure
# relative to it, keeping the libquil/ prefix the release job unzips.
path: ${{ github.workspace }}/artifacts

25 changes: 14 additions & 11 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,38 @@ jobs:
git config --global user.name "${{ github.triggering_actor }}"
git config --global user.email "${{ github.triggering_actor }}@users.noreply.github.com"

- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0

# Each artifact is downloaded into its own directory: the two macOS
# artifacts contain identically named files, so a shared directory would
# have one overwrite the other.
- name: Download linux artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: linux-amd64
path: artifacts/
path: artifacts/linux-amd64/

- name: Archive linux artifacts
run: |
cd artifacts && zip linux-amd64.zip libquil/libsbcl.so libquil/libquil.so libquil/libquil.core libquil/libquil.h
cd artifacts/linux-amd64 && zip ../linux-amd64.zip libquil/libsbcl.so libquil/libquil.so libquil/libquil.core libquil/libquil.h

- name: Download macos artifacts
uses: actions/download-artifact@v3
- name: Download macos arm64 artifacts
uses: actions/download-artifact@v4
with:
name: macos
path: artifacts/
name: macos-arm64
path: artifacts/macos-arm64/

- name: Archive linux artifacts
- name: Archive macos arm64 artifacts
run: |
cd artifacts && zip macos.zip libquil/libsbcl.so libquil/libquil.dylib libquil/libquil.core libquil/libquil.h
cd artifacts/macos-arm64 && zip ../macos-arm64.zip libquil/libsbcl.so libquil/libquil.dylib libquil/libquil.core libquil/libquil.h

- name: List artifacts
run: |
ls -R artifacts/
unzip -l artifacts/linux-amd64.zip
unzip -l artifacts/macos.zip
unzip -l artifacts/macos-arm64.zip

- name: Install Knope
uses: knope-dev/action@v2.0.0
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ libquil.c
libquil.core
libquil.h
libquil.so
libquil.dylib
libquil.py
60 changes: 57 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
.PHONY: all clean

OS:=$(shell uname -s)
OS := $(shell uname -s)

SBCL ?= sbcl

ifeq ($(OS), Darwin)
LIBQUIL_TARGET = libquil.dylib
CCFLAGS = -dynamiclib
Expand All @@ -9,13 +12,64 @@ else
CCFLAGS = -shared
endif

# The library needs to embed the SBCL runtime. `make.sh` does not build a
# linkable runtime, so it has to be produced separately by running
# `make-shared-library.sh` in the SBCL source tree, and neither `install.sh` nor
# most package managers install the result. Look in the usual places for it, and
# let the user point at it directly with e.g. `make LIBSBCL=/path/to/libsbcl.a`.
#
# Which file to expect depends on the platform: on arm64 macOS the SBCL runtime
# is only built as a static archive (see SBCL's Config.arm64-darwin), so a
# shared libsbcl does not exist there at all.
SBCL_CORE_DIR := $(dir $(shell $(SBCL) --noinform --no-sysinit --no-userinit --non-interactive \
--eval '(princ (namestring sb-ext:*core-pathname*))' 2>/dev/null))
LIBSBCL_SEARCH_DIRS := $(SBCL_HOME) $(SBCL_CORE_DIR) /usr/local/lib /usr/lib /opt/homebrew/lib
LIBSBCL_CANDIDATES := \
$(foreach dir,$(LIBSBCL_SEARCH_DIRS),\
$(dir)/libsbcl.a $(dir)/libsbcl.dylib $(dir)/libsbcl.so)

LIBSBCL ?= $(firstword $(wildcard $(LIBSBCL_CANDIDATES)))

# A static runtime must be linked whole: the entry points the generated
# libquil.c calls are reached only through the core, so without this the linker
# drops most of the archive. Its own dependencies have to be named explicitly
# too, since an archive records none. A shared runtime carries both properties
# already and just needs to be linked normally.
SBCL_STATIC_DEPS ?= $(shell pkg-config --libs libzstd 2>/dev/null || echo -lzstd) -lm -ldl -lpthread

ifeq ($(suffix $(LIBSBCL)), .a)
ifeq ($(OS), Darwin)
LIBSBCL_LDFLAGS = -Wl,-force_load,$(LIBSBCL) $(SBCL_STATIC_DEPS)
else
LIBSBCL_LDFLAGS = -Wl,--whole-archive $(LIBSBCL) -Wl,--no-whole-archive $(SBCL_STATIC_DEPS)
endif
else ifeq ($(OS), Darwin)
# Link by path rather than -lsbcl: make-shared-library.sh names its output
# libsbcl.so even on macOS, and the -l flag only ever looks for libsbcl.dylib or
# libsbcl.a.
LIBSBCL_LDFLAGS = $(LIBSBCL)
else
LIBSBCL_LDFLAGS = -L$(dir $(LIBSBCL)) -lsbcl
endif

all: $(LIBQUIL_TARGET)

libquil.core libquil.c libquil.h libquil.py: src/libquil.lisp src/qvm/*.lisp src/quilc/*.lisp
sbcl --dynamic-space-size 8192 --load "src/build-image.lisp"
$(SBCL) --dynamic-space-size 8192 --load "src/build-image.lisp"

$(LIBQUIL_TARGET): libquil.core libquil.c
gcc $(CCFLAGS) -o $@ libquil.c -lsbcl
ifeq ($(LIBSBCL),)
@echo "error: no linkable SBCL runtime found." >&2
@echo "Searched for libsbcl.a, libsbcl.dylib and libsbcl.so in:" >&2
@$(foreach dir,$(LIBSBCL_SEARCH_DIRS),echo " $(dir)" >&2;)
@echo "" >&2
@echo "Build one from an SBCL source tree of the SAME version as $(SBCL):" >&2
@echo " sh make.sh --with-sb-linkable-runtime && sh make-shared-library.sh" >&2
@echo "then point make at the result, e.g.:" >&2
@echo " make LIBSBCL=/path/to/sbcl/src/runtime/libsbcl.a" >&2
@exit 1
endif
$(CC) $(CCFLAGS) -o $@ libquil.c $(LIBSBCL_LDFLAGS)

clean:
rm -f libquil.so libquil.c libquil.h libquil.core libquil.py libquil.dylib example
45 changes: 42 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
We provide pre-built binaries for the following systems

- Linux x64 (tested specifically on Ubuntu)
- macOS x64
- macOS aarch64 (Apple Silicon)

Note that ARM is not yet supported on any of the above.
Intel macOS binaries are no longer published. Other platforms, including Intel
macOS, can be built from source — see [Building from
source](#building-from-source).

## Requirements

Expand All @@ -24,7 +26,7 @@ These libraries are required by `libquil`:
On systems which use `apt` to install packages (e.g. Ubuntu), these libraries can be installed with the command

```
sudo apt install libblas-dev libffi-dev libffi7 liblapack-dev libz-dev
sudo apt install libblas-dev libffi-dev liblapack-dev libz-dev
```

On systems which use `brew` to install packages (e.g macOS), these libraries can be installed with the command
Expand Down Expand Up @@ -59,6 +61,43 @@ replacing `<version-identifier>` with the desired version, e.g. `0.3.0`.

If you would like to manually install the library (for example in the case where you want to install the library to a non-standard location), find the appropriate version and operating system from the [releases page](https://github.com/rigetti/libquil/releases). Within the `.zip` archive you will find the library and header files that are required to use the library. Move these into your file system.

## Building from source

Building requires an SBCL that has a *linkable runtime* — a `libsbcl.a` or
`libsbcl.so`/`libsbcl.dylib` that gets embedded into the library. Neither
`make.sh` nor most package managers produce one (Homebrew's `sbcl` bottle, for
instance, does not), so it has to be built from an SBCL source tree of the same
version as the `sbcl` used for the rest of the build:

```bash
sh make.sh --with-sb-linkable-runtime && sh make-shared-library.sh && sh install.sh
```

`install.sh` places the runtime in SBCL's home directory, where the `Makefile`
finds it automatically. To use one from elsewhere, pass it explicitly:

```bash
make LIBSBCL=/path/to/sbcl/src/runtime/libsbcl.a
```

Note that on aarch64 macOS, SBCL only builds its runtime as the static
`libsbcl.a`; there is no shared `libsbcl.dylib` on that platform. The `Makefile`
handles either form.

The Lisp dependencies (`quilc`, `qvm`, `magicl`, `sbcl-librarian`) are expected
in your Quicklisp local-projects directory. Then:

```bash
make
```

### Linear algebra backend on aarch64 macOS

Homebrew's reference `lapack` computes incorrect eigenvectors on aarch64, which
surfaces as `Could not find diagonalizer for matrix ... after 16 attempts`
during compilation. Install OpenBLAS (`brew install openblas`) and ensure
`magicl` loads it in preference to `lapack`.

# C API Reference

## Libquil functions and types
Expand Down
26 changes: 20 additions & 6 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ err() {
exit 1
}

if [[ "$(uname -p)" =~ "arm" ]]; then
err "Unsupported CPU architecture: $(uname -p)."
fi

if [[ -n "${1-}" ]]
then
LIBQUIL_URL_PREFIX="https://github.com/rigetti/libquil/releases/download/v${1}"
Expand All @@ -19,13 +15,31 @@ else
fi

OS="$(uname)"
ARCH="$(uname -m)"
if [[ "${OS}" == "Linux" ]]
then
IS_LINUX=1
LIBQUIL_RELEASE_FILE="linux-amd64.zip"
case "${ARCH}" in
x86_64 | amd64)
LIBQUIL_RELEASE_FILE="linux-amd64.zip"
;;
*)
err "Unsupported CPU architecture for Linux: ${ARCH}. Only x86_64 is supported." \
"You can build libquil from source; see https://github.com/rigetti/libquil#building-from-source"
;;
esac
elif [[ "${OS}" == "Darwin" ]]
then
LIBQUIL_RELEASE_FILE="macos.zip"
case "${ARCH}" in
arm64 | aarch64)
LIBQUIL_RELEASE_FILE="macos-arm64.zip"
;;
*)
err "Unsupported CPU architecture for macOS: ${ARCH}. Only Apple Silicon (arm64) is supported." \
"Intel macOS builds are no longer published. You can build libquil from source; see" \
"https://github.com/rigetti/libquil#building-from-source"
;;
esac
else
err "Unsupported operating system. Supported operating systems are Linux and macOS."
fi
Expand Down
2 changes: 1 addition & 1 deletion knope.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ changelog = "CHANGELOG.md"
path = "artifacts/linux-amd64.zip"

[[package.assets]]
path = "artifacts/macos.zip"
path = "artifacts/macos-arm64.zip"

[[workflows]]
name = "release"
Expand Down
Loading
Loading