Skip to content

Commit

Permalink
Build and upload the C and C++ bindings in nightly builds
Browse files Browse the repository at this point in the history
  • Loading branch information
VivekPanyam committed Oct 20, 2023
1 parent f455545 commit 333d31b
Show file tree
Hide file tree
Showing 12 changed files with 337 additions and 61 deletions.
6 changes: 4 additions & 2 deletions .buildkite/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ steps:
- name: "Native Build x86_64-unknown-linux-gnu"
agents:
queue: default
command: "python3 ci/build.py --release --target x86_64-unknown-linux-gnu --nightly --runner_release_dir target/runner_releases"
command: "python3 ci/build.py --release --target x86_64-unknown-linux-gnu --nightly --runner_release_dir target/runner_releases --c_cpp_bindings_release_dir target/bindings_releases"
artifact_paths:
- "target/cargo-timings/*"
- "target/wheels/*"
- "target/runner_releases/*"
- "target/bindings_releases/*"
plugins:
- docker-compose#v3.7.0:
run: x86_64
Expand All @@ -16,11 +17,12 @@ steps:
- name: "Native Build aarch64-unknown-linux-gnu"
agents:
queue: arm64
command: "python3 ci/build.py --release --target aarch64-unknown-linux-gnu --nightly --runner_release_dir target/runner_releases"
command: "python3 ci/build.py --release --target aarch64-unknown-linux-gnu --nightly --runner_release_dir target/runner_releases --c_cpp_bindings_release_dir target/bindings_releases"
artifact_paths:
- "target/cargo-timings/*"
- "target/wheels/*"
- "target/runner_releases/*"
- "target/bindings_releases/*"
plugins:
- docker-compose#v3.7.0:
run: arm64
Expand Down
25 changes: 24 additions & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- run: rustup default stable
- uses: Swatinem/rust-cache@v2
- run: pip3 install toml maturin==0.14.13
- run: python3 ci/build.py --target x86_64-apple-darwin --release --nightly --runner_release_dir /tmp/runner_releases
- run: python3 ci/build.py --target x86_64-apple-darwin --release --nightly --runner_release_dir /tmp/runner_releases --c_cpp_bindings_release_dir /tmp/bindings_releases
- name: Upload runners
uses: actions/upload-artifact@v3
with:
Expand All @@ -29,6 +29,11 @@ jobs:
with:
name: py-wheels-macos-x86
path: target/wheels/
- name: Upload C/C++ bindings
uses: actions/upload-artifact@v3
with:
name: c-cpp-bindings-x86_64-apple-darwin
path: /tmp/bindings_releases
nightly_release_mac_aarch64:
name: "Native Build macOS aarch64"
runs-on: ubuntu-latest
Expand All @@ -50,6 +55,11 @@ jobs:
with:
name: py-wheels-macos-aarch64
path: /tmp/target/wheels/
- name: Upload C/C++ bindings
uses: actions/upload-artifact@v3
with:
name: c-cpp-bindings-macos-aarch64
path: /tmp/bindings_releases
nightly_release_buildkite:
name: "Native Builds Linux (x86_64 and aarch64)"
runs-on: ubuntu-latest
Expand All @@ -71,6 +81,11 @@ jobs:
with:
name: py-wheels-linux
path: /tmp/target/wheels/
- name: Upload C/C++ bindings
uses: actions/upload-artifact@v3
with:
name: c-cpp-bindings-linux
path: /tmp/target/bindings_releases

upload_nightly_builds:
name: "Upload nightly builds"
Expand Down Expand Up @@ -101,6 +116,14 @@ jobs:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_NIGHTLY_TOKEN }}
TWINE_NON_INTERACTIVE: true
- name: Upload C and C++ bindings
run: cargo run --package build-utils --bin upload_c_cpp_bindings
env:
CARTON_NIGHTLY_S3_BUCKET: ${{ vars.CARTON_NIGHTLY_S3_BUCKET }}
CARTON_NIGHTLY_S3_REGION: ${{ vars.CARTON_NIGHTLY_S3_REGION }}
CARTON_NIGHTLY_S3_ENDPOINT: ${{ secrets.CARTON_NIGHTLY_S3_ENDPOINT }}
CARTON_NIGHTLY_ACCESS_KEY_ID: ${{ secrets.CARTON_NIGHTLY_ACCESS_KEY_ID }}
CARTON_NIGHTLY_SECRET_ACCESS_KEY: ${{ secrets.CARTON_NIGHTLY_SECRET_ACCESS_KEY }}
build_wasm:
name: WASM Build wasm32-unknown-unknown
runs-on: ubuntu-latest
Expand Down
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 15 additions & 2 deletions ci/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,34 @@ def update_version_numbers():
parser.add_argument("--nightly", action="store_true", help="Update version numbers with a dev build suffix")
parser.add_argument("--hide_output", action="store_true", help="Redirect all subprocess output to /dev/null")
parser.add_argument("--runner_release_dir", help="The runner release dir (if any)")
parser.add_argument("--c_cpp_bindings_release_dir", help="The C/C++ bindings release dir (if any)")
args = parser.parse_args()

