Skip to content

Commit

Permalink
Use TARGET_CC env variable to enforce clang when building C code
Browse files Browse the repository at this point in the history
  • Loading branch information
xxuejie committed Jan 4, 2024
1 parent eb598e0 commit 9e3ee13
Show file tree
Hide file tree
Showing 16 changed files with 77 additions and 36 deletions.
7 changes: 3 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ CUSTOM_RUSTFLAGS := --cfg debug_assertions
# stdout in unit tests
CARGO_ARGS :=
MODE := release
# Tweak this to change the clang version to use for building C code
LLVM_SUFFIX := -16
CLANG := clang$(LLVM_SUFFIX)
# Tweak this to change the clang version to use for building C code. By default
# we use a bash script with somes heuristics to find clang in current system.
CLANG := $(shell $(TOP)/scripts/find_clang)
# When this is set, a single contract will be built instead of all contracts
CONTRACT :=
# By default, we would clean build/{release,debug} folder first, in case old
Expand All @@ -28,7 +28,6 @@ export CUSTOM_RUSTFLAGS
export TOP
export CARGO_ARGS
export MODE
export LLVM_SUFFIX
export CLANG
export BUILD_DIR

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Generally speaking, the directory structure, is simply a standard Rust workspace
* `deps`: All git submodules should go here.
* `tests`: Top level contract tests. Typically one would want to build full CKB transactions including the smart contracts in development, then run them in CKB's verifier for assurance of behaviors.
* `docker`: Sample docker files for reproducible build. You might or might not need this in your project.
* `scripts`: Utility scripts that will be leveraged by makefiles.
* `Makefile`: Top, workspace level makefile for firing up commands.

