From e19dcaf04d488e3e05b5a0852cad01219246095b Mon Sep 17 00:00:00 2001 From: songww Date: Tue, 1 Dec 2020 23:55:59 +0800 Subject: [PATCH 1/6] Add build support for iOS --- fftw-src/build.rs | 73 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/fftw-src/build.rs b/fftw-src/build.rs index e01b12fc..21c0bb10 100644 --- a/fftw-src/build.rs +++ b/fftw-src/build.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use std::env::var; +use std::env::{var, set_var}; use std::fs::{canonicalize, File}; use std::io::{copy, Write}; use std::path::{Path, PathBuf}; @@ -38,12 +38,12 @@ fn download_archive_windows(out_dir: &Path) -> Result<()> { .arg("/MACHINE:X64") .arg(format!("/DEF:lib{}.def", name)) .arg(format!("/OUT:lib{}.lib", name)) - .current_dir(out_dir)) + .current_dir(out_dir)); } Ok(()) } -fn build_unix(out_dir: &Path) { +fn build_unix(out_dir: &Path, flags: &[&str]) { let src_dir = PathBuf::from(var("CARGO_MANIFEST_DIR").unwrap()).join("fftw-3.3.8"); let out_src_dir = out_dir.join("src"); fs_extra::dir::copy( @@ -60,10 +60,12 @@ fn build_unix(out_dir: &Path) { ) .unwrap(); if !out_dir.join("lib/libfftw3.a").exists() { - build_fftw(&[], &out_src_dir, &out_dir); + build_fftw(flags, &out_src_dir, &out_dir); } if !out_dir.join("lib/libfftw3f.a").exists() { - build_fftw(&["--enable-single"], &out_src_dir, &out_dir); + let mut flags = flags.to_vec(); + flags.push("--enable-single"); + build_fftw(&flags, &out_src_dir, &out_dir); } } @@ -83,14 +85,15 @@ fn build_fftw(flags: &[&str], src_dir: &Path, out_dir: &Path) { run(Command::new("make").arg("install").current_dir(&src_dir)); } -fn run(command: &mut Command) { +fn run(command: &mut Command) -> String { println!("Running: {:?}", command); - match command.status() { - Ok(status) => { - if !status.success() { - panic!("`{:?}` failed: {}", command, status); + match command.output() { + Ok(output) => { + if !output.status.success() { + panic!("`{:?}` failed: {}", command, output.status); } - } + return String::from_utf8(output.stdout).unwrap() + }, Err(error) => { panic!("failed to execute `{:?}`: {}", command, error); } @@ -98,16 +101,44 @@ fn run(command: &mut Command) { } fn main() { + println!("cargo:rerun-if-cahnged=build.rs"); let out_dir = PathBuf::from(var("OUT_DIR").unwrap()); - if cfg!(target_os = "windows") { - download_archive_windows(&out_dir).unwrap(); - println!("cargo:rustc-link-search={}", out_dir.display()); - println!("cargo:rustc-link-lib=libfftw3-3"); - println!("cargo:rustc-link-lib=libfftw3f-3"); - } else { - build_unix(&out_dir); - println!("cargo:rustc-link-search={}", out_dir.join("lib").display()); - println!("cargo:rustc-link-lib=static=fftw3"); - println!("cargo:rustc-link-lib=static=fftw3f"); + let target = var("TARGET").unwrap(); + let triple = target.split("-").collect::>(); + let target_os = var("CARGO_CFG_TARGET_OS").unwrap(); + let arch = match triple[0] { + "aarch64" => "arm64", + "armv7" => "armv7", + "armv7s" => "armv7s", + "x86" => "x86", + "x86_64" => "x86_64", + &_ => panic!("Unsupported platform {}", target_os), + }; + match target_os.as_ref() { + "ios" => { + let cc = run(Command::new("xcrun").args(&["--sdk", "iphoneos", "-f", "clang"])); + set_var("CC", cc.trim()); + let sysroot = run(Command::new("xcrun").args(&["--sdk", "iphoneos", "--show-sdk-path"])); + set_var("CFLAGS", format!("-O3 -pipe -isysroot {} -arch {} -miphoneos-version-min=9.0", sysroot.trim(), arch)); + let flags = &[&format!("--with-sysroot={}", sysroot.trim()), "--host=arm-apple-darwin"]; + build_unix(&out_dir, flags); + } + "android" => { + }, + "windows" => { + download_archive_windows(&out_dir).unwrap(); + println!("cargo:rustc-link-search={}", out_dir.display()); + println!("cargo:rustc-link-lib=libfftw3-3"); + println!("cargo:rustc-link-lib=libfftw3f-3"); + } + _ => { + if var("CARGO_CFG_TARGET_FAMILY").unwrap_or("".to_string()) != "unix" { + panic!("Unsupported platform {}", target_os); + } + build_unix(&out_dir, &[]); + println!("cargo:rustc-link-search={}", out_dir.join("lib").display()); + println!("cargo:rustc-link-lib=static=fftw3"); + println!("cargo:rustc-link-lib=static=fftw3f"); + } } } From 39b099bdc15902367f64ffc0656ed51e8230772e Mon Sep 17 00:00:00 2001 From: songww Date: Wed, 2 Dec 2020 00:04:14 +0800 Subject: [PATCH 2/6] enable neon for armv7 --- fftw-src/build.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fftw-src/build.rs b/fftw-src/build.rs index 21c0bb10..93c4f29a 100644 --- a/fftw-src/build.rs +++ b/fftw-src/build.rs @@ -65,6 +65,9 @@ fn build_unix(out_dir: &Path, flags: &[&str]) { if !out_dir.join("lib/libfftw3f.a").exists() { let mut flags = flags.to_vec(); flags.push("--enable-single"); + if var("CARGO_CFG_TARGET_ARCH").unwrap().starts_with("armv7") { + flags.push("--enable-neon"); + } build_fftw(&flags, &out_src_dir, &out_dir); } } From 78c8b4bccbbcae48e0e2e013ebf96f42b1756221 Mon Sep 17 00:00:00 2001 From: songww Date: Mon, 7 Dec 2020 21:16:32 +0800 Subject: [PATCH 3/6] enable threads --- fftw-src/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fftw-src/build.rs b/fftw-src/build.rs index 93c4f29a..f05ada08 100644 --- a/fftw-src/build.rs +++ b/fftw-src/build.rs @@ -78,6 +78,8 @@ fn build_fftw(flags: &[&str], src_dir: &Path, out_dir: &Path) { .arg("--with-pic") .arg("--enable-static") .arg("--disable-doc") + .arg("--enable-threads") + .arg("--with-combined-threads") .arg(format!("--prefix={}", out_dir.display())) .args(flags) .current_dir(&src_dir), From 78d0ba964f87091145d17736913d4ebf111f83b7 Mon Sep 17 00:00:00 2001 From: songww Date: Thu, 18 Mar 2021 16:03:32 +0800 Subject: [PATCH 4/6] iOS static link. Fix iOS static link. --- fftw-src/build.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fftw-src/build.rs b/fftw-src/build.rs index f05ada08..19aeea9c 100644 --- a/fftw-src/build.rs +++ b/fftw-src/build.rs @@ -127,6 +127,9 @@ fn main() { set_var("CFLAGS", format!("-O3 -pipe -isysroot {} -arch {} -miphoneos-version-min=9.0", sysroot.trim(), arch)); let flags = &[&format!("--with-sysroot={}", sysroot.trim()), "--host=arm-apple-darwin"]; build_unix(&out_dir, flags); + println!("cargo:rustc-link-search={}", out_dir.join("lib").display()); + println!("cargo:rustc-link-lib=static=fftw3"); + println!("cargo:rustc-link-lib=static=fftw3f"); } "android" => { }, From 7839a41935277dc986b592a30df994c459141d9d Mon Sep 17 00:00:00 2001 From: songww Date: Thu, 18 Mar 2021 16:04:51 +0800 Subject: [PATCH 5/6] Add build support for android aarch64 and armv7. --- fftw-src/build.rs | 120 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 11 deletions(-) diff --git a/fftw-src/build.rs b/fftw-src/build.rs index 19aeea9c..56d41990 100644 --- a/fftw-src/build.rs +++ b/fftw-src/build.rs @@ -1,5 +1,6 @@ use anyhow::Result; -use std::env::{var, set_var}; +use cc; +use std::env::{set_var, var}; use std::fs::{canonicalize, File}; use std::io::{copy, Write}; use std::path::{Path, PathBuf}; @@ -95,10 +96,16 @@ fn run(command: &mut Command) -> String { match command.output() { Ok(output) => { if !output.status.success() { - panic!("`{:?}` failed: {}", command, output.status); + panic!( + "`{:?}` failed: {}\nstdout:\n{}\nstderr:\n{}", + command, + output.status, + unsafe { String::from_utf8_unchecked(output.stdout) }, + unsafe { String::from_utf8_unchecked(output.stderr) } + ); } - return String::from_utf8(output.stdout).unwrap() - }, + return String::from_utf8(output.stdout).unwrap(); + } Err(error) => { panic!("failed to execute `{:?}`: {}", command, error); } @@ -121,18 +128,109 @@ fn main() { }; match target_os.as_ref() { "ios" => { - let cc = run(Command::new("xcrun").args(&["--sdk", "iphoneos", "-f", "clang"])); - set_var("CC", cc.trim()); - let sysroot = run(Command::new("xcrun").args(&["--sdk", "iphoneos", "--show-sdk-path"])); - set_var("CFLAGS", format!("-O3 -pipe -isysroot {} -arch {} -miphoneos-version-min=9.0", sysroot.trim(), arch)); - let flags = &[&format!("--with-sysroot={}", sysroot.trim()), "--host=arm-apple-darwin"]; - build_unix(&out_dir, flags); + let tool = cc::Build::new() + .target(&target) + .flag_if_supported(&format!("-march={}", arch)) + .get_compiler(); + set_var("CC", tool.cc_env()); + set_var("CFLAGS", tool.cflags_env()); + let sysroot = + run(Command::new("xcrun").args(&["--sdk", "iphoneos", "--show-sdk-path"])); + let args = &[ + &format!("--with-sysroot={}", sysroot.trim()), + "--host=arm-apple-darwin", + ]; + build_unix(&out_dir, args); println!("cargo:rustc-link-search={}", out_dir.join("lib").display()); println!("cargo:rustc-link-lib=static=fftw3"); println!("cargo:rustc-link-lib=static=fftw3f"); } "android" => { - }, + let tool = cc::Build::new() + .target(&target) + .flag_if_supported("-mfloat-abi=softfp") + .flag_if_supported("-mfpu=neon") + .get_compiler(); + let mut cc = Command::new(tool.cc_env()) + .arg("--version") + .status() + .ok() + .and_then(|status| { + if status.success() { + Some(tool.cc_env()) + } else { + None + } + }); + let ndk_root: PathBuf = var("ANDROID_NDK_ROOT") + .map_err(|_| var("ANDROID_NDK_HOME")) + .expect("ndk not found, please set ANDROID_NDK_ROOT to where ndk installed.") + .into(); + let mut sysroot: String = "".to_string(); + if cc.is_none() { + let host = var("HOST").unwrap(); + let triple = host.split("-").collect::>(); + let toolchain = ndk_root + .join("toolchains/llvm/prebuilt") + .join(&format!("{}-{}", triple[2], triple[0])) + .join("bin"); + if !toolchain.exists() { + panic!(format!( + "Unsupported platform {}, ndk toolchain dose not exists, {}!", + host, + toolchain.display() + )); + }; + match target.as_str() { + "aarch64-linux-android" => { + set_var("AR", toolchain.join("aarch64-linux-android-ar")); + set_var("AS", toolchain.join("aarch64-linux-android-as")); + set_var("LD", toolchain.join("aarch64-linux-android-ld")); + set_var("STRIP", toolchain.join("aarch64-linux-android-strip")); + set_var("RANLIB", toolchain.join("aarch64-linux-android-ranlib")); + cc = Some( + toolchain + .join("aarch64-linux-android21-clang") + .into_os_string(), + ); + sysroot = format!( + "--with-sysroot={}/platforms/android-21/arch-arm64", + ndk_root.display() + ); + } + "armv7-linux-androideabi" => { + set_var("AR", toolchain.join("arm-linux-androideabi-ar")); + set_var("AS", toolchain.join("arm-linux-androideabi-as")); + set_var("LD", toolchain.join("arm-linux-androideabi-ld")); + set_var("STRIP", toolchain.join("arm-linux-androideabi-strip")); + set_var("RANLIB", toolchain.join("arm-linux-androideabi-ranlib")); + cc = Some( + toolchain + .join("armv7a-linux-androideabi21-clang") + .into_os_string(), + ); + sysroot = format!( + "--with-sysroot={}/platforms/android-21/arch-arm", + ndk_root.display() + ); + } + &_ => { + unimplemented!(); + } + }; + }; + set_var("CFLAGS", tool.cflags_env()); + set_var("CC", cc.unwrap()); + let cross = format!("--host={}", target); + if target.starts_with("arm") { + build_unix(&out_dir, &[cross.as_str(), sysroot.as_str()]); + } else { + build_unix(&out_dir, &[cross.as_str(), sysroot.as_str()]); + } + println!("cargo:rustc-link-search={}", out_dir.join("lib").display()); + println!("cargo:rustc-link-lib=static=fftw3"); + println!("cargo:rustc-link-lib=static=fftw3f"); + } "windows" => { download_archive_windows(&out_dir).unwrap(); println!("cargo:rustc-link-search={}", out_dir.display()); From 7c2214b9621a277d5936a90565ead8f42da644e4 Mon Sep 17 00:00:00 2001 From: songww Date: Thu, 18 Mar 2021 13:53:48 +0800 Subject: [PATCH 6/6] Update ci with Android/iOS --- .github/workflows/rust.yml | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 018d9eec..f026dc58 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -41,6 +41,60 @@ jobs: command: test args: --manifest-path=fftw/Cargo.toml --features=${{ matrix.feature }} --no-default-features + ios: + runs-on: macos-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v1 + - name: Force XCode + run: sudo xcode-select -switch /Applications/Xcode.app + - name: Install targets + run: rustup target install aarch64-apple-ios + - uses: actions-rs/cargo@v1 + with: + command: test + args: > + --all-targets + --manifest-path=fftw/Cargo.toml + --target aarch64-apple-ios + --features=source + --no-default-features + --no-run + + android: + runs-on: ubuntu-18.04 + strategy: + fail-fast: false + matrix: + targets: ["aarch64-linux-android", "armv7-linux-androideabi"] + steps: + - uses: nttld/setup-ndk@v1 + with: + ndk-version: r21d + - name: Show env + env: + OUTPUT_NDK_PATH: ${{ steps.setup-ndk.outputs.ndk-path }} + run: > + ls /usr/local/lib/android/sdk/ndk/; + echo ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT; + echo ${{ steps.setup-ndk.outputs.ndk-path }}; + echo output-ndk-path=$OUTPUT_NDK_PATH; + - uses: actions/checkout@v1 + - name: Install targets + run: rustup target install aarch64-linux-android armv7-linux-androideabi + - uses: actions-rs/cargo@v1 + with: + command: test + args: > + --all-targets + --manifest-path=fftw/Cargo.toml + --target ${{ matrix.targets }} + --features=source + --no-default-features + --no-run + --verbose + linux: runs-on: ubuntu-18.04 strategy: