From 18d643a6fc7e91584cd70a05f4a01136305c2755 Mon Sep 17 00:00:00 2001 From: jaoleal Date: Mon, 2 Mar 2026 20:33:25 -0300 Subject: [PATCH 1/2] fix(build): improve error messages when cmake is not found Replace bare .unwrap() calls on cmake Command invocations with descriptive error handling. The first cmake call (configure) now specifically detects ErrorKind::NotFound and reports that cmake is required with installation instructions. The build and install calls use .expect() with clear messages and check exit status. --- libbitcoinkernel-sys/build.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libbitcoinkernel-sys/build.rs b/libbitcoinkernel-sys/build.rs index 7a120fe0..63d561d0 100644 --- a/libbitcoinkernel-sys/build.rs +++ b/libbitcoinkernel-sys/build.rs @@ -42,7 +42,7 @@ fn main() { .arg("-DENABLE_IPC=OFF") .arg(format!("-DCMAKE_INSTALL_PREFIX={}", install_dir.display())) .status() - .unwrap(); + .expect("cmake is required to build libbitcoinkernel. Please install cmake and ensure it is in your PATH."); let num_jobs = env::var("NUM_JOBS") .ok() @@ -56,7 +56,7 @@ fn main() { .arg(build_config) .arg(format!("--parallel={num_jobs}")) .status() - .unwrap(); + .expect("Failed to run cmake build"); Command::new("cmake") .arg("--install") @@ -64,7 +64,7 @@ fn main() { .arg("--config") .arg(build_config) .status() - .unwrap(); + .expect("Failed to run cmake install"); // Check if the build system used a multi-config generator let lib_dir = if install_dir.join("lib").join(build_config).exists() { From cf8d36d73cdd5f276c1fc14a7703025f5831c457 Mon Sep 17 00:00:00 2001 From: jaoleal Date: Mon, 16 Feb 2026 14:00:35 -0300 Subject: [PATCH 2/2] feat(build): move to cmake crate for building script in build.rs `libbitcoinkernel-sys/build.rs` was executing a cmake binary from the environment and doing some manual flag and path configuration. The presented changes delegate the same job to the cmake crate which also handles dependencies accross environments. --- libbitcoinkernel-sys/Cargo.toml | 1 + libbitcoinkernel-sys/build.rs | 97 ++++++++++++++------------------- 2 files changed, 41 insertions(+), 57 deletions(-) diff --git a/libbitcoinkernel-sys/Cargo.toml b/libbitcoinkernel-sys/Cargo.toml index bd0460ab..f5561bb6 100644 --- a/libbitcoinkernel-sys/Cargo.toml +++ b/libbitcoinkernel-sys/Cargo.toml @@ -51,5 +51,6 @@ exclude = [ publish = true [build-dependencies] +cmake = "0.1" cc = "1.2" bindgen = "0.72" diff --git a/libbitcoinkernel-sys/build.rs b/libbitcoinkernel-sys/build.rs index 63d561d0..f8138b93 100644 --- a/libbitcoinkernel-sys/build.rs +++ b/libbitcoinkernel-sys/build.rs @@ -2,82 +2,66 @@ use bindgen::RustEdition; use std::env; use std::path::Path; use std::path::PathBuf; -use std::process::Command; fn main() { let bitcoin_dir = Path::new("bitcoin"); - let out_dir = env::var("OUT_DIR").unwrap(); - let build_dir = Path::new(&out_dir).join("bitcoin"); - let install_dir = Path::new(&out_dir).join("install"); - - println!("{} {}", bitcoin_dir.display(), build_dir.display()); // Iterate through all files in the Bitcoin Core submodule directory println!("cargo:rerun-if-changed={}", bitcoin_dir.display()); let build_config = "RelWithDebInfo"; - Command::new("cmake") - .arg("-B") - .arg(&build_dir) - .arg("-S") - .arg(bitcoin_dir) - .arg(format!("-DCMAKE_BUILD_TYPE={build_config}")) - .arg("-DBUILD_KERNEL_LIB=ON") - .arg("-DBUILD_TESTS=OFF") - .arg("-DBUILD_BENCH=OFF") - .arg("-DBUILD_KERNEL_TEST=OFF") - .arg("-DBUILD_TX=OFF") - .arg("-DBUILD_WALLET_TOOL=OFF") - .arg("-DENABLE_WALLET=OFF") - .arg("-DENABLE_EXTERNAL_SIGNER=OFF") - .arg("-DBUILD_UTIL=OFF") - .arg("-DBUILD_BITCOIN_BIN=OFF") - .arg("-DBUILD_DAEMON=OFF") - .arg("-DBUILD_UTIL_CHAINSTATE=OFF") - .arg("-DBUILD_CLI=OFF") - .arg("-DBUILD_FUZZ_BINARY=OFF") - .arg("-DBUILD_SHARED_LIBS=OFF") - .arg("-DCMAKE_INSTALL_LIBDIR=lib") - .arg("-DENABLE_IPC=OFF") - .arg(format!("-DCMAKE_INSTALL_PREFIX={}", install_dir.display())) - .status() - .expect("cmake is required to build libbitcoinkernel. Please install cmake and ensure it is in your PATH."); - - let num_jobs = env::var("NUM_JOBS") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(1); // Default to 1 if not set + let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); - Command::new("cmake") - .arg("--build") - .arg(&build_dir) - .arg("--config") - .arg(build_config) - .arg(format!("--parallel={num_jobs}")) - .status() - .expect("Failed to run cmake build"); + // On Windows/MSVC, CMake normally adds /DWIN32 and /D_WINDOWS via + // CMAKE_CXX_FLAGS_INIT, but setting CMAKE_CXX_FLAGS to empty overrides + // that. We must restore these definitions so that code guarded by + // #if defined(WIN32) (e.g. cleanse.cpp's SecureZeroMemory path) compiles + // correctly instead of falling through to GCC-style inline assembly. + let (c_flags, cxx_flags) = if target_os == "windows" { + ("/DWIN32 /D_WINDOWS", "/DWIN32 /D_WINDOWS") + } else { + ("", "") + }; - Command::new("cmake") - .arg("--install") - .arg(&build_dir) - .arg("--config") - .arg(build_config) - .status() - .expect("Failed to run cmake install"); + let output_dir = cmake::Config::new("bitcoin") + .profile(build_config) + .no_default_flags(true) + .define("CMAKE_C_FLAGS", c_flags) + .define("CMAKE_CXX_FLAGS", cxx_flags) + .define("CMAKE_ASM_FLAGS", "") + .define("BUILD_KERNEL_LIB", "ON") + .define("BUILD_TESTS", "OFF") + .define("BUILD_BENCH", "OFF") + .define("BUILD_KERNEL_TEST", "OFF") + .define("BUILD_TX", "OFF") + .define("BUILD_WALLET_TOOL", "OFF") + .define("ENABLE_WALLET", "OFF") + .define("ENABLE_EXTERNAL_SIGNER", "OFF") + .define("BUILD_UTIL", "OFF") + .define("BUILD_BITCOIN_BIN", "OFF") + .define("BUILD_DAEMON", "OFF") + .define("BUILD_UTIL_CHAINSTATE", "OFF") + .define("BUILD_CLI", "OFF") + .define("BUILD_FUZZ_BINARY", "OFF") + .define("BUILD_SHARED_LIBS", "OFF") + .define("CMAKE_INSTALL_LIBDIR", "lib") + .define("ENABLE_IPC", "OFF") + .build(); // Check if the build system used a multi-config generator - let lib_dir = if install_dir.join("lib").join(build_config).exists() { - install_dir.join("lib").join(build_config) + let lib_dir = if output_dir.join("lib").join(build_config).exists() { + output_dir.join("lib").join(build_config) } else { - install_dir.join("lib") + output_dir.join("lib") }; + println!("cargo:rustc-link-search=native={}", lib_dir.display()); println!("cargo:rustc-link-lib=static=bitcoinkernel"); // Header path for bindgen - let include_path = install_dir.join("include"); + let include_path = output_dir.join("include"); let header = include_path.join("bitcoinkernel.h"); #[allow(deprecated)] @@ -97,7 +81,6 @@ fn main() { .expect("Couldn't write bindings!"); let compiler = cc::Build::new().get_compiler(); - let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); if target_os == "windows" { println!("cargo:rustc-link-lib=bcrypt");