Note for the sample here, I am not locking Rust toolchain versions, since I believe latest stable Rust is good enough to build smart contracts. However for individual projects one is working on, it might or might not make sense to lock Rust toolchain version for stability.
Expand All @@ -61,6 +62,7 @@ $ make build CUSTOM_RUSTFLAGS="" # release build without debug assertio
$ make build CARGO_ARGS="--verbose" # release build with `--verbose` attached to cargo command, you can use other arguments accepted by cargo
$ make build CONTRACT=minimal-log # build a single contract
$ make build CLEAN_BUILD_DIR_FIRST=false # keep old untouched binaries
$ make build CLANG=clang-17 # use a specific clang version to build C code
```

You can also combine all the arguments here, suppose in a previous build you have build all the binaries, now you only want to build minimal-log binary. Doing `make build CONTRACT=minimal-log` will erase other binaries, you can do `make build CONTRACT=minimal-log CLEAN_BUILD_DIR_FIRST=false` to both build the minimal-log binary, and also keep the old ones untouched.
Expand Down
2 changes: 1 addition & 1 deletion contracts/atomics-without-a/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
ckb-std = { version = "0.15.0", features = [ "build-with-clang" ] }
ckb-std = "0.15.0"
log = { version = "0.4.20", default-features = false }
bytes = { version = "1.5.0", default-features = false }

Expand Down
5 changes: 4 additions & 1 deletion contracts/atomics-without-a/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs,-a $(CUSTOM_RUSTFLAGS)
# stdout in unit tests
CARGO_ARGS :=
MODE := release
# Tweak this to change the clang version to use for building C code. By default
# we use a bash script with somes heuristics to find clang in current system.
CLANG := $(shell $(TOP)/scripts/find_clang)
# When this is set to some value, the generated binaries will be copied over
BUILD_DIR :=
# Generated binaries to copy. By convention, a Rust crate's directory name will
Expand All @@ -30,7 +33,7 @@ endif
default: build test

build:
RUSTFLAGS="$(FULL_RUSTFLAGS)" \
RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" \
cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS)
@set -eu; \
if [ "x$(BUILD_DIR)" != "x" ]; then \
Expand Down
2 changes: 1 addition & 1 deletion contracts/legacy-c-dependency/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ version = "0.1.0"
edition = "2021"

[dependencies]
ckb-std = { version = "0.15.0", features = [ "build-with-clang" ] }
ckb-std = "0.15.0"
blake2b-rs = "0.2.0"
15 changes: 7 additions & 8 deletions contracts/legacy-c-dependency/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs $(CUSTOM_RUSTFLAGS)
# stdout in unit tests
CARGO_ARGS :=
MODE := release
# Tweak this to change the clang version to use for building C code. By default
# we use a bash script with somes heuristics to find clang in current system.
CLANG := $(shell $(TOP)/scripts/find_clang)
# When this is set to some value, the generated binaries will be copied over
BUILD_DIR :=
# Generated binaries to copy. By convention, a Rust crate's directory name will
Expand All @@ -23,12 +26,8 @@ BUILD_DIR :=
# more than one binary is supported here.
BINARIES := $(notdir $(shell pwd))

# For dependencies that are still using GNU-style convention, we would need
# to setup certain environment variables, so they can be built via clang
LLVM_SUFFIX := -16
CLANG := clang$(LLVM_SUFFIX)

TARGET_CC := $(CLANG)
# Some older crates might not be parpared to be built against clang, we would
# need to override CFLAGS to prepare them.
TARGET_CFLAGS := --target=riscv64 -march=rv64imc_zba_zbb_zbc_zbs \
-nostdinc -nostdlib \
-I $(TOP)deps/ckb-c-stdlib/libc -DCKB_DECLARATION_ONLY
Expand All @@ -40,8 +39,8 @@ endif
default: build test

build:
RUSTFLAGS="$(FULL_RUSTFLAGS)" \
TARGET_CC="$(TARGET_CC)" TARGET_CFLAGS="$(TARGET_CFLAGS)" \
RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" \
TARGET_CFLAGS="$(TARGET_CFLAGS)" \
cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS)
@set -eu; \
if [ "x$(BUILD_DIR)" != "x" ]; then \
Expand Down
2 changes: 1 addition & 1 deletion contracts/loads-of-hashes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
ckb-std = { version = "0.15.0", features = [ "build-with-clang" ] }
ckb-std = "0.15.0"
big-cell-fetcher = { path = "../../crates/big-cell-fetcher" }
big-witness-hasher = { path = "../../crates/big-witness-hasher" }
blake2b-ref = "0.3.1"
5 changes: 4 additions & 1 deletion contracts/loads-of-hashes/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs $(CUSTOM_RUSTFLAGS)
# stdout in unit tests
CARGO_ARGS :=
MODE := release
# Tweak this to change the clang version to use for building C code. By default
# we use a bash script with somes heuristics to find clang in current system.
CLANG := $(shell $(TOP)/scripts/find_clang)
# When this is set to some value, the generated binaries will be copied over
BUILD_DIR :=
# Generated binaries to copy. By convention, a Rust crate's directory name will
Expand All @@ -30,7 +33,7 @@ endif
default: build test

build:
RUSTFLAGS="$(FULL_RUSTFLAGS)" \
RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" \
cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS)
@set -eu; \
if [ "x$(BUILD_DIR)" != "x" ]; then \
Expand Down
2 changes: 1 addition & 1 deletion contracts/minimal-log/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ version = "0.1.0"
edition = "2021"

[dependencies]
ckb-std = { version = "0.15.0", features = [ "build-with-clang" ] }
ckb-std = "0.15.0"
5 changes: 4 additions & 1 deletion contracts/minimal-log/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs $(CUSTOM_RUSTFLAGS)
# stdout in unit tests
CARGO_ARGS :=
MODE := release
# Tweak this to change the clang version to use for building C code. By default
# we use a bash script with somes heuristics to find clang in current system.
CLANG := $(shell $(TOP)/scripts/find_clang)
# When this is set to some value, the generated binaries will be copied over
BUILD_DIR :=
# Generated binaries to copy. By convention, a Rust crate's directory name will
Expand All @@ -30,7 +33,7 @@ endif
default: build test

build:
RUSTFLAGS="$(FULL_RUSTFLAGS)" \
RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" \
cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS)
@set -eu; \
if [ "x$(BUILD_DIR)" != "x" ]; then \
Expand Down
2 changes: 1 addition & 1 deletion contracts/stack-reorder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
ckb-std = { version = "0.15.0", features = [ "build-with-clang" ] }
ckb-std = "0.15.0"

[build-dependencies]
cc = "1.0"
5 changes: 4 additions & 1 deletion contracts/stack-reorder/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs $(CUSTOM_RUSTFLAGS) \
# stdout in unit tests
CARGO_ARGS :=
MODE := release
# Tweak this to change the clang version to use for building C code. By default
# we use a bash script with somes heuristics to find clang in current system.
CLANG := $(shell $(TOP)/scripts/find_clang)
# When this is set to some value, the generated binaries will be copied over
BUILD_DIR :=
# Generated binaries to copy. By convention, a Rust crate's directory name will
Expand All @@ -31,7 +34,7 @@ endif
default: build test

build:
RUSTFLAGS="$(FULL_RUSTFLAGS)" \
RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" \
cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS)
@set -eu; \
if [ "x$(BUILD_DIR)" != "x" ]; then \
Expand Down
13 changes: 6 additions & 7 deletions contracts/stack-reorder/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ fn main() {
println!("cargo:rerun-if-changed=bootloader.S");
println!("cargo:rerun-if-changed=ld_interface.ld");

let clang = match std::env::var_os("CLANG") {
Some(val) => val,
None => "clang-16".into(),
};

let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
if target_arch == "riscv64" {
cc::Build::new()
let mut build = cc::Build::new();
assert!(
build.get_compiler().is_like_clang(),
"Clang must be used as the compiler!"
);
build
.file("bootloader.S")
.static_flag(true)
.compiler(clang)
.no_default_flags(true)
.flag("--target=riscv64")
.flag("-march=rv64imc_zba_zbb_zbc_zbs")
Expand Down
2 changes: 1 addition & 1 deletion crates/big-cell-fetcher/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
ckb-std = { version = "0.15.0", features = [ "build-with-clang" ] }
ckb-std = "0.15.0"

# Supporting native tests powered by ckb-x64-simulator
[target.'cfg(all(target_arch = "x86_64", unix))'.dependencies.ckb-std]
Expand Down
13 changes: 6 additions & 7 deletions crates/big-witness-hasher/build.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
fn main() {
println!("cargo:rerun-if-changed=c.c");

let clang = match std::env::var_os("CLANG") {
Some(val) => val,
None => "clang-16".into(),
};

let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
if target_arch == "riscv64" {
cc::Build::new()
let mut build = cc::Build::new();
assert!(
build.get_compiler().is_like_clang(),
"Clang must be used as the compiler!"
);
build
.file("c.c")
.static_flag(true)
.include("../../deps/ckb-c-stdlib")
.include("../../deps/ckb-c-stdlib/libc")
.compiler(clang)
.no_default_flags(true)
.flag("--target=riscv64")
.flag("-march=rv64imc_zba_zbb_zbc_zbs")
Expand Down
31 changes: 31 additions & 0 deletions scripts/find_clang
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
#
# An utility script used to find a binary of clang 16+

if [[ -n "${CLANG}" ]]; then
echo "${CLANG}"
exit 0
fi

CANDIDATES=("clang" "clang-16" "clang-17")

BREW_PREFIX=$(brew --prefix 2> /dev/null)
if [[ -n "${BREW_PREFIX}" ]]; then
CANDIDATES+=(
"${BREW_PREFIX}/opt/llvm/bin/clang"
"${BREW_PREFIX}/opt/llvm@16/bin/clang"
"${BREW_PREFIX}/opt/llvm@17/bin/clang"
)
fi

for candidate in ${CANDIDATES[@]}; do
OUTPUT=$($candidate -dumpversion 2> /dev/null | cut -d'.' -f 1)

if [[ $((OUTPUT)) -ge 16 ]]; then
echo "$candidate"
exit 0
fi
done

>&2 echo "Cannot find clang of version 16+!"
exit 1

0 comments on commit 9e3ee13

Please sign in to comment.