From 5ef73c1d0f44b1f99cef251cc6b304ef344c63df Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Mon, 7 Sep 2015 09:31:33 +0200 Subject: [PATCH 01/11] Support for using the GNUstep blocks runtime (part of libobjc2) --- Cargo.toml | 4 ++++ src/lib.rs | 3 ++- test_utils/block_utils.c | 4 ++++ test_utils/build.rs | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d76a389..da8a0be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,10 @@ exclude = [".gitignore"] [dependencies] libc = "0.1" +[features] +gnustep_runtime = [] + [dev-dependencies.objc_test_utils] version = "0.0" path = "test_utils" + diff --git a/src/lib.rs b/src/lib.rs index 0b14880..da410e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,8 @@ use std::ops::{Deref, DerefMut}; use std::ptr; use libc::{c_int, c_ulong, c_void}; -#[link(name = "System", kind = "dylib")] +#[cfg_attr(not(feature = "gnustep_runtime"),link(name = "System", kind = "dylib"))] +#[cfg_attr(feature ="gnustep_runtime",link(name = "objc", kind = "dylib"))] extern { static _NSConcreteStackBlock: (); diff --git a/test_utils/block_utils.c b/test_utils/block_utils.c index 440dbb9..84b47d6 100644 --- a/test_utils/block_utils.c +++ b/test_utils/block_utils.c @@ -1,5 +1,9 @@ #include +#if __has_include("Block.h") #include +#elif __has_include("objc/blocks_runtime.h") +#include +#endif typedef int32_t (^IntBlock)(); typedef int32_t (^AddBlock)(int32_t); diff --git a/test_utils/build.rs b/test_utils/build.rs index 7c1455a..11300b4 100644 --- a/test_utils/build.rs +++ b/test_utils/build.rs @@ -1,5 +1,5 @@ extern crate gcc; fn main() { - gcc::compile_library("libblock_utils.a", &["block_utils.c"]); + gcc::Config::new().file("block_utils.c").flag("-fblocks").compile("libblock_utils.a"); } From 97da41bb0b2ac40b670e7b0421307444388290fd Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 18:16:26 +0200 Subject: [PATCH 02/11] Support more choices for the blocks runtime --- Cargo.toml | 6 +++--- build.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 ---- 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index 0bb2a0f..77f2d4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ readme = "README.md" repository = "http://github.com/SSheldon/rust-block" documentation = "http://ssheldon.github.io/rust-objc/block/" license = "MIT" +build = "build.rs" exclude = [ ".gitignore", @@ -18,10 +19,9 @@ exclude = [ "tests-ios/**", ] -[features] -gnustep_runtime = [] +[target.'cfg(not(any(target_os = "macos", target_os = "ios")))'.build-dependencies] +gcc = "0.3" [dev-dependencies.objc_test_utils] version = "0.0" path = "test_utils" - diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b8872ca --- /dev/null +++ b/build.rs @@ -0,0 +1,62 @@ +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +extern crate gcc; +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +use std::error::Error; +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +use std::io::Write; +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +use std::process::{ExitStatus,Stdio}; +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +use std::result::Result; +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +static MINI_MAIN: &'static str = r#" +extern void *_Block_copy(const void *aBlock); +int main() { + void (*ptr)(const void*) = _Block_copy; + return 0; +}"#; + +#[cfg(any(target_os = "macos", target_os = "ios"))] +fn main() { + println!("cargo:rustc-link-lib=framework=System") +} + +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +fn has_library(library: &str) -> Result<(),String> { + let invocation_result = gcc::Config::new() + .get_compiler().to_command() + .arg(format!("-l{}", library)) + .args(&["-x", "c"]) + .args(&["-o", "/dev/null"]) + .arg(format!("-")) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn(); + if invocation_result.is_err() { + return Result::Err("Could not spawn compiler".to_string()) + } + let mut process = invocation_result.unwrap(); + if let Err(why) = process.stdin.take().unwrap().write_all(MINI_MAIN.as_bytes()) { + return Result::Err(format!("Could not compile: {}", why.description())) + } + process.wait() + .or(Result::Err("Failed to compile".to_string())) + .and_then(| status : ExitStatus| if status.success() { + Result::Ok(()) + } else { + Result::Err(format!("{} unavailable", library)) + }) +} + + +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +fn main() { + if has_library("BlocksRuntime").is_ok() { + println!("cargo:rustc-link-lib=BlocksRuntime") + } else if let Err(why) = has_library("objc") { + panic!("Could not find blocks runtime library: {}", why) + } else { + println!("cargo:rustc-link-lib=objc") + } + +} diff --git a/src/lib.rs b/src/lib.rs index b9c5d1d..2ffc9ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,10 +56,6 @@ use std::ptr; enum Class { } -#[cfg_attr(any(target_os = "macos", target_os = "ios"), - link(name = "System", kind = "dylib"))] -#[cfg_attr(not(any(target_os = "macos", target_os = "ios")), - link(name = "BlocksRuntime", kind = "dylib"))] extern { static _NSConcreteStackBlock: Class; From ea5ffa7d1765d1e3957ed7568241bf371649262e Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 19:32:06 +0200 Subject: [PATCH 03/11] Tweak search order The test for libobjc will fail if it doesn't include support for blocks. --- build.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.rs b/build.rs index b8872ca..042f574 100644 --- a/build.rs +++ b/build.rs @@ -28,7 +28,7 @@ fn has_library(library: &str) -> Result<(),String> { .arg(format!("-l{}", library)) .args(&["-x", "c"]) .args(&["-o", "/dev/null"]) - .arg(format!("-")) + .arg("-") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn(); @@ -51,12 +51,12 @@ fn has_library(library: &str) -> Result<(),String> { #[cfg(not(any(target_os = "macos", target_os = "ios")))] fn main() { - if has_library("BlocksRuntime").is_ok() { - println!("cargo:rustc-link-lib=BlocksRuntime") - } else if let Err(why) = has_library("objc") { + if has_library("objc").is_ok() { + println!("cargo:rustc-link-lib=objc") + } else if let Err(why) = has_library("BlocksRuntime") { panic!("Could not find blocks runtime library: {}", why) } else { - println!("cargo:rustc-link-lib=objc") + println!("cargo:rustc-link-lib=BlocksRuntime") } } From 86d06e13581a563507cadf3c8896f20f9abba38f Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 19:37:07 +0200 Subject: [PATCH 04/11] Temporarily enable -v to find out what goes wrong on travis --- build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build.rs b/build.rs index 042f574..7221113 100644 --- a/build.rs +++ b/build.rs @@ -28,6 +28,7 @@ fn has_library(library: &str) -> Result<(),String> { .arg(format!("-l{}", library)) .args(&["-x", "c"]) .args(&["-o", "/dev/null"]) + .arg("-v") .arg("-") .stdin(Stdio::piped()) .stdout(Stdio::piped()) From 46d7c7ab0aa76f0cdb5b9b60a322f40333e26919 Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 17:45:52 +0000 Subject: [PATCH 05/11] Let's try to select clang --- build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build.rs b/build.rs index 7221113..a6001ce 100644 --- a/build.rs +++ b/build.rs @@ -24,6 +24,7 @@ fn main() { #[cfg(not(any(target_os = "macos", target_os = "ios")))] fn has_library(library: &str) -> Result<(),String> { let invocation_result = gcc::Config::new() + .compiler("clang") .get_compiler().to_command() .arg(format!("-l{}", library)) .args(&["-x", "c"]) From ef285c46e9302db61f0e2d2d96f218a96383c711 Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 19:48:37 +0200 Subject: [PATCH 06/11] Remove -v flag again --- build.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/build.rs b/build.rs index a6001ce..ecac25c 100644 --- a/build.rs +++ b/build.rs @@ -29,7 +29,6 @@ fn has_library(library: &str) -> Result<(),String> { .arg(format!("-l{}", library)) .args(&["-x", "c"]) .args(&["-o", "/dev/null"]) - .arg("-v") .arg("-") .stdin(Stdio::piped()) .stdout(Stdio::piped()) From 29dc7440a3f08d9adda5fe39ef7fe0b273f0813c Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 19:57:02 +0200 Subject: [PATCH 07/11] Try travis to get end test the Obj-C blocks rt --- .travis.yml | 17 ++++++++++++----- travis_install.sh | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 702eaee..ff15425 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,17 +6,24 @@ os: - osx - linux env: - - IOS_ARCHS="" + - IOS_ARCHS="" BLOCKS_RUNTIME=ObjC matrix: include: - os: osx osx_image: xcode7.2 rust: nightly env: IOS_ARCHS="i386 x86_64 armv7 armv7s aarch64" + - os: linux + env: BLOCKS_RUNTIME=BlocksRuntime + addons: + apt: + packages: + - libblocksruntime-dev sudo: false install: ./travis_install.sh +before_script: > + if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$BLOCKS_RUNTIME" = "ObjC" ]; then + export LIBRARY_PATH=$HOME/libobjc2_staging/lib:$LIBRARY_PATH; + export LD_LIBRARY_PATH=$HOME/libobjc2_staging/lib:$LD_LIBRARY_PATH; + fi script: ./travis_test.sh -addons: - apt: - packages: - - libblocksruntime-dev diff --git a/travis_install.sh b/travis_install.sh index 27c11fe..fd9008c 100755 --- a/travis_install.sh +++ b/travis_install.sh @@ -9,6 +9,16 @@ rust_ios_install() { "./${ios_stdlib}/install.sh" --prefix=$(rustc --print sysroot) } +gnustep_install() { + git clone https://github.com/gnustep/libobjc2.git + mkdir libobjc2/build + cd libobjc2/build + export CC="clang" + export CXX="clang++" + cmake -DCMAKE_INSTALL_PREFIX:PATH=$HOME/libobjc2_staging ../ + make install +} + for arch in $IOS_ARCHS; do rust_ios_install "$arch" done @@ -17,3 +27,7 @@ if [ -n "$IOS_ARCHS" ]; then curl -LO https://github.com/SSheldon/rust-test-ios/releases/download/0.1.1/rust-test-ios chmod +x rust-test-ios fi + +if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$BLOCKS_RUNTIME" = "ObjC" ]; then + gnustep_install +fi From e8458b82500c0e5f99713412542cba057a2f8734 Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 20:02:21 +0200 Subject: [PATCH 08/11] Need CPATH setting, readd matrix dimension --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index ff15425..ef80850 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,14 @@ matrix: rust: nightly env: IOS_ARCHS="i386 x86_64 armv7 armv7s aarch64" - os: linux + rust: stable + env: BLOCKS_RUNTIME=BlocksRuntime + addons: + apt: + packages: + - libblocksruntime-dev + - os: linux + rust: nightly env: BLOCKS_RUNTIME=BlocksRuntime addons: apt: @@ -25,5 +33,6 @@ before_script: > if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$BLOCKS_RUNTIME" = "ObjC" ]; then export LIBRARY_PATH=$HOME/libobjc2_staging/lib:$LIBRARY_PATH; export LD_LIBRARY_PATH=$HOME/libobjc2_staging/lib:$LD_LIBRARY_PATH; + export CPATH=$HOME/libobjc2_staging/include:$CPATH; fi script: ./travis_test.sh From 153ca15c2d174610116a4b0b7536e661b4c416f6 Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 20:08:22 +0200 Subject: [PATCH 09/11] Fix missing env var --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ef80850..a418a09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,14 +15,14 @@ matrix: env: IOS_ARCHS="i386 x86_64 armv7 armv7s aarch64" - os: linux rust: stable - env: BLOCKS_RUNTIME=BlocksRuntime + env: IOS_ARCHS="" BLOCKS_RUNTIME=BlocksRuntime addons: apt: packages: - libblocksruntime-dev - os: linux rust: nightly - env: BLOCKS_RUNTIME=BlocksRuntime + env: IOS_ARCHS="" BLOCKS_RUNTIME=BlocksRuntime addons: apt: packages: From 5a5ddbce279b582c95a49c8cde2b7fc184d84bc5 Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Wed, 20 Jul 2016 20:11:05 +0200 Subject: [PATCH 10/11] Wow. I am terrible at keeping these consistent --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a418a09..7845c64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ matrix: - os: osx osx_image: xcode7.2 rust: nightly - env: IOS_ARCHS="i386 x86_64 armv7 armv7s aarch64" + env: IOS_ARCHS="i386 x86_64 armv7 armv7s aarch64" BLOCKS_RUNTIME=ObjC - os: linux rust: stable env: IOS_ARCHS="" BLOCKS_RUNTIME=BlocksRuntime From 24f10532624bcfbaf18a45a37efb1828614c062b Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Thu, 21 Jul 2016 10:20:00 +0200 Subject: [PATCH 11/11] Rename a few things for clarity --- .travis.yml | 10 +++++----- build.rs | 6 +++--- travis_install.sh | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7845c64..fd3ed3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,23 +6,23 @@ os: - osx - linux env: - - IOS_ARCHS="" BLOCKS_RUNTIME=ObjC + - IOS_ARCHS="" BLOCKS_RUNTIME=ObjC-compatible matrix: include: - os: osx osx_image: xcode7.2 rust: nightly - env: IOS_ARCHS="i386 x86_64 armv7 armv7s aarch64" BLOCKS_RUNTIME=ObjC + env: IOS_ARCHS="i386 x86_64 armv7 armv7s aarch64" BLOCKS_RUNTIME=ObjC-compatible - os: linux rust: stable - env: IOS_ARCHS="" BLOCKS_RUNTIME=BlocksRuntime + env: IOS_ARCHS="" BLOCKS_RUNTIME=Standalone addons: apt: packages: - libblocksruntime-dev - os: linux rust: nightly - env: IOS_ARCHS="" BLOCKS_RUNTIME=BlocksRuntime + env: IOS_ARCHS="" BLOCKS_RUNTIME=Standalone addons: apt: packages: @@ -30,7 +30,7 @@ matrix: sudo: false install: ./travis_install.sh before_script: > - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$BLOCKS_RUNTIME" = "ObjC" ]; then + if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$BLOCKS_RUNTIME" = "ObjC-compatible" ]; then export LIBRARY_PATH=$HOME/libobjc2_staging/lib:$LIBRARY_PATH; export LD_LIBRARY_PATH=$HOME/libobjc2_staging/lib:$LD_LIBRARY_PATH; export CPATH=$HOME/libobjc2_staging/include:$CPATH; diff --git a/build.rs b/build.rs index ecac25c..3e8ec12 100644 --- a/build.rs +++ b/build.rs @@ -22,7 +22,7 @@ fn main() { } #[cfg(not(any(target_os = "macos", target_os = "ios")))] -fn has_library(library: &str) -> Result<(),String> { +fn check_block_copy_symbol_in_lib(library: &str) -> Result<(),String> { let invocation_result = gcc::Config::new() .compiler("clang") .get_compiler().to_command() @@ -52,9 +52,9 @@ fn has_library(library: &str) -> Result<(),String> { #[cfg(not(any(target_os = "macos", target_os = "ios")))] fn main() { - if has_library("objc").is_ok() { + if check_block_copy_symbol_in_lib("objc").is_ok() { println!("cargo:rustc-link-lib=objc") - } else if let Err(why) = has_library("BlocksRuntime") { + } else if let Err(why) = check_block_copy_symbol_in_lib("BlocksRuntime") { panic!("Could not find blocks runtime library: {}", why) } else { println!("cargo:rustc-link-lib=BlocksRuntime") diff --git a/travis_install.sh b/travis_install.sh index fd9008c..f0ad32a 100755 --- a/travis_install.sh +++ b/travis_install.sh @@ -28,6 +28,6 @@ if [ -n "$IOS_ARCHS" ]; then chmod +x rust-test-ios fi -if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$BLOCKS_RUNTIME" = "ObjC" ]; then +if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$BLOCKS_RUNTIME" = "ObjC-compatible" ]; then gnustep_install fi