Skip to content

Commit 0c64621

Browse files
authored
chore: Fetch tket-c-api from conan remote (#1002)
This greatly simplifies the build! No setup is required anymore. Just `uv run cargo build` and you are good to go -- or `cargo build` with `conan` in your path. In addition, no C++ compilation should happen if you are on one of the supported platforms (Linux X86, Mac ARM, Mac X86 or Windows X86). As before, If you do not want to use `conan`, you just need to set `TKET_C_API_PATH` to point to the install folder of a compiled dynamic library of `tket-c-api`.
1 parent d609bf5 commit 0c64621

File tree

20 files changed

+154
-379
lines changed

20 files changed

+154
-379
lines changed

.github/actions/tket-c-api/action.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ runs:
3232
if: steps.cache.outputs.cache-hit != 'true'
3333
shell: bash
3434
run: |
35-
cd tket1-passes/tket-c-api
36-
PACKAGE_NAME="tket-c-api/$(conan inspect . --format=json | jq -r '.version')"
37-
CONAN_OUTPUT=$(conan create . --build=missing --options="$PACKAGE_NAME:shared=True" --format=json)
35+
cd tket1-passes
36+
CONAN_OUTPUT=$(conan install . --build=missing --options="tket-c-api/*:shared=True" --format=json)
3837
CONAN_LIB_FOLDER=$(echo "$CONAN_OUTPUT" | jq -r ".graph.nodes.\"1\".package_folder")
3938
cp -r $CONAN_LIB_FOLDER ${{ inputs.install-path }}
4039

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ jobs:
6464
uses: dtolnay/rust-toolchain@stable
6565
with:
6666
components: rustfmt, clippy
67+
# This step is not required, but speeds up the build by caching the tket-c-api library
68+
# The alternative is to install conan and remove the `TKET_C_API_PATH` env var
6769
- name: Install tket-c-api library
6870
uses: ./.github/actions/tket-c-api
6971
with:
@@ -169,6 +171,8 @@ jobs:
169171
uses: KyleMayes/install-llvm-action@v2
170172
with:
171173
version: ${{ env.LLVM_VERSION }}
174+
# This step is not required, but speeds up the build by caching the tket-c-api library
175+
# The alternative is to install conan and remove the `TKET_C_API_PATH` env var
172176
- name: Install tket-c-api library
173177
uses: ./.github/actions/tket-c-api
174178
with:
@@ -201,6 +205,8 @@ jobs:
201205
uses: KyleMayes/install-llvm-action@v2
202206
with:
203207
version: ${{ env.LLVM_VERSION }}
208+
# This step is not required, but speeds up the build by caching the tket-c-api library
209+
# The alternative is to install conan and remove the `TKET_C_API_PATH` env var
204210
- name: Install tket-c-api library
205211
uses: ./.github/actions/tket-c-api
206212
with:
@@ -235,6 +241,8 @@ jobs:
235241
uses: KyleMayes/install-llvm-action@v2
236242
with:
237243
version: ${{ env.LLVM_VERSION }}
244+
# This step is not required, but speeds up the build by caching the tket-c-api library
245+
# The alternative is to install conan and remove the `TKET_C_API_PATH` env var
238246
- name: Install tket-c-api library
239247
uses: ./.github/actions/tket-c-api
240248
with:

DEVELOPMENT.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,6 @@ devenv shell
2424
All the required dependencies should be available. You can automate loading the
2525
shell by setting up [direnv](https://devenv.sh/automatic-shell-activation/).
2626

27-
<!-- TODO: Remove once the pre-compiled binaries are available. -->
28-
Currently you will need to compile the tket C API manually. To do this, run:
29-
```bash
30-
just setup-tket-c-api
31-
```
32-
This step will be removed in the future, once the pre-compiled binaries are available.
33-
3427
### Manual setup
3528

3629
To setup the environment manually you will need:

justfile

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,10 @@ help:
44

55
# Prepare the environment for development, installing all the dependencies and
66
# setting up the pre-commit hooks.
7-
setup: setup-tket-c-api
7+
setup:
88
uv sync
99
[[ -n "${TKET_JUST_INHIBIT_GIT_HOOKS:-}" ]] || uv run pre-commit install -t pre-commit
1010

11-
# Configure the conan cache for tket-c-api.
12-
setup-tket-c-api:
13-
uv run conan remote add -f tket-libs https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs --index 0
14-
cd tket1-passes/tket-c-api && uv run conan create . --build=missing
15-
1611
# Run the pre-commit checks.
1712
check:
1813
uv run pre-commit run --all-files

tket1-passes/README.md

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,21 @@ API.
77

88
## Building instructions
99

10-
Building `tket1-passes` is done using `conan >= 2.0`. After installing `conan`,
11-
(`pip install conan` or use `pipx`), you must set up `conan` to use the
12-
artifactory containing the tket package:
13-
14-
```
15-
conan remote add tket-libs https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs --index 0
16-
```
17-
18-
For the time being, one extra step is required to export `tket-c-api` to the conan cache:
19-
20-
```
21-
cd tket-c-api && conan create . --build=missing"
22-
```
23-
24-
That's it! You can now build the library using `cargo build`.
10+
Building `tket1-passes` is done using `conan >= 2.0`. This will be installed
11+
automatically by `uv` if using the build tools `just` or `uv` (recommended; see
12+
[DEVELOPMENT.md](../DEVELOPMENT.md) for more detailed instructions). If you wish
13+
to run `cargo build` directly, make sure that `conan` is installed and available
14+
in your `PATH`.
2515

2616
If conan is unable to fetch all dependencies as pre-compiled binaries, you will
2717
also need standard C++ tooling to compile the dependencies (i.e. a reasonably
2818
recent version of cmake and a C++ compiler).
2919

20+
You can also eschew using conan altogether by setting the `TKET_C_API_PATH`
21+
environment variable to point to a pre-compiled version of the `tket-c-api`
22+
library. Note that this must be a dynamic library (the pre-built binaries on
23+
conan on the other hand are static libraries).
24+
3025
## Currently supported TKET1 features
3126

3227
This library is currently limited to legacy TKET passes (a small subset of them, in fact).

tket1-passes/build.rs

Lines changed: 95 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,9 @@
44
55
use std::env;
66
use std::path::{Path, PathBuf};
7+
use std::process::Command;
78

8-
fn is_macos() -> bool {
9-
let target = env::var("TARGET").unwrap();
10-
target.contains("apple")
11-
}
12-
13-
fn is_windows() -> bool {
14-
let target = env::var("TARGET").unwrap();
15-
target.contains("windows")
16-
}
9+
const CONAN_REMOTE: &str = "https://quantinuumsw.jfrog.io/artifactory/api/conan/tket1-libs";
1710

1811
fn main() {
1912
// // Configure when to rerun the build script
@@ -23,20 +16,43 @@ fn main() {
2316

2417
let custom_tket_path = env::var("TKET_C_API_PATH").ok().map(PathBuf::from);
2518

19+
let target = SupportedPlatform::from_target_str(&env::var("TARGET").unwrap());
20+
2621
let header_path = if let Some(path) = custom_tket_path {
27-
cargo_set_custom_lib_path(&path.join("lib"));
22+
cargo_set_custom_lib_path(&path.join("lib"), target);
2823
path.join("include").join("tket-c-api.h")
2924
} else {
3025
// Get dependencies from conan
31-
let conan_install = conan2::ConanInstall::new()
32-
.build("missing")
33-
.detect_profile()
34-
.run()
35-
.parse();
36-
conan_install.emit();
37-
38-
// Get header path
26+
27+
// 1. Add the conan remote to get the tket-c-api source and binaries
28+
add_conan_remote_if_missing(CONAN_REMOTE);
29+
30+
// 2. Select one of the pre-built conan profiles if possible (fallback to default)
31+
let profile_name = target
32+
.map(|t| t.get_prebuilt_conan_profile())
33+
.unwrap_or_else(|| {
34+
println!("cargo:warning=Unrecognized platform. Defaulting to default conan profile and building from source.");
35+
"default"
36+
});
37+
let profile_path = Path::new("./conan-profiles").join(profile_name);
38+
println!("Using conan profile: {}", profile_path.display());
39+
40+
// 3. Prepare the conan install command
41+
let mut conan_install = conan2::ConanInstall::new();
3942
conan_install
43+
.build_type("Release")
44+
.profile(profile_path.to_str().unwrap());
45+
46+
if profile_name == "default" {
47+
conan_install.detect_profile().build("missing");
48+
}
49+
50+
// 4. Run the conan install command and point cargo to the correct install paths
51+
let cargo_instructions = conan_install.run().parse();
52+
cargo_instructions.emit();
53+
54+
// 5. Get header path for bindgen
55+
cargo_instructions
4056
.include_paths()
4157
.into_iter()
4258
.map(|incl_path| incl_path.join("tket-c-api.h"))
@@ -51,7 +67,7 @@ fn main() {
5167
);
5268

5369
// Link in standard C++ library.
54-
if is_macos() {
70+
if target.is_some_and(|t| t.is_macos()) {
5571
println!("cargo:rustc-link-lib=c++");
5672
} else {
5773
println!("cargo:rustc-link-lib=stdc++");
@@ -70,10 +86,68 @@ fn main() {
7086
.expect("Couldn't write bindings!");
7187
}
7288

73-
fn cargo_set_custom_lib_path(search_path: &Path) {
89+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
90+
enum SupportedPlatform {
91+
MacOsX86,
92+
MacOsArm,
93+
WindowsX86,
94+
LinusX86,
95+
}
96+
97+
impl SupportedPlatform {
98+
fn from_target_str(target: &str) -> Option<Self> {
99+
if target.contains("apple") && target.contains("x86") {
100+
Some(SupportedPlatform::MacOsX86)
101+
} else if target.contains("apple") && target.contains("aarch64") {
102+
Some(SupportedPlatform::MacOsArm)
103+
} else if target.contains("windows") && target.contains("x86") {
104+
Some(SupportedPlatform::WindowsX86)
105+
} else if target.contains("linux") && target.contains("x86") {
106+
Some(SupportedPlatform::LinusX86)
107+
} else {
108+
None
109+
}
110+
}
111+
112+
fn is_macos(&self) -> bool {
113+
matches!(
114+
self,
115+
SupportedPlatform::MacOsX86 | SupportedPlatform::MacOsArm
116+
)
117+
}
118+
119+
fn get_prebuilt_conan_profile(&self) -> &'static str {
120+
// Corresponds to profiles which have pre-built binaries in the tket-libs conan remote
121+
// See ./conan-profiles/README.md for more details
122+
match self {
123+
SupportedPlatform::MacOsX86 => "macos-13",
124+
SupportedPlatform::MacOsArm => "macos-15",
125+
SupportedPlatform::WindowsX86 => "windows-2025",
126+
SupportedPlatform::LinusX86 => "linux-x86_64-gcc14",
127+
}
128+
}
129+
}
130+
131+
fn add_conan_remote_if_missing(conan_remote: &str) {
132+
let check_exists = Command::new("conan")
133+
.args(["remote", "list", "-fjson"])
134+
.output()
135+
.unwrap();
136+
137+
let stdout_str = String::from_utf8_lossy(&check_exists.stdout);
138+
if !stdout_str.contains(conan_remote) {
139+
println!("Adding conan remote: {conan_remote}");
140+
Command::new("conan")
141+
.args(["remote", "add", "tket-libs", conan_remote, "--index", "0"])
142+
.output()
143+
.unwrap();
144+
}
145+
}
146+
147+
fn cargo_set_custom_lib_path(search_path: &Path, target: Option<SupportedPlatform>) {
74148
println!("cargo:rustc-link-search={}", search_path.display());
75149

76-
let lib_name = if is_windows() {
150+
let lib_name = if target.is_some_and(|t| t == SupportedPlatform::WindowsX86) {
77151
"libtket-c-api"
78152
} else {
79153
"tket-c-api"

tket1-passes/conan-profiles/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This directory lists the conan profiles for which pre-built tket-c-api binaries
2+
are available in the tket-libs conan remote.
3+
The build script in `../build.rs` will try to use one of these profiles if possible.
4+
5+
They have been copied over from the [tket repository](https://github.com/CQCL/tket/tree/fed6b1c15dfa12df5520578b5fa852210187727e/conan-profiles).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[settings]
2+
arch=x86_64
3+
build_type=Release
4+
compiler=gcc
5+
compiler.cppstd=gnu17
6+
compiler.libcxx=libstdc++11
7+
compiler.version=13
8+
os=Linux

tket1-passes/conan-profiles/macos-13

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[settings]
2+
arch=x86_64
3+
build_type=Release
4+
compiler=apple-clang
5+
compiler.cppstd=gnu17
6+
compiler.libcxx=libc++
7+
compiler.version=15
8+
os=Macos

tket1-passes/conan-profiles/macos-15

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[settings]
2+
arch=armv8
3+
build_type=Release
4+
compiler=apple-clang
5+
compiler.cppstd=gnu17
6+
compiler.libcxx=libc++
7+
compiler.version=16
8+
os=Macos

0 commit comments

Comments
 (0)