TARGET = args.target
RELEASE_FLAG = "--release" if args.release else None
HIDE_OUTPUT = args.hide_output

# We don't use `--locked` on nightly builds because we need to change version numbers
LOCKED_FLAG = "--locked" if not args.nightly else None

print(f"""
Building with configuration:
Target: `{TARGET}`
Release mode: {args.release}
Nightly mode: {args.nightly}
Runner release dir: {args.runner_release_dir}
Bindings release dir: {args.c_cpp_bindings_release_dir}
""")

# Check up front so we don't build and then fail
if args.runner_release_dir is not None:
if os.path.exists(args.runner_release_dir):
raise ValueError("Supplied runner release dir already exists! Please remove it and try again.")

if args.c_cpp_bindings_release_dir is not None:
if os.path.exists(args.c_cpp_bindings_release_dir):
raise ValueError("Supplied runner bindings dir already exists! Please remove it and try again.")

# Update version numbers if this is a nightly build
if args.nightly:
update_version_numbers()
Expand All @@ -94,10 +103,10 @@ def update_version_numbers():
os.environ["LIBTORCH_CXX11_ABI"] = "0"

# Fetch deps (always in release mode)
run_command(["cargo", "run", "--locked", "--timings", "--release", "-p", "fetch-deps", "--target", TARGET])
run_command(["cargo", "run", LOCKED_FLAG, "--timings", "--release", "-p", "fetch-deps", "--target", TARGET])

# Build everything
run_command(["cargo", "build", "--locked", RELEASE_FLAG, "--verbose", "--timings", "--target", TARGET])
run_command(["cargo", "build", LOCKED_FLAG, RELEASE_FLAG, "--verbose", "--timings", "--target", TARGET])

# Build wheels for the python bindings
# TODO: store timing info
Expand All @@ -118,6 +127,10 @@ def update_version_numbers():
run_command(["cargo", "run", RELEASE_FLAG, "--timings", "--target", TARGET, "-p", "carton-runner-torch", "--bin", "build_torch_releases", "--", "--output-path", args.runner_release_dir])
run_command(["cargo", "run", RELEASE_FLAG, "--timings", "--target", TARGET, "-p", "carton-runner-wasm", "--bin", "build_wasm_releases", "--", "--output-path", args.runner_release_dir])

if args.c_cpp_bindings_release_dir is not None:
os.makedirs(args.c_cpp_bindings_release_dir)
run_command(["cargo", "run", RELEASE_FLAG, "--timings", "--target", TARGET, "-p", "build-utils", "--bin", "build_c_cpp_bindings", "--", "--bindings-path", args.c_cpp_bindings_release_dir, "--target", TARGET])

