Skip to content

Commit f455014

Browse files
committed
feat(build): support pre-built libbitcoinkernel via LIBBITCOINKERNEL_LIB_DIR
When the LIBBITCOINKERNEL_LIB_DIR environment variable is set, build.rs skips the CMake configure/build/install steps entirely and links against the pre-built static library at the given path. This follows the same pattern as openssl-sys with OPENSSL_LIB_DIR. This allows builders to pre-compile libbitcoinkernel separately and point the sys crate at the result, rather than needing adding patches to its projects.
1 parent 01bf6d4 commit f455014

1 file changed

Lines changed: 114 additions & 105 deletions

File tree

libbitcoinkernel-sys/build.rs

Lines changed: 114 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,13 @@ use std::path::Path;
33
use std::process::Command;
44

55
fn main() {
6-
let bitcoin_dir = Path::new("bitcoin");
7-
let out_dir = env::var("OUT_DIR").unwrap();
8-
let build_dir = Path::new(&out_dir).join("bitcoin");
9-
let install_dir = Path::new(&out_dir).join("install");
10-
11-
println!("{} {}", bitcoin_dir.display(), build_dir.display());
12-
13-
// Iterate through all files in the Bitcoin Core submodule directory
14-
println!("cargo:rerun-if-changed={}", bitcoin_dir.display());
15-
16-
let build_config = "RelWithDebInfo";
17-
18-
let mut cmake_configure = Command::new("cmake");
19-
cmake_configure
20-
.arg("-B")
21-
.arg(&build_dir)
22-
.arg("-S")
23-
.arg(bitcoin_dir)
24-
.arg(format!("-DCMAKE_BUILD_TYPE={build_config}"))
25-
.arg("-DBUILD_KERNEL_LIB=ON")
26-
.arg("-DBUILD_TESTS=OFF")
27-
.arg("-DBUILD_BENCH=OFF")
28-
.arg("-DBUILD_KERNEL_TEST=OFF")
29-
.arg("-DBUILD_TX=OFF")
30-
.arg("-DBUILD_WALLET_TOOL=OFF")
31-
.arg("-DENABLE_WALLET=OFF")
32-
.arg("-DENABLE_EXTERNAL_SIGNER=OFF")
33-
.arg("-DBUILD_UTIL=OFF")
34-
.arg("-DBUILD_BITCOIN_BIN=OFF")
35-
.arg("-DBUILD_DAEMON=OFF")
36-
.arg("-DBUILD_UTIL_CHAINSTATE=OFF")
37-
.arg("-DBUILD_CLI=OFF")
38-
.arg("-DBUILD_FUZZ_BINARY=OFF")
39-
.arg("-DBUILD_SHARED_LIBS=OFF")
40-
.arg("-DCMAKE_INSTALL_LIBDIR=lib")
41-
.arg("-DENABLE_IPC=OFF")
42-
.arg(format!("-DCMAKE_INSTALL_PREFIX={}", install_dir.display()));
43-
446
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
457
let is_android = target_os == "android";
468

9+
// When LIBBITCOINKERNEL_LIB_DIR is set, skip the CMake build and link
10+
// against the pre-built library directly (same pattern as openssl-sys).
11+
println!("cargo:rerun-if-env-changed=LIBBITCOINKERNEL_LIB_DIR");
12+
4713
let ndk = if is_android {
4814
Some(
4915
env::var("ANDROID_NDK_HOME")
@@ -53,79 +19,122 @@ fn main() {
5319
None
5420
};
5521

56-
if is_android {
57-
let ndk = ndk.as_deref().unwrap();
58-
let toolchain_file = format!("{ndk}/build/cmake/android.toolchain.cmake");
59-
60-
// Rust target triple -> NDK ABI name.
61-
let abi = match env::var("TARGET").unwrap() {
62-
t if t.contains("aarch64") => "arm64-v8a",
63-
t if t.contains("armv7") => "armeabi-v7a",
64-
t if t.contains("x86_64") => "x86_64",
65-
target => panic!("Unsupported Android ABI: {target}"),
66-
};
22+
if let Ok(lib_dir) = env::var("LIBBITCOINKERNEL_LIB_DIR") {
23+
println!("cargo:rustc-link-search=native={lib_dir}");
24+
println!("cargo:rustc-link-lib=static=bitcoinkernel");
25+
} else {
26+
let bitcoin_dir = Path::new("bitcoin");
27+
let out_dir = env::var("OUT_DIR").unwrap();
28+
let build_dir = Path::new(&out_dir).join("bitcoin");
29+
let install_dir = Path::new(&out_dir).join("install");
6730

68-
// API level 24+ is required because Bitcoin Core uses getifaddrs
69-
// which was introduced in Android API 24 (Nougat).
70-
//
71-
// This can be overridden to a higher level by setting ANDROID_API_LEVEL.
72-
let api_level = match env::var("ANDROID_API_LEVEL") {
73-
Ok(level) => {
74-
let n: u32 = level.parse().expect("ANDROID_API_LEVEL must be a number");
75-
assert!(n >= 24, "ANDROID_API_LEVEL must be 24+");
76-
level
77-
}
78-
_ => "24".to_string(),
79-
};
31+
println!("{} {}", bitcoin_dir.display(), build_dir.display());
8032

33+
// Iterate through all files in the Bitcoin Core submodule directory
34+
println!("cargo:rerun-if-changed={}", bitcoin_dir.display());
35+
36+
let build_config = "RelWithDebInfo";
37+
38+
let mut cmake_configure = Command::new("cmake");
8139
cmake_configure
82-
.arg(format!("-DCMAKE_TOOLCHAIN_FILE={toolchain_file}"))
83-
.arg(format!("-DANDROID_ABI={abi}"))
84-
.arg(format!("-DANDROID_PLATFORM=android-{api_level}"))
85-
.arg("-DCMAKE_SYSTEM_NAME=Android")
86-
.arg(format!("-DCMAKE_ANDROID_NDK={ndk}"))
87-
// The Android NDK toolchain sets CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
88-
// to ONLY, which prevents cmake from finding host packages via
89-
// CMAKE_PREFIX_PATH. Override it so Boost headers can be located.
90-
.arg("-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH");
91-
}
40+
.arg("-B")
41+
.arg(&build_dir)
42+
.arg("-S")
43+
.arg(bitcoin_dir)
44+
.arg(format!("-DCMAKE_BUILD_TYPE={build_config}"))
45+
.arg("-DBUILD_KERNEL_LIB=ON")
46+
.arg("-DBUILD_TESTS=OFF")
47+
.arg("-DBUILD_BENCH=OFF")
48+
.arg("-DBUILD_KERNEL_TEST=OFF")
49+
.arg("-DBUILD_TX=OFF")
50+
.arg("-DBUILD_WALLET_TOOL=OFF")
51+
.arg("-DENABLE_WALLET=OFF")
52+
.arg("-DENABLE_EXTERNAL_SIGNER=OFF")
53+
.arg("-DBUILD_UTIL=OFF")
54+
.arg("-DBUILD_BITCOIN_BIN=OFF")
55+
.arg("-DBUILD_DAEMON=OFF")
56+
.arg("-DBUILD_UTIL_CHAINSTATE=OFF")
57+
.arg("-DBUILD_CLI=OFF")
58+
.arg("-DBUILD_FUZZ_BINARY=OFF")
59+
.arg("-DBUILD_SHARED_LIBS=OFF")
60+
.arg("-DCMAKE_INSTALL_LIBDIR=lib")
61+
.arg("-DENABLE_IPC=OFF")
62+
.arg(format!("-DCMAKE_INSTALL_PREFIX={}", install_dir.display()));
63+
64+
if is_android {
65+
let ndk = ndk.as_deref().unwrap();
66+
let toolchain_file = format!("{ndk}/build/cmake/android.toolchain.cmake");
67+
68+
// Rust target triple -> NDK ABI name.
69+
let abi = match env::var("TARGET").unwrap() {
70+
t if t.contains("aarch64") => "arm64-v8a",
71+
t if t.contains("armv7") => "armeabi-v7a",
72+
t if t.contains("x86_64") => "x86_64",
73+
target => panic!("Unsupported Android ABI: {target}"),
74+
};
75+
76+
// API level 24+ is required because Bitcoin Core uses getifaddrs
77+
// which was introduced in Android API 24 (Nougat).
78+
//
79+
// This can be overridden to a higher level by setting ANDROID_API_LEVEL.
80+
let api_level = match env::var("ANDROID_API_LEVEL") {
81+
Ok(level) => {
82+
let n: u32 = level.parse().expect("ANDROID_API_LEVEL must be a number");
83+
assert!(n >= 24, "ANDROID_API_LEVEL must be 24+");
84+
level
85+
}
86+
_ => "24".to_string(),
87+
};
88+
89+
cmake_configure
90+
.arg(format!("-DCMAKE_TOOLCHAIN_FILE={toolchain_file}"))
91+
.arg(format!("-DANDROID_ABI={abi}"))
92+
.arg(format!("-DANDROID_PLATFORM=android-{api_level}"))
93+
.arg("-DCMAKE_SYSTEM_NAME=Android")
94+
.arg(format!("-DCMAKE_ANDROID_NDK={ndk}"))
95+
// The Android NDK toolchain sets CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
96+
// to ONLY, which prevents cmake from finding host packages via
97+
// CMAKE_PREFIX_PATH. Override it so Boost headers can be located.
98+
.arg("-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH");
99+
}
92100

93-
cmake_configure
94-
.status()
95-
.expect("cmake should be installed and available in PATH");
96-
97-
let num_jobs = env::var("NUM_JOBS")
98-
.ok()
99-
.and_then(|v| v.parse::<u32>().ok())
100-
.unwrap_or(1); // Default to 1 if not set
101-
102-
Command::new("cmake")
103-
.arg("--build")
104-
.arg(&build_dir)
105-
.arg("--config")
106-
.arg(build_config)
107-
.arg(format!("--parallel={num_jobs}"))
108-
.status()
109-
.unwrap();
110-
111-
Command::new("cmake")
112-
.arg("--install")
113-
.arg(&build_dir)
114-
.arg("--config")
115-
.arg(build_config)
116-
.status()
117-
.unwrap();
118-
119-
// Check if the build system used a multi-config generator
120-
let lib_dir = if install_dir.join("lib").join(build_config).exists() {
121-
install_dir.join("lib").join(build_config)
122-
} else {
123-
install_dir.join("lib")
124-
};
101+
cmake_configure
102+
.status()
103+
.expect("cmake should be installed and available in PATH");
104+
105+
let num_jobs = env::var("NUM_JOBS")
106+
.ok()
107+
.and_then(|v| v.parse::<u32>().ok())
108+
.unwrap_or(1); // Default to 1 if not set
109+
110+
Command::new("cmake")
111+
.arg("--build")
112+
.arg(&build_dir)
113+
.arg("--config")
114+
.arg(build_config)
115+
.arg(format!("--parallel={num_jobs}"))
116+
.status()
117+
.unwrap();
118+
119+
Command::new("cmake")
120+
.arg("--install")
121+
.arg(&build_dir)
122+
.arg("--config")
123+
.arg(build_config)
124+
.status()
125+
.unwrap();
125126

126-
println!("cargo:rustc-link-search=native={}", lib_dir.display());
127+
// Check if the build system used a multi-config generator
128+
let lib_dir = if install_dir.join("lib").join(build_config).exists() {
129+
install_dir.join("lib").join(build_config)
130+
} else {
131+
install_dir.join("lib")
132+
};
127133

128-
println!("cargo:rustc-link-lib=static=bitcoinkernel");
134+
println!("cargo:rustc-link-search=native={}", lib_dir.display());
135+
136+
println!("cargo:rustc-link-lib=static=bitcoinkernel");
137+
}
129138

130139
let compiler = cc::Build::new().get_compiler();
131140

0 commit comments

Comments
 (0)