Skip to content

Commit 78196e1

Browse files
docs: update README and DEVELOPMENT.md to reflect current repo structure (#14)
Agent-Logs-Url: https://github.com/Quantinuum/hugrverse-env/sessions/0be68f6f-4b24-4d08-9e80-f28c454e0612 Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jake-arkinstall <65358059+jake-arkinstall@users.noreply.github.com>
1 parent 494f8f0 commit 78196e1

File tree

2 files changed

+141
-79
lines changed

2 files changed

+141
-79
lines changed

DEVELOPMENT.md

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ sandboxed environment that CI uses.
1010
(e.g. [QEMU binfmt](https://github.com/multiarch/qemu-user-static) or
1111
Docker Desktop's built-in emulation). Building natively is strongly
1212
recommended for AArch64 because emulation will be very slow for a full
13-
LLVM build.
13+
LLVM or tket build.
1414

1515
## Linux (manylinux) builds
1616

@@ -19,6 +19,9 @@ images. They do not embed the build scripts; instead the repository root is
1919
mounted at `/host` at runtime so that edits are picked up immediately without
2020
rebuilding the image.
2121

22+
Each build script lives at `deps/<dependency>/<platform>.sh` and takes a single
23+
argument: the path where the output `.tar.gz` should be written.
24+
2225
### x86_64
2326

2427
```bash
@@ -28,15 +31,18 @@ docker build \
2831
-t hugrverse-env-manylinux-x86_64 \
2932
.
3033

31-
# 2. Run the full build (output lands in ./artifacts/)
34+
# 2. Run a single dependency build (e.g. llvm)
3235
mkdir -p artifacts
3336
docker run --rm \
3437
-v "$(pwd):/host" \
3538
hugrverse-env-manylinux-x86_64 \
36-
/host/builds/manylinux_2_28_x86_64/build.sh \
37-
/host/artifacts/hugrverse_env_manylinux_2_28_x86_64.tar.gz
39+
bash /host/deps/llvm/manylinux_2_28_x86_64.sh \
40+
/host/artifacts/hugrenv-llvm-manylinux_2_28_x86_64.tar.gz
3841
```
3942

43+
Replace `llvm` with `tket` (or any other dependency) to build that component
44+
instead.
45+
4046
### AArch64 (native AArch64 host recommended)
4147

4248
```bash
@@ -49,8 +55,8 @@ mkdir -p artifacts
4955
docker run --rm \
5056
-v "$(pwd):/host" \
5157
hugrverse-env-manylinux-aarch64 \
52-
/host/builds/manylinux_2_28_aarch64/build.sh \
53-
/host/artifacts/hugrverse_env_manylinux_2_28_aarch64.tar.gz
58+
bash /host/deps/llvm/manylinux_2_28_aarch64.sh \
59+
/host/artifacts/hugrenv-llvm-manylinux_2_28_aarch64.tar.gz
5460
```
5561

5662
> **Tip:** pass `-e VERBOSE=1` to enable verbose output from build sub-steps,
@@ -65,56 +71,66 @@ build:
6571
docker run --rm -it \
6672
-v "$(pwd):/host" \
6773
hugrverse-env-manylinux-x86_64 \
68-
-c 'cd /host && bash'
74+
bash
6975
```
7076

71-
You can then run individual sub-scripts (e.g.
72-
`bash builds/manylinux_2_28_x86_64/llvm/build.sh`) to test in isolation.
77+
You can then run individual scripts (e.g.
78+
`bash /host/deps/llvm/manylinux_2_28_x86_64.sh /tmp/hugrenv-llvm-manylinux_2_28_x86_64.tar.gz`)
79+
to test in isolation.
7380

7481
## macOS builds
7582

76-
macOS build scripts run natively; no Docker is needed.
83+
macOS build scripts run natively; no Docker is needed. The `MACOSX_DEPLOYMENT_TARGET`
84+
environment variable should be set to `11.0` to match what CI uses.
7785

7886
```bash
87+
export MACOSX_DEPLOYMENT_TARGET=11.0
88+
7989
# ARM64
80-
bash builds/macosx_11_0_arm64/build.sh /tmp/hugrverse_env_macosx_11_0_arm64.tar.gz
90+
bash deps/llvm/macosx_11_0_aarch64.sh /tmp/hugrenv-llvm-macosx_11_0_aarch64.tar.gz
8191

8292
# x86_64 (Intel Mac)
83-
bash builds/macosx_11_0_x86_64/build.sh /tmp/hugrverse_env_macosx_11_0_x86_64.tar.gz
93+
bash deps/llvm/macosx_11_0_x86_64.sh /tmp/hugrenv-llvm-macosx_11_0_x86_64.tar.gz
8494
```
8595

86-
The scripts will install any missing dependencies via Homebrew.
96+
Replace `llvm` with `tket` to build the tket dependency. The scripts will
97+
install any missing dependencies via Homebrew.
8798

8899
## Windows builds
89100

90-
Open a **Developer PowerShell for VS 2022** (or run `.\builds\win_amd64\build.ps1`
91-
from a terminal that already has the MSVC environment loaded):
101+
Windows scripts are standard Bash scripts that must be run from a shell that
102+
has the MSVC environment loaded (e.g. Git Bash launched from a **Developer
103+
Command Prompt for VS 2022**, or after sourcing `vcvars64.bat`). CI uses the
104+
`ilammy/msvc-dev-cmd` action to set this up automatically.
92105

93-
```powershell
94-
.\builds\win_amd64\build.ps1 -OutputPath C:\Temp\hugrverse_env_win_amd64.zip
106+
```bash
107+
bash deps/llvm/win_amd64.sh /tmp/hugrenv-llvm-win_amd64.tar.gz
108+
bash deps/tket/win_amd64.sh /tmp/hugrenv-tket-win_amd64.tar.gz
95109
```
96110

97-
> The MSVC environment can be loaded in a regular PowerShell session with the
98-
> `ilammy/msvc-dev-cmd` action logic, or by sourcing
111+
> The MSVC environment can be loaded in a regular PowerShell session by
112+
> sourcing
99113
> `"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"`.
100114
101-
## Adding a new component
115+
## Adding a new dependency
102116

103-
1. Create `builds/<platform>/<component>/build.sh` (or `.ps1`).
104-
2. Source it from the platform's parent `build.sh` / `build.ps1`.
105-
3. Test locally using the methods above before opening a PR.
106-
4. Update `README.md` to document the new component.
117+
1. Create a `deps/<dependency>/` directory with a `<platform>.sh` script for
118+
each supported platform. Each script must accept the output tarball path as
119+
its first argument.
120+
2. Test locally using the methods above before opening a PR.
121+
3. Update `README.md` to document the new component.
107122

108123
## Verifying the archive
109124

110125
After a local build, inspect the archive to confirm its contents:
111126

112127
```bash
113128
# Linux / macOS
114-
tar -tzf artifacts/hugrverse_env_manylinux_2_28_x86_64.tar.gz | head -20
129+
tar -tzf artifacts/hugrenv-llvm-manylinux_2_28_x86_64.tar.gz | head -20
115130

116131
# Windows
117-
unzip -l artifacts\hugrverse_env_win_amd64.zip | head -20
132+
tar -tzf /tmp/hugrenv-llvm-win_amd64.tar.gz | head -20
118133
```
119134

120-
Installed LLVM binaries should appear under `opt/llvm/bin/` in the archive.
135+
LLVM binaries should appear under `hugrverse/bin/` in the archive; tket
136+
libraries under `hugrverse/lib/`.

README.md

Lines changed: 98 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,81 +3,127 @@
33
CI environment bootstrapping for hugrverse projects.
44

55
This repository builds and releases pre-compiled tooling environments used by
6-
other repositories in the Quantinuum hugrverse. Each release contains a
7-
compressed archive (`.tar.gz` or `.zip`) of pre-built tools for a specific
8-
target platform. Downstream projects download these archives during their CI
9-
bootstrap phase so that they never need to compile heavyweight dependencies
10-
from scratch.
6+
other repositories in the Quantinuum hugrverse. The goal is to provide
7+
libraries that are as compatible as possible across the platforms that matter
8+
most to Rust/Python build pipelines. On Linux, libraries are built inside
9+
[manylinux 2.28](https://github.com/pypa/manylinux) containers, giving broad
10+
binary compatibility across a wide range of distributions. On macOS the
11+
deployment target is set to 11.0.
12+
13+
Each release attaches a compressed archive (`hugrenv-<dep>-<platform>.tar.gz`)
14+
for every supported dependency/platform combination, plus a `hugrenv.lock` file
15+
that records the release version and the Nix-style SHA-256 hash of every
16+
archive.
1117

1218
## What is built
1319

1420
| Component | Version | Description |
1521
|-----------|---------|-------------|
1622
| LLVM | 21.1.8 | Clang + LLD + LLVM core libraries |
23+
| tket | 2.16.0 | Quantinuum tket quantum compiler + C API |
1724

1825
## Supported platforms
1926

20-
| Platform tag | Runner | Archive format |
21-
|---------------------------|-------------------------------|----------------|
22-
| `manylinux_2_28_x86_64` | Docker `quay.io/pypa/manylinux_2_28_x86_64` on `ubuntu-latest` | `.tar.gz` |
23-
| `manylinux_2_28_aarch64` | Docker `quay.io/pypa/manylinux_2_28_aarch64` on `ubuntu-24.04-arm` | `.tar.gz` |
24-
| `macosx_11_0_aarch64` | `macos-14` | `.tar.gz` |
25-
| `macosx_11_0_x86_64` | `macos-15-intel` | `.tar.gz` |
26-
| `win_amd64` | `windows-latest` + MSVC | `.zip` |
27+
| Platform tag | Runner | Notes |
28+
|---------------------------|-----------------------------------------------------------------|-------|
29+
| `manylinux_2_28_x86_64` | Docker `quay.io/pypa/manylinux_2_28_x86_64` on `ubuntu-latest` | manylinux 2.28 — broad Linux compatibility |
30+
| `manylinux_2_28_aarch64` | Docker `quay.io/pypa/manylinux_2_28_aarch64` on `ubuntu-24.04-arm` | manylinux 2.28 — broad Linux compatibility |
31+
| `macosx_11_0_aarch64` | `macos-14` | `MACOSX_DEPLOYMENT_TARGET=11.0` |
32+
| `macosx_11_0_x86_64` | `macos-15-intel` | `MACOSX_DEPLOYMENT_TARGET=11.0` |
33+
| `win_amd64` | `windows-latest` + MSVC | |
34+
35+
## Using hugrverse-env in your repository
36+
37+
### 1. Obtain a `hugrenv.lock` file
38+
39+
Every [GitHub release](https://github.com/Quantinuum/hugrverse-env/releases)
40+
attaches a `hugrenv.lock` file alongside the compiled archives. Download the
41+
lock file for the version you want to pin and **commit it to your repository**
42+
(e.g. at the repository root as `hugrenv.lock`). The lock file records the
43+
release version and a content hash for every archive so downstream workflows
44+
can verify what they download.
45+
46+
### 2. Install hugrenv packages in GitHub Actions
47+
48+
Use the `.github/actions/install-hugrenv` composite action from this
49+
repository. It reads your committed `hugrenv.lock`, detects the current runner
50+
platform, downloads the requested packages from the matching release, extracts
51+
them, and sets the relevant environment variables (`LLVM_SYS_211_PREFIX`,
52+
`LIBCLANG_PATH`, `TKET_C_API_PATH`, `LD_LIBRARY_PATH` / `DYLD_LIBRARY_PATH`,
53+
`PATH`, etc.) for subsequent steps.
54+
55+
```yaml
56+
- name: Install hugrenv
57+
uses: Quantinuum/hugrverse-env/.github/actions/install-hugrenv@main
58+
with:
59+
packages: llvm,tket # comma-separated; defaults to "llvm,tket"
60+
lockfile: hugrenv.lock # relative path to your lock file; default is "hugrenv.lock"
61+
```
62+
63+
The action supports all five platforms listed above and works on Linux, macOS,
64+
and Windows runners without any additional setup.
2765
2866
## Repository layout
2967
3068
```
31-
builds/
32-
<platform>/ # One directory per target platform
33-
build.sh # Parent script: builds all components, then bundles output
34-
version.txt # Managed by release-please; records the current version
35-
llvm/
36-
build.sh # Builds LLVM from source into /opt/llvm (or C:\hugrverse\llvm)
69+
deps/
70+
llvm/
71+
manylinux_2_28_x86_64.sh # Builds LLVM for each platform
72+
manylinux_2_28_aarch64.sh
73+
macosx_11_0_aarch64.sh
74+
macosx_11_0_x86_64.sh
75+
win_amd64.sh
76+
tket/
77+
manylinux_2_28_x86_64.sh # Builds tket + C API for each platform
78+
manylinux_2_28_aarch64.sh
79+
macosx_11_0_aarch64.sh
80+
macosx_11_0_x86_64.sh
81+
win_amd64.sh
3782
docker/
3883
manylinux_2_28_x86_64.Dockerfile # Local-testing image for x86_64 Linux
3984
manylinux_2_28_aarch64.Dockerfile # Local-testing image for AArch64 Linux
4085
.github/
86+
actions/
87+
install-hugrenv/
88+
action.yml # Composite action: reads lock file, downloads & installs packages
4189
workflows/
42-
build.yml # Builds each platform; uploads artifact on release
43-
release-please.yml # Creates release PRs and tags via release-please
44-
release-please-config.json # Monorepo release-please configuration
45-
.release-please-manifest.json # Current version for each package
90+
build.yml # Builds changed targets on PRs; uploads artifacts
91+
merge.yml # Promotes merged-PR artifacts to main-* on merge to main
92+
release.yml # Bundles main-* artifacts, generates hugrenv.lock, publishes release
4693
```
4794

4895
## How CI works
4996

50-
1. **Build workflow** (`build.yml`) — triggered on every pull request, push to
51-
`main`, published GitHub release, and manually via `workflow_dispatch`.
97+
1. **Build** (`build.yml`) — triggered on pull requests and manually via
98+
`workflow_dispatch`.
99+
* On a PR, only scripts that changed since the base commit are built.
52100
* Linux targets are built inside the official `quay.io/pypa/manylinux_2_28_*`
53-
Docker images to ensure binary compatibility with the manylinux ABI.
54-
* macOS targets run natively on the appropriate GitHub-hosted runners.
55-
* The Windows target runs with the MSVC toolchain on `windows-latest`.
56-
* On a release event the resulting archives are also uploaded directly to
57-
the GitHub release.
58-
59-
2. **Release workflow** (`release-please.yml`) — triggered on every push to
60-
`main`.
61-
* Uses [release-please](https://github.com/googleapis/release-please) in
62-
monorepo mode with five independent packages, one per platform.
63-
* When commits affecting a platform directory are merged to `main`,
64-
release-please opens a release PR for that platform.
65-
* Merging the release PR creates a tag (e.g.
66-
`hugrverse-env-manylinux_2_28_x86_64-v1.2.3`) and a GitHub release.
67-
* The build workflow then triggers on the published release and attaches the
68-
compiled archive.
69-
70-
## Adding a new component
71-
72-
1. Create a `builds/<platform>/<component>/build.sh` (or `.ps1` for Windows)
73-
that downloads, compiles, and installs the component to `/opt/<component>`
74-
(or `C:\hugrverse\<component>` on Windows).
75-
2. Call the new script from `builds/<platform>/build.sh` and, if needed, add
76-
the install directory to the `tar` / `Compress-Archive` invocation that
77-
creates the bundle.
78-
3. Repeat for every platform that should include the component.
101+
Docker images to ensure manylinux binary compatibility.
102+
* macOS targets run natively; `MACOSX_DEPLOYMENT_TARGET` is set to `11.0`.
103+
* The Windows target uses the MSVC toolchain via `ilammy/msvc-dev-cmd`.
104+
* Each built archive is uploaded as a PR artifact named
105+
`pr-<head-sha>-<dep>-<platform>`.
106+
107+
2. **Merge** (`merge.yml`) — triggered when a PR is merged to `main`.
108+
* Finds the PR build artifacts by head SHA and re-uploads them as
109+
`main-<dep>-<platform>` artifacts (retained 90 days).
110+
111+
3. **Release** (`release.yml`) — triggered manually via `workflow_dispatch`.
112+
* Downloads all `main-*` promoted artifacts.
113+
* Generates a `hugrenv.lock` containing the version and Nix-style SHA-256
114+
hashes for every archive.
115+
* Creates a GitHub release tagged `v<version>` and attaches all archives
116+
plus the lock file.
117+
118+
## Adding a new dependency
119+
120+
1. Create `deps/<dependency>/` and add a `<platform>.sh` script for each
121+
supported platform. Each script accepts an output tarball path as its first
122+
argument and produces a `hugrenv-<dependency>-<platform>.tar.gz`.
123+
2. Repeat for every platform that should include the dependency.
124+
3. Update this README to document the new component.
79125

80126
## Local development
81127

82-
See [DEVELOPMENT.md](DEVELOPMENT.md) for instructions on testing changes
83-
locally using Docker.
128+
See [DEVELOPMENT.md](DEVELOPMENT.md) for instructions on testing build-script
129+
changes locally using Docker (Linux) or running scripts natively (macOS/Windows).

0 commit comments

Comments
 (0)