# Show sccache stats
RUSTC_WRAPPER = os.getenv("RUSTC_WRAPPER", "")
if "sccache" in RUSTC_WRAPPER:
Expand Down
14 changes: 13 additions & 1 deletion ci/trigger_cirrus_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,13 @@
build_and_test_script:
- source $HOME/.cargo/env
- pip3 install toml maturin==0.14.13
- python3 ci/build.py --target aarch64-apple-darwin --release --nightly --runner_release_dir $CIRRUS_WORKING_DIR/runner_releases
- python3 ci/build.py --target aarch64-apple-darwin --release --nightly --runner_release_dir $CIRRUS_WORKING_DIR/runner_releases --c_cpp_bindings_release_dir $CIRRUS_WORKING_DIR/bindings_releases
binaries_artifacts:
path: "runner_releases/*"
wheels_artifacts:
path: "target/wheels/*"
bindings_artifacts:
path: "bindings_releases/*"
"""

Expand Down Expand Up @@ -170,3 +172,13 @@

with zipfile.ZipFile("/tmp/wheels.zip", 'r') as zip_ref:
zip_ref.extractall("/tmp")


print("Downloading bindings...")
res = requests.get(f"https://api.cirrus-ci.com/v1/artifact/build/{build_id}/bindings.zip", headers={"Authorization": CIRRUS_AUTH})

with open("/tmp/bindings.zip", "wb") as f:
f.write(res.content)

with zipfile.ZipFile("/tmp/bindings.zip", 'r') as zip_ref:
zip_ref.extractall("/tmp")
7 changes: 7 additions & 0 deletions source/build-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ publish = false
escargot = "0.5.8"
log = "0.4"
cc = "1.0"
clap = { version = "4.0.29", features = ["derive"] }
env_logger = "0.9"
tempfile = "3.3.0"

# Required by the bindings upload code
rust-s3 = { version = "0.32.3", features = ["tokio-rustls-tls"], default-features = false }
tokio = { version = "1", features = ["full"] }
118 changes: 118 additions & 0 deletions source/build-utils/src/bin/build_c_cpp_bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright 2023 Vivek Panyam
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{
path::{Path, PathBuf},
process::Command,
};

use build_utils::{build_c_bindings, build_cpp_bindings};
use clap::Parser;

#[derive(Parser, Debug)]
struct Args {
/// The local folder to output bindings too
#[arg(long)]
bindings_path: PathBuf,

/// The compilation target (used as a suffix for the bindings tar)
#[arg(long)]
target: String,
}

fn main() {
// Logging
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();

// Parse args
let args = Args::parse();

build_c_cpp_bindings(&args.bindings_path, &args.target);
}

fn build_c_cpp_bindings(bindings_path: &Path, target: &str) {
let source_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap()
.to_path_buf();

let tempdir = tempfile::tempdir().unwrap();

// Build the C bindings and copy them into the output dir
let c_dir = tempdir.path().join("c");
std::fs::create_dir(&c_dir).unwrap();

// Create lib and include dirs
let c_lib_dir = c_dir.join("lib");
let c_include_dir = c_dir.join("include");
std::fs::create_dir(&c_lib_dir).unwrap();
std::fs::create_dir(&c_include_dir).unwrap();

// Build the C bindings and copy them to the lib dir
let c_bindings = build_c_bindings();
std::fs::copy(c_bindings.shared_lib, c_lib_dir.join("libcarton_c.so")).unwrap();
std::fs::copy(c_bindings.static_lib, c_lib_dir.join("libcarton_c.a")).unwrap();

// Copy the header to the include dir
std::fs::copy(
source_dir.join("carton-bindings-c/carton.h"),
c_include_dir.join("carton.h"),
)
.unwrap();

// Make a tar file for the C bindings
assert!(Command::new("tar")
.arg("-cvzf")
.arg(bindings_path.join(format!("carton_c_{}.tar.gz", target)))
.arg(".")
.current_dir(c_dir)
.status()
.unwrap()
.success());

// Build the C++ bindings and copy them into the output dir
let cpp_dir = tempdir.path().join("cpp");
std::fs::create_dir(&cpp_dir).unwrap();

// Create lib and include dirs
let cpp_lib_dir = cpp_dir.join("lib");
let cpp_include_dir = cpp_dir.join("include");
std::fs::create_dir(&cpp_lib_dir).unwrap();
std::fs::create_dir(&cpp_include_dir).unwrap();

// Build the C++ bindings and put the files in the lib dir
build_cpp_bindings(&cpp_lib_dir);

// Copy header files in
std::fs::copy(
source_dir.join("carton-bindings-cpp/src/carton.hh"),
&cpp_include_dir.join("carton.hh"),
)
.unwrap();
std::fs::copy(
source_dir.join("carton-bindings-cpp/src/carton_impl.hh"),
cpp_include_dir.join("carton_impl.hh"),
)
.unwrap();

// Make a tar file for the C++ bindings
assert!(Command::new("tar")
.arg("-cvzf")
.arg(bindings_path.join(format!("carton_cpp_{}.tar.gz", target)))
.arg(".")
.current_dir(cpp_dir)
.status()
.unwrap()
.success());
}
71 changes: 71 additions & 0 deletions source/build-utils/src/bin/upload_c_cpp_bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2023 Vivek Panyam
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::Arc;

use s3::{creds::Credentials, Bucket, Region};

/// Upload the C and C++ bindings in CI
#[tokio::main]
async fn main() {
let bucket = Arc::new(
Bucket::new(
&std::env::var("CARTON_NIGHTLY_S3_BUCKET").unwrap(),
Region::Custom {
region: std::env::var("CARTON_NIGHTLY_S3_REGION").unwrap(),
endpoint: std::env::var("CARTON_NIGHTLY_S3_ENDPOINT").unwrap(),
},
Credentials::new(
Some(&std::env::var("CARTON_NIGHTLY_ACCESS_KEY_ID").unwrap()),
Some(&std::env::var("CARTON_NIGHTLY_SECRET_ACCESS_KEY").unwrap()),
None,
None,
None,
)
.unwrap(),
)
.unwrap(),
);

let handles: Vec<_> = [
"/tmp/artifacts/c-cpp-bindings-linux",
"/tmp/artifacts/c-cpp-bindings-macos-aarch64",
"/tmp/artifacts/c-cpp-bindings-x86_64-apple-darwin",
]
.into_iter()
.flat_map(|dir| {
std::fs::read_dir(dir)
.unwrap()
.into_iter()
.filter_map(|item| item.ok())
.map(|item| (item.path(), item.file_name().to_str().unwrap().to_owned()))
})
.map(|(path, filename)| {
let bucket = bucket.clone();
tokio::spawn(async move {
let content = tokio::fs::read(path).await.unwrap();

// Upload the zip file
bucket
.put_object(format!("/bindings/{}", filename), &content)
.await
.unwrap();
})
})
.collect();

for handle in handles {
handle.await.unwrap();
}
}
Loading

0 comments on commit 333d31b

Please sign in to comment.