@@ -3,47 +3,13 @@ use std::path::Path;
33use std:: process:: Command ;
44
55fn 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 ( ) ;
125118
126- println ! ( "cargo:rustc-link-search=native={}" , lib_dir. display( ) ) ;
119+ Command :: new ( "cmake" )
120+ . arg ( "--install" )
121+ . arg ( & build_dir)
122+ . arg ( "--config" )
123+ . arg ( build_config)
124+ . status ( )
125+ . unwrap ( ) ;
127126
128- println ! ( "cargo:rustc-link-lib=static=bitcoinkernel" ) ;
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+ } ;
133+
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
@@ -164,6 +173,17 @@ fn main() {
164173 println ! ( "cargo:rustc-link-search=native={ndk_lib_dir}" ) ;
165174 println ! ( "cargo:rustc-link-lib=static=c++_static" ) ;
166175 println ! ( "cargo:rustc-link-lib=static=c++abi" ) ;
176+
177+ // The pre-compiled libcompiler_builtins for armv7-linux-androideabi
178+ // ships ARM EABI helper symbols tagged with @@LIBC_N (e.g.
179+ // __aeabi_memcpy@@LIBC_N). When lld links a shared library or
180+ // executable it errors because the LIBC_N version node is not
181+ // defined in any version script. --exclude-libs,ALL marks every
182+ // symbol pulled from static archives as local, which suppresses
183+ // the version-node error.
184+ if ndk_triple == "arm-linux-androideabi" {
185+ println ! ( "cargo:rustc-link-arg=-Wl,--exclude-libs,ALL" ) ;
186+ }
167187 } else if compiler. is_like_clang ( ) {
168188 if target_os == "macos" {
169189 println ! ( "cargo:rustc-link-lib=dylib=c++" ) ;
0 commit comments