-
Notifications
You must be signed in to change notification settings - Fork 21
Feat: Android support #158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| /target | ||
| Cargo.lock | ||
| coverage_report | ||
| result |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
| - Added Nix package outputs for Android with bundled NDK r24, Rust toolchains, Boost, and cmake. | ||
| - Added `Block::check` to perform context-free validation of a block (size, weight, coinbase, transactions, sigops), with optional proof-of-work and merkle-root checks toggled via the `BLOCK_CHECK_BASE` / `_POW` / `_MERKLE` / `_ALL` flags. Returns a `BlockCheckResult` enum carrying the validation state on failure. | ||
|
|
||
| ### Changed | ||
|
|
@@ -16,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |
| ## [0.2.1] 2026-05-20 | ||
|
|
||
| ### Added | ||
| - Added Nix package outputs for Android with bundled NDK r27, Rust toolchains, Boost, and cmake. | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to go in a new
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be removed from the |
||
| - Added `BlockTreeEntry::ancestor` to look up an ancestor block at a given height. Returns `None` if the height is out of range. This operation is O(log N). | ||
| - Added `Transaction::locktime()` to retrieve a transaction's `nLockTime` value as a `u32`. | ||
| - Added `TxIn::sequence()` to retrieve an input's `nSequence` value as a `u32`. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,34 @@ use std::env; | |
| use std::path::Path; | ||
| use std::process::Command; | ||
|
|
||
| // Rust target triple -> NDK ABI name. | ||
| fn android_abi(target: &str) -> Option<&'static str> { | ||
| match target { | ||
| t if t.contains("aarch64") => Some("arm64-v8a"), | ||
| t if t.contains("armv7") => Some("armeabi-v7a"), | ||
| t if t.contains("x86_64") => Some("x86_64"), | ||
| _ => panic!("Unsupported Android ABI: {target}"), | ||
| } | ||
| } | ||
|
jaoleal marked this conversation as resolved.
|
||
|
|
||
| // Rust target triple -> NDK sysroot lib directory triple. | ||
| // armv7 differs: Rust says `armv7-linux-androideabi`, NDK says `arm-linux-androideabi`. | ||
| fn android_sysroot_triple(target: &str) -> &str { | ||
| if target.starts_with("armv7") { | ||
| "arm-linux-androideabi" | ||
| } else { | ||
| target | ||
| } | ||
| } | ||
|
|
||
| fn android_host_tag() -> &'static str { | ||
| match std::env::consts::OS { | ||
| "macos" => "darwin-x86_64", | ||
| "linux" => "linux-x86_64", | ||
| os => panic!("unsupported build host for Android cross-compilation: {os}"), | ||
| } | ||
| } | ||
|
|
||
| fn main() { | ||
| let bitcoin_dir = Path::new("bitcoin"); | ||
| let out_dir = env::var("OUT_DIR").unwrap(); | ||
|
|
@@ -15,7 +43,8 @@ fn main() { | |
|
|
||
| let build_config = "RelWithDebInfo"; | ||
|
|
||
| Command::new("cmake") | ||
| let mut cmake_configure = Command::new("cmake"); | ||
| cmake_configure | ||
| .arg("-B") | ||
| .arg(&build_dir) | ||
| .arg("-S") | ||
|
|
@@ -38,7 +67,45 @@ fn main() { | |
| .arg("-DBUILD_SHARED_LIBS=OFF") | ||
| .arg("-DCMAKE_INSTALL_LIBDIR=lib") | ||
| .arg("-DENABLE_IPC=OFF") | ||
| .arg(format!("-DCMAKE_INSTALL_PREFIX={}", install_dir.display())) | ||
| .arg(format!("-DCMAKE_INSTALL_PREFIX={}", install_dir.display())); | ||
|
|
||
| let target = env::var("TARGET").unwrap(); | ||
| let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); | ||
| let is_android = target_os == "android"; | ||
|
|
||
| if is_android { | ||
| let ndk = env::var("ANDROID_NDK_HOME") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are fetching this twice. Any chance we can reuse this? |
||
| .expect("Android target detected but ANDROID_NDK_HOME is not set"); | ||
| let toolchain_file = format!("{ndk}/build/cmake/android.toolchain.cmake"); | ||
|
|
||
| let abi = android_abi(&target).unwrap(); | ||
|
|
||
| // API level 24+ is required because Bitcoin Core uses getifaddrs | ||
| // which was introduced in Android API 24 (Nougat). | ||
| // | ||
| // This can be overriden by setting ANDROID_API_LEVEL. | ||
| let api_level = match env::var("ANDROID_API_LEVEL") { | ||
| Ok(level) => { | ||
| let n: u32 = level.parse().expect("ANDROID_API_LEVEL must be a number"); | ||
| assert!(n >= 24, "ANDROID_API_LEVEL must be 24+"); | ||
| level | ||
| } | ||
| _ => "24".to_string(), | ||
| }; | ||
|
|
||
| cmake_configure | ||
| .arg(format!("-DCMAKE_TOOLCHAIN_FILE={toolchain_file}")) | ||
| .arg(format!("-DANDROID_ABI={abi}")) | ||
| .arg(format!("-DANDROID_PLATFORM=android-{api_level}")) | ||
| .arg("-DCMAKE_SYSTEM_NAME=Android") | ||
| .arg(format!("-DCMAKE_ANDROID_NDK={ndk}")) | ||
| // The Android NDK toolchain sets CMAKE_FIND_ROOT_PATH_MODE_PACKAGE | ||
| // to ONLY, which prevents cmake from finding host packages via | ||
| // CMAKE_PREFIX_PATH. Override it so Boost headers can be located. | ||
| .arg("-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH"); | ||
| } | ||
|
|
||
| cmake_configure | ||
| .status() | ||
| .expect("cmake should be installed and available in PATH"); | ||
|
|
||
|
|
@@ -70,19 +137,31 @@ fn main() { | |
| } else { | ||
| install_dir.join("lib") | ||
| }; | ||
|
|
||
| println!("cargo:rustc-link-search=native={}", lib_dir.display()); | ||
|
|
||
| println!("cargo:rustc-link-lib=static=bitcoinkernel"); | ||
|
|
||
| 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"); | ||
| println!("cargo:rustc-link-lib=shell32"); | ||
| } | ||
| } else if is_android { | ||
| // Android NDK ships libc++_static.a and libc++abi.a in the | ||
| // per-architecture sysroot directory (not the API-level subdirectory). | ||
| let ndk = env::var("ANDROID_NDK_HOME").expect("We called ANDROID_NDK_HOME before."); | ||
|
|
||
| let ndk_triple = android_sysroot_triple(&target); | ||
|
|
||
| let host_tag = android_host_tag(); | ||
|
|
||
| if compiler.is_like_clang() { | ||
| let ndk_lib_dir = | ||
| format!("{ndk}/toolchains/llvm/prebuilt/{host_tag}/sysroot/usr/lib/{ndk_triple}"); | ||
| println!("cargo:rustc-link-search=native={ndk_lib_dir}"); | ||
| println!("cargo:rustc-link-lib=static=c++_static"); | ||
| println!("cargo:rustc-link-lib=static=c++abi"); | ||
| } else if compiler.is_like_clang() { | ||
| if target_os == "macos" { | ||
| println!("cargo:rustc-link-lib=dylib=c++"); | ||
| } else { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.