Repository: TimNN/cargo-lipo (language: rust)

Issue:
Deprecate 32-bit targets
As of iOS 11, 32-bit apps are no longer supported on iOS. Removing the 32-bit targets would save considerable compilation time, and also allow programs too large for 32-bit to be lipo'd without running into this sort of error:
```
LLVM ERROR: Section too large, can't encode r_address (0x1005de7) into 24 bits of scattered relocation entry.
```


Discussion / hints:
For the record, I do know that one can do this manually by specifying just the 64-bit targets on the command line:
```
cargo lipo --targets=aarch64-apple-ios,x86_64-apple-ios --release
```
But going forward it'd be nice to have the default behaviour be the forward-compatible one.

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index 30d211d..bfc1561 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,29 +1,43 @@
 language: rust
 
-sudo: false
-
-# run builds for all the trains (and more)
+os: osx
+osx_image: xcode10.1
+addons:
+  homebrew:
+    packages:
+      - bats-core
 rust:
-  - nightly
-  - beta
-  # check it compiles on the latest stable compiler
   - stable
-  # and the first stable one (this should be bumped as the minimum
-  # Rust version required changes)
-  - 1.28.0
+  - 1.31.1
+  - beta
+  - nightly
+
+stages:
+  - check
+  - test
+
+jobs:
+  include:
+    - stage: check
+      os: linux
+      dist: xenial
+      rust: stable
+      before_script:
+        - rustup component add rustfmt clippy
+      script:
+        - (cd . && cargo fmt --all -- --check)
+        - (cd ./testdata/simple && cargo fmt --all -- --check)
+        - (cd ./testdata/workspace && cargo fmt --all -- --check)
+        - cargo clippy --all --manifest-path ./Cargo.toml -- --deny warnings
+        - cargo clippy --all --manifest-path ./testdata/simple/Cargo.toml -- --deny warnings
+        - cargo clippy --all --manifest-path ./testdata/workspace/Cargo.toml -- --deny warnings
 
-# load travis-cargo
 before_script:
-  - |
-      pip install 'travis-cargo<0.2' --user &&
-      export PATH=$HOME/.local/bin:$PATH
+  - rustup target add aarch64-apple-ios x86_64-apple-ios
 
-# the main build
 script:
-  - |
-      travis-cargo build
-
-env:
-  global:
-    # override the default `--features unstable` used for the nightly branch (optional)
-    - TRAVIS_CARGO_NIGHTLY_FEATURE=""
+  - set -e
+  - cargo build
+  - export PATH="$PWD/target/debug:$PATH"
+  - cargo lipo --version
+  - ./integration.bats.sh
diff --git a/Cargo.lock b/Cargo.lock
index 508846a..b2e0e00 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,75 +1,366 @@
+[[package]]
+name = "aho-corasick"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "ansi_term"
-version = "0.7.5"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "autocfg"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "backtrace"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "bitflags"
-version = "0.5.0"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cargo-lipo"
-version = "2.0.0"
+version = "3.0.0"
+dependencies = [
+ "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "cc"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "clap"
-version = "2.2.6"
+version = "2.32.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "ansi_term 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "error-chain"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "failure"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "humantime"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "itoa"
-version = "0.1.1"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "lazy_static"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.2.43"
+version = "0.2.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
-name = "num-traits"
-version = "0.1.43"
+name = "memchr"
+version = "2.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "num-traits"
-version = "0.2.6"
+name = "proc-macro2"
+version = "0.4.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "quote"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "redox_termios"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ryu"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "0.7.15"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_derive"
+version = "1.0.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "serde_json"
-version = "0.7.4"
+version = "1.0.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "strsim"
-version = "0.4.1"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "structopt"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "0.15.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "termion"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ucd-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -77,21 +368,115 @@ name = "unicode-width"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "utf8-ranges"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "vec_map"
-version = "0.6.0"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "version_check"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "wincolor"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [metadata]
-"checksum ansi_term 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30275ad0ad84ec1c06dde3b3f7d23c6006b7d76d61a85e7060b426b747eff70d"
-"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
-"checksum clap 2.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ae14fd6c0dfcaab81ac4413928edb79dd7fd04634f7bfffe1af64946eec3b4d2"
-"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
-"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
-"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
-"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
-"checksum serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0e0732aa8ec4267f61815a396a942ba3525062e3bd5520aa8419927cfc0a92"
-"checksum serde_json 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b22e8a0554f31cb0f501e027de07b253553b308124f61c57598b9678dba35c0b"
-"checksum strsim 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5f575d5ced6634a5c4cb842163dab907dc7e9148b28dc482d81b8855cbe985"
+"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
+"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
+"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727"
+"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
+"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
+"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
+"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe"
+"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
+"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
+"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
+"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
+"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
+"checksum failure 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e945b93ec214c6e97b520ec6c5d80267fc97af327658ee5b9f35984626e51fbf"
+"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
+"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
+"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
+"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
+"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
+"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9"
+"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
+"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
+"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
+"checksum redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f22c50afdcf3f0a31ebb6b47697f6a7c5e5a24967e842858118bce0615f0afad"
+"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
+"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
+"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
+"checksum rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "01b90379b8664dd83460d59bdc5dd1fd3172b8913788db483ed1325171eab2f7"
+"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)" = "157e12af46859e968da75dea9845530e13d03bcab2009a41b9b7bb3cf4eb3ec2"
+"checksum serde_derive 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)" = "9469829702497daf2daf3c190e130c3fa72f719920f73c86160d43e8f8d76951"
+"checksum serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bdf540260cfee6da923831f4776ddc495ada940c30117977c70f1313a6130545"
+"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
+"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3"
+"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04"
+"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc"
+"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
+"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
+"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
+"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
+"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
+"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
 "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
-"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
+"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
+"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
+"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
diff --git a/Cargo.toml b/Cargo.toml
index 6dde59d..b3f1930 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,8 +1,9 @@
 [package]
 name = "cargo-lipo"
-version = "2.0.0"
+version = "3.0.0"
 authors = ["Tim Neumann <mail@timnn.me>"]
 description = "cargo lipo subcommand to automatically create universal libraries for iOS"
+edition = "2018"
 
 homepage = "https://github.com/TimNN/cargo-lipo"
 repository = "https://github.com/TimNN/cargo-lipo"
@@ -14,5 +15,9 @@ keywords = ["cargo", "iOS"]
 license = "MIT/Apache-2.0"
 
 [dependencies]
-clap = "~2.2.3"
-serde_json = "0.7.0"
+cargo_metadata = "0.6"
+clap = "2.32"
+env_logger = "0.6"
+failure = { version = "0.1", default-features = false, features = ["std"] }
+log = "0.4"
+structopt = "0.2"
diff --git a/README.md b/README.md
index aac8669..43cb4c0 100644
--- a/README.md
+++ b/README.md
@@ -14,23 +14,41 @@ name = "..."
 crate-type = ["staticlib"]
 ```
 
+### XCode Integration
+
+`cargo-lipo` easily integrates with XCode. Although note that his functionality has only been added recently and may not yet be perfect (the XCode build process is somewhat of a blackbox to me).
+
+1. In your *"Build Settings"* change *"Enable Bitcode"* to **`No`**.
+
+2. Add a new *"Run Script"* phase to your *"Build Phases"*. Place it **before** *"Compile Sources"*. Add something like the following to the script:
+
+    ```bash
+    # The $PATH used by XCode likely won't contain Cargo, fix that.
+    # This assumes a default `rustup` setup.
+    export PATH="$HOME/.cargo/bin:$PATH"
+
+    # --xcode-integ determines --release and --targets from XCode's env vars.
+    # Depending your setup, specify the rustup toolchain explicitly.
+    cargo-lipo --xcode-integ --manifest-path ../something/Cargo.toml
+    ```
+
+3. Build the project once, then update the *"Link Binary with Libraries"* phase: Click the <kbd>+</kbd>, then choose *"Add Other..."*. Navigate to `your-cargo-project/target/universal/{debug-or-release}` and select your library(s).
+
+4. Go back to your *"Build Settings"* and add *"Library Search Paths"* for *"Debug"* and *"Release"*, pointing to `your-cargo-project/target/universal/{debug-or-release}`.
+
 ## Installation
 
-Install `cargo lipo` with `cargo install cargo-lipo`. `cargo lipo` can be build with rust 1.8 and later.
+Install `cargo lipo` with `cargo install cargo-lipo`. `cargo lipo` should always be buildable with the latest stable Rust version. For the minimum supported version check `.travis.yml`.
 
 You also need a rust compiler which can compile for the iOS targets. If you use [rustup](https://www.rustup.rs/) all you should have to do is
 
 ```sh
-rustup target add aarch64-apple-ios
-rustup target add armv7-apple-ios
-rustup target add i386-apple-ios
-rustup target add x86_64-apple-ios
+# 64 bit targets (real device & simulator):
+rustup target add aarch64-apple-ios x86_64-apple-ios
+# 32 bit targets (you probably don't need these):
+rustup target add armv7-apple-ios i386-apple-ios
 ```
 
-**Note:** This should work on stable starting with the 1.8 release.
-
-Alternatively you can build a rust compiler with iOS support yourself.
-
 ## Troubleshooting
 
  Cargo fails with ``error: can't find crate for `std` ``: Your rust compiler most likely does not support cross-compiling to iOS.
diff --git a/integration.bats.sh b/integration.bats.sh
new file mode 100755
index 0000000..37f8744
--- /dev/null
+++ b/integration.bats.sh
@@ -0,0 +1,112 @@
+#!/usr/bin/env bats
+
+check_env() {
+    if [ -n "${CARGO_LIPO_TEST_DIRECT_CALL+x}" ]; then
+        export CARGO_LIPO="cargo-lipo lipo --color=always"
+
+        cat > xcode/.xcode-lipo <<EOF
+#!/bin/bash
+
+exec $BATS_TEST_DIRNAME/target/debug/cargo-lipo "\$@"
+EOF
+
+        chmod +x xcode/.xcode-lipo
+
+        return
+    fi
+
+    local CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}"
+
+    if [ -e "$CARGO_HOME/bin/cargo-lipo" ]; then
+        echo 'ERROR: cargo-lipo exists in $CARGO_HOME/bin. This is a problem because Cargo'
+        echo 'ERROR: will always search that directory first. Either remove that file or'
+        echo 'ERROR: define $CARGO_LIPO_TEST_DIRECT_CALL'
+        return 1
+    fi
+
+    export CARGO_LIPO="cargo lipo --color=always"
+}
+
+check_archs() {
+    # awk is used to trim a trailing space.
+    local actual="$(lipo -archs "$2" | awk '{$1=$1};1' |  tr ' ' '\n' | sort | paste -sd',' -)"
+    if [ "$1" != "$actual" ]; then
+        echo "Expected: [$1], actual: [$actual]"
+        return 1
+    fi
+}
+
+xcode() {
+    xcodebuild -workspace xcode/cargo-lipo-test.xcodeproj/project.xcworkspace -scheme cargo-lipo-test -configuration $2 -sdk iphonesimulator12.1 $1
+}
+
+setup() {
+    cd "$BATS_TEST_DIRNAME/testdata"
+    rm -rf {simple,workspace}/target
+
+    check_env
+
+    cargo build --color=always --manifest-path "$BATS_TEST_DIRNAME/Cargo.toml"
+    export PATH="$BATS_TEST_DIRNAME/target/debug:$PATH"
+}
+
+@test "build simple in directory" {
+    (cd simple && ${CARGO_LIPO})
+    check_archs arm64,x86_64 simple/target/universal/debug/libsimple.a
+}
+
+@test "build simple in subdirectory" {
+    (cd simple/src && ${CARGO_LIPO})
+    check_archs arm64,x86_64 simple/target/universal/debug/libsimple.a
+}
+
+@test "build simple with --manifest-path" {
+    ${CARGO_LIPO} --manifest-path simple/Cargo.toml
+    check_archs arm64,x86_64 simple/target/universal/debug/libsimple.a
+}
+
+@test "build simple with --release" {
+    ${CARGO_LIPO} --release --manifest-path simple/Cargo.toml
+    check_archs arm64,x86_64 simple/target/universal/release/libsimple.a
+}
+
+@test "build simple with --targets" {
+    ${CARGO_LIPO} --targets aarch64-apple-ios --manifest-path simple/Cargo.toml
+    check_archs arm64 simple/target/universal/debug/libsimple.a
+}
+
+@test "build single project from workspace" {
+    ${CARGO_LIPO} -p static1 --manifest-path workspace/Cargo.toml
+    check_archs arm64,x86_64 workspace/target/universal/debug/libstatic1.a
+}
+
+@test "build project with build script" {
+    ${CARGO_LIPO} -p static2build --manifest-path workspace/Cargo.toml
+    check_archs arm64,x86_64 workspace/target/universal/debug/libstatic2build.a
+}
+
+@test "build project with multiple targets" {
+    ${CARGO_LIPO} -p static3bin --manifest-path workspace/Cargo.toml
+    check_archs arm64,x86_64 workspace/target/universal/debug/libstatic3bin.a
+}
+
+@test "build all from workspace" {
+    ${CARGO_LIPO} --manifest-path workspace/Cargo.toml
+    check_archs arm64,x86_64 workspace/target/universal/debug/libstatic1.a
+    check_archs arm64,x86_64 workspace/target/universal/debug/libstatic2build.a
+    check_archs arm64,x86_64 workspace/target/universal/debug/libstatic3bin.a
+}
+
+@test "xcode build debug for simulator" {
+    xcode "clean build" Debug
+    check_archs x86_64 workspace/target/universal/debug/libstatic1.a
+    check_archs x86_64 workspace/target/universal/debug/libstatic2build.a
+    check_archs x86_64 workspace/target/universal/debug/libstatic3bin.a
+}
+
+@test "xcode build release for simulator" {
+    xcode "clean build" Release
+    check_archs x86_64 workspace/target/universal/release/libstatic1.a
+    check_archs x86_64 workspace/target/universal/release/libstatic2build.a
+    check_archs x86_64 workspace/target/universal/release/libstatic3bin.a
+}
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..0e680f6
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,13 @@
+edition = "2018"
+newline_style = "Unix"
+# I prefer crate -> self -> super
+reorder_imports = false
+use_small_heuristics = "Max"
+
+# Unstable options that can't be used on stable.
+#enum_discrim_align_threshold = 20
+#error_on_line_overflow = true
+#error_on_unformatted = true
+#format_macro_matchers = true
+#format_strings = true
+#wrap_comments = true
diff --git a/src/cargo.rs b/src/cargo.rs
new file mode 100644
index 0000000..382ca23
--- /dev/null
+++ b/src/cargo.rs
@@ -0,0 +1,92 @@
+use crate::{Invocation, Result};
+use std::env;
+use std::ffi::OsString;
+use std::process::Command;
+
+pub(crate) struct Cargo<'a> {
+    cargo: OsString,
+    invocation: &'a Invocation,
+}
+
+impl<'a> Cargo<'a> {
+    pub(crate) fn new(invocation: &'a Invocation) -> Cargo {
+        Cargo { cargo: env::var_os("CARGO").unwrap_or_else(|| "cargo".into()), invocation }
+    }
+
+    pub(crate) fn build_lib(&self, name: &str, target: &str) -> Result<()> {
+        crate::exec::run(self.prepare_build_lib(name, target))
+    }
+
+    pub(crate) fn profile(&self) -> &str {
+        if self.invocation.release {
+            "release"
+        } else {
+            "debug"
+        }
+    }
+
+    fn prepare(&self) -> Command {
+        let mut cmd = Command::new(&self.cargo);
+
+        cmd.arg("--color").arg(self.invocation.color.value());
+
+        if self.invocation.verbose > 1 {
+            cmd.arg(format!("-{}", "v".repeat(self.invocation.verbose as usize)));
+        }
+
+        if self.invocation.locked {
+            cmd.arg("--locked");
+        }
+
+        if self.invocation.frozen {
+            cmd.arg("--frozen");
+        }
+
+        if !self.invocation.no_sanitize_env {
+            crate::xcode::sanitize_env(&mut cmd);
+        }
+
+        cmd
+    }
+
+    fn prepare_target(&self, sub_command: &str, name: &str, target: &str) -> Command {
+        let mut cmd = self.prepare();
+        cmd.arg(sub_command);
+
+        if let Some(ref path) = self.invocation.manifest_path {
+            cmd.arg("--manifest-path").arg(path);
+        }
+
+        cmd.arg("-p").arg(name).arg("--target").arg(target);
+
+        if self.invocation.release {
+            cmd.arg("--release");
+        }
+
+        cmd
+    }
+
+    fn prepare_build_lib(&self, name: &str, target: &str) -> Command {
+        let mut cmd = self.prepare_target("build", name, target);
+
+        cmd.arg("--lib");
+
+        if self.invocation.all_features {
+            cmd.arg("--all-features");
+        }
+
+        if self.invocation.no_default_features {
+            cmd.arg("--no-default-features");
+        }
+
+        if let Some(ref features) = self.invocation.features {
+            cmd.arg("--features").arg(features);
+        }
+
+        if let Some(jobs) = self.invocation.jobs {
+            cmd.arg("--jobs").arg(jobs.to_string());
+        }
+
+        cmd
+    }
+}
diff --git a/src/exec.rs b/src/exec.rs
new file mode 100644
index 0000000..75f64ca
--- /dev/null
+++ b/src/exec.rs
@@ -0,0 +1,16 @@
+use crate::Result;
+use failure::{bail, ResultExt};
+use log::debug;
+use std::process::Command;
+
+pub fn run(mut cmd: Command) -> Result<()> {
+    debug!("Running: {:?}", cmd);
+
+    let status = cmd.status().with_context(|e| format!("Executing {:?} failed: {}", cmd, e))?;
+
+    if !status.success() {
+        bail!("Executing {:?} finished with error status: {}", cmd, status);
+    }
+
+    Ok(())
+}
diff --git a/src/json_macros.rs b/src/json_macros.rs
deleted file mode 100644
index 92567d4..0000000
--- a/src/json_macros.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-/// Retrieve a value of type `serde_json::Value::$Var` from the given `$value: serde_json::Value`
-/// located at `$path$.
-///
-/// Returns `Result<_, &str>`.
-macro_rules! json_get {($Var:ident, $value:ident $(.$path:ident)+) => (
-    $value.find_path(&[$(stringify!($path)),*])
-          .ok_or(concat!("no such value: ", stringify!($value), $(".", stringify!($path)),*))
-          .and_then(|val| match val {
-              &::json::Value::$Var(ref var) => ::std::result::Result::Ok(var),
-              _ => Err(concat!("incorrect value type, expected: ", stringify!($Var))),
-          });
-)}
diff --git a/src/lipo.rs b/src/lipo.rs
new file mode 100644
index 0000000..caf41b5
--- /dev/null
+++ b/src/lipo.rs
@@ -0,0 +1,50 @@
+use crate::Result;
+use crate::cargo::Cargo;
+use crate::meta::Meta;
+use failure::ResultExt;
+use log::info;
+use std::fs;
+use std::process::Command;
+
+pub(crate) fn build(cargo: &Cargo, meta: &Meta, targets: &[impl AsRef<str>]) -> Result<()> {
+    for package in meta.packages() {
+        let lib_name = format!("lib{}.a", package.lib_name());
+        let mut inputs = vec![];
+
+        for target in targets {
+            let target = target.as_ref();
+            info!("Building {:?} for {:?}", package.name(), target);
+
+            cargo.build_lib(package.name(), target).with_context(|e| {
+                format!("Failed to build {:?} for {:?}: {}", package.name(), target, e)
+            })?;
+
+            let mut input = meta.target_dir().to_owned();
+            input.push(target);
+            input.push(cargo.profile());
+            input.push(&lib_name);
+
+            inputs.push(input);
+        }
+
+        let mut output = meta.target_dir().to_owned();
+        output.push("universal");
+        output.push(cargo.profile());
+
+        fs::create_dir_all(&output).with_context(|e| {
+            format!("Creating output directory \"{}\" failed: {}", output.display(), e)
+        })?;
+
+        output.push(&lib_name);
+
+        let mut cmd = Command::new("lipo");
+        cmd.arg("-create").arg("-output").arg(output);
+        cmd.args(inputs);
+
+        info!("Creating universal library for {}", package.name());
+
+        crate::exec::run(cmd)?;
+    }
+
+    Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index 6f11024..6acac5a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,221 +1,204 @@
-extern crate clap;
-extern crate serde_json as json;
-
-use clap::{App, SubCommand};
-use std::fs;
-use std::path::{Path, PathBuf};
-use std::process::{self, Command, ExitStatus};
-use std::result::Result as StdResult;
-
-use msg_error::{Error, Result};
-
-#[macro_use] mod json_macros;
-#[macro_use] mod msg_error;
-
-static IOS_TRIPLES: &'static [&'static str] = &[
-    "aarch64-apple-ios",
-    "armv7-apple-ios",
-    "i386-apple-ios",
-    "x86_64-apple-ios",
-];
-
-fn main() {
-    #[cfg(not(any(test, target = "i686-apple-darwin", target = "x86_64-apple-darwin")))]
-    println!("Due to a known rustc issue, cargo-lipo can only be run on macOS. \
-              See https://github.com/rust-lang/rust/issues/36156#issuecomment-373201676 \
-              for more info.");
-
-    if let Err(err) = real_main() {
-        println!("{}", err);
-        process::exit(1);
-    }
+#![allow(clippy::needless_pass_by_value, clippy::new_ret_no_self, clippy::single_char_pattern)]
+#![deny(unused_must_use)]
+
+use failure::ResultExt;
+use log::{error, warn, trace};
+use std::cmp;
+use std::ffi::OsString;
+use std::path::PathBuf;
+use std::process;
+use structopt::StructOpt;
+
+mod cargo;
+mod exec;
+mod lipo;
+mod meta;
+mod xcode;
+
+type Result<T> = std::result::Result<T, failure::Error>;
+
+/// Automatically create universal libraries.
+#[derive(StructOpt, Debug)]
+#[structopt(name = "cargo-lipo", bin_name = "cargo")]
+#[structopt(author = "")]
+#[structopt(raw(setting = "clap::AppSettings::SubcommandRequiredElseHelp"))]
+struct CargoInvocation {
+    #[structopt(subcommand)]
+    cmd: Command,
 }
 
-fn real_main() -> Result<()> {
-    let matches = build_app().get_matches();
-    let matches = trm!("Invalid invocation"; matches.subcommand_matches("lipo").ok_or("subcommand required"));
-
-    let release = matches.is_present("release");
-    let verbose = matches.is_present("verbose");
-
-    let lib_name = try!(find_lib_name(verbose));
-
-    let triples: Vec<&str> = match matches.values_of("targets") {
-        Some(values) => values.collect(),
-        None => IOS_TRIPLES.to_vec(),
-    };
-
-    let features = matches.value_of("features").unwrap_or("");
-    let no_default_features = matches.is_present("no-default-features");
-
-    let color = matches.value_of("color").unwrap_or("auto");
-
-    for triple in &triples {
-        try!(build_triple(BuildOptions {
-            triple,
-            release,
-            verbose,
-            features,
-            color,
-            no_default_features,
-        }));
-    }
-
-    let target_path = try!(find_target_path(verbose));
-    let target_subdir = if release { "release" } else { "debug" };
-
-    let out_dir = target_path.join("universal").join(&target_subdir);
-    let out = out_dir.join(&lib_name);
-
-    trm!("Failed to create output directory"; fs::create_dir_all(&out_dir));
-
-    let mut cmd = Command::new("lipo");
-    cmd.args(&["-create", "-output"]);
-    cmd.arg(out.as_os_str());
-
-    for triple in &triples {
-        cmd.arg(target_path.join(triple).join(target_subdir).join(&lib_name).as_os_str());
-    }
-
-    let status = trm!("Failed to execute lipo"; cmd.status());
-
-    trm!("lipo exited unsuccessfully"; exit_to_result(status));
-
-    Ok(())
-}
-
-fn build_app<'a, 'b>() -> App<'a, 'b> {
-    App::new("cargo-lipo")
-        .version(env!("CARGO_PKG_VERSION"))
-        .author("Tim Neumann <mail@timnn.me>")
-        .about("This binary should only be executed as a custom cargo subcommand (ie. `cargo lipo`)")
-        .bin_name("cargo")
-        .subcommand(SubCommand::with_name("lipo")
-            .version(env!("CARGO_PKG_VERSION"))
-            .author("Tim Neumann <mail@timnn.me>")
-            .about("Automatically create universal libraries")
-            .args_from_usage("--release 'Compiles in release mode'
-                              --targets=[TRIPLE1,TRIPLE2] 'Build for the target triples'
-                              --features=[FEATURES] 'Space-separated list of features to also build'
-                              --no-default-features 'Do not activate the `default` feature'
-                              --color=[WHEN] 'Coloring: auto, always, never'
-                              -v --verbose 'Print additional information'")
-        )
+#[derive(StructOpt, Debug)]
+enum Command {
+    /// Automatically create universal libraries.
+    #[structopt(name = "lipo")]
+    #[structopt(author = "")]
+    Invocation(Invocation),
 }
 
-/// Struct containing arguments for `build_triple`.
-#[derive(Debug, Clone)]
-struct BuildOptions<'a> {
-    pub triple: &'a str,
-    pub release: bool,
-    pub verbose: bool,
-    pub features: &'a str,
-    pub color: &'a str,
-    pub no_default_features: bool,
+#[derive(StructOpt, Debug)]
+struct Invocation {
+    /// Coloring: auto, always, never
+    #[structopt(long, default_value = "auto", value_name = "WHEN")]
+    color: Coloring,
+
+    /// Use verbose output (-vv very verbose output)
+    #[structopt(long, short)]
+    #[structopt(parse(from_occurrences))]
+    verbose: u32,
+
+    /// Override the check for running on macOS
+    #[structopt(long = "allow-run-on-non-macos")]
+    run_on_non_macos: bool,
+
+    /// Determine `targets` and `release` from the environment provided by XCode to build scripts.
+    #[structopt(long = "xcode-integ")]
+    #[structopt(conflicts_with = "release", conflicts_with = "targets")]
+    xcode_integ: bool,
+
+    /// Don't run `cargo clean` when XCode cleans the project.
+    #[structopt(long = "xcode-ignore-clean")]
+    #[structopt(requires = "xcode_integ")]
+    xcode_ignore_clean: bool,
+
+    /// Don't remove environment variables that can cause issues with build scripts when calling
+    /// cargo.
+    #[structopt(long = "no-sanitize-env")]
+    no_sanitize_env: bool,
+
+    /// Build artifacts in release mode, with optimizations
+    #[structopt(long)]
+    release: bool,
+
+    /// Require Cargo.lock and cache are up to date
+    #[structopt(long)]
+    frozen: bool,
+
+    /// Require Cargo.lock is up to date
+    #[structopt(long)]
+    locked: bool,
+
+    /// Number of parallel jobs to be used by Cargo, defaults to # of CPUs
+    #[structopt(long, short, value_name = "N")]
+    jobs: Option<u32>,
+
+    /// Build all packages in the workspace (that have a `staticlib` target)
+    #[structopt(long)]
+    all: bool,
+
+    /// Package(s) to build (must have a `staticlib` target)
+    #[structopt(short, long = "package", value_name = "NAME")]
+    #[structopt(conflicts_with = "all")]
+    packages: Vec<String>,
+
+    /// Activate all available features
+    #[structopt(long = "all-features")]
+    all_features: bool,
+
+    /// Path to Cargo.toml
+    #[structopt(long = "no-default-features")]
+    no_default_features: bool,
+
+    /// Space-separated list of features to activate
+    #[structopt(long, value_name = "FEATURES")]
+    #[structopt(parse(from_os_str))]
+    features: Option<OsString>,
+
+    /// Path to Cargo.toml
+    #[structopt(long = "manifest-path", value_name = "PATH")]
+    #[structopt(parse(from_os_str))]
+    manifest_path: Option<PathBuf>,
+
+    /// Build for the target triples
+    #[structopt(long, value_name = "TARGET1,TARGET2")]
+    #[structopt(value_delimiter = ",")]
+    #[structopt(default_value = "aarch64-apple-ios,x86_64-apple-ios")]
+    targets: Vec<String>,
 }
 
-/// Invoke `cargo build` for the given triple.
-fn build_triple(build: BuildOptions) -> Result<()> {
-    let mut cmd = Command::new("cargo");
-    cmd.args(&[
-        "build",
-        "--target", build.triple,
-        "--lib",
-        "--features", build.features,
-        "--color", build.color]);
-
-    if build.release { cmd.arg("--release"); }
-    if build.verbose { cmd.arg("--verbose"); }
-    if build.no_default_features { cmd.arg("--no-default-features"); }
-
-    log_command(&cmd, build.verbose);
+fn main() {
+    let cargo = CargoInvocation::from_args();
+    let Command::Invocation(invocation) = cargo.cmd;
+
+    env_logger::Builder::from_default_env()
+        .default_format_timestamp(false)
+        .write_style(invocation.color.log_style())
+        .filter_module(
+            "cargo_lipo",
+            [log::LevelFilter::Info, log::LevelFilter::Debug, log::LevelFilter::Trace]
+                [cmp::min(invocation.verbose, 2) as usize],
+        )
+        .init();
 
-    let status = trm!("Failed to build library for {}", build.triple; cmd.status());
-    trm!("Cargo exited unsuccessfully"; exit_to_result(status));
+    trace!("Invocation: {:#?}", invocation);
 
-    Ok(())
+    if let Err(e) = run(invocation) {
+        error!("{}", e);
+        std::process::exit(1);
+    }
 }
 
-/// Find the name of the staticlibrary to build as defined in the project's `Cargo.toml`.
-fn find_lib_name(verbose: bool) -> Result<String> {
-    static ERR: &'static str = "Failed to parse `cargo read-manifest` output";
-
-    let value = trm!(ERR; cargo_json_value("read-manifest", verbose));
-
-    let targets = trm!(ERR; json_get!(Array, value.targets));
-
-    let mut lib_name = None;
-
-    for target in targets {
-        let kinds = trm!(ERR; json_get!(Array, target.kind));
-
-        for kind in kinds {
-            let kind = trm!(ERR; kind.as_string().ok_or("kind is not a string"));
-
-            if kind == "staticlib" {
-                if let Some(_) = lib_name {
-                    return Err(Error::new(ERR, "Multiple targets with kind `staticlib` found"));
-                }
-
-                lib_name = Some(trm!(ERR; json_get!(String, target.name)));
-            }
+fn run(invocation: Invocation) -> Result<()> {
+    if !cfg!(target_os = "macos") {
+        if invocation.run_on_non_macos {
+            warn!("Running on non-macOS, `cargo lipo` will likely not work");
+        } else {
+            error!(
+                "Running on non-macOS, `cargo lipo` will likely not work. \
+                 Use `--allow-run-on-non-macos` to override this check."
+            );
+            process::exit(1);
         }
     }
 
-    match lib_name {
-        Some(name) => Ok(String::from("lib") + &name.replace("-", "_") + ".a"),
-        None => Err(Error::new(ERR, "No target with kind `staticlib` found")),
-    }
-}
-
-/// Find the path to the project's `target` directory.
-fn find_target_path(verbose: bool) -> Result<PathBuf> {
-    static ERR: &'static str = "Failed to parse `cargo metadata`";
-    static ERR2: &'static str = "Failed to verify target directory";
+    let meta = cargo_metadata::metadata(invocation.manifest_path.as_ref().map(|p| p.as_ref()))
+        .map_err(failure::SyncFailure::new)
+        .with_context(|e| format!("cargo_metadata failed: {}", e))?;
 
-    let value = trm!(ERR; cargo_json_value("metadata", verbose));
+    trace!("Metadata: {:#?}", meta);
 
-    let target_directory = trm!(ERR; json_get!(String, value.target_directory));
-    let target: &Path = target_directory.as_ref();
+    let meta = meta::Meta::new(&invocation, &meta)?;
 
-    let meta = trm!(ERR2; fs::metadata(&target));
-
-    if !meta.is_dir() {
-        Err(Error::new(ERR2, "not a directory"))
+    if invocation.xcode_integ {
+        xcode::integ(&meta, invocation)
     } else {
-        Ok(target.to_path_buf())
+        lipo::build(&cargo::Cargo::new(&invocation), &meta, &invocation.targets)
     }
 }
 
-/// Create a `serde_json::Value` from the output of the given cargo subcomand.
-fn cargo_json_value(subcommand: &str, verbose: bool) -> Result<json::Value> {
-    let mut cmd = Command::new("cargo");
-    cmd.arg(subcommand);
-
-    log_command(&cmd, verbose);
-
-    let output = trm!("Failed to execute cargo"; cmd.output());
-
-    trm!("Cargo exited unsuccessfully"; exit_to_result(output.status));
-
-    let json = trm!("Invalid json"; String::from_utf8(output.stdout));
-    let value = trm!("Invalid json"; json::from_str(&json));
-
-    Ok(value)
+#[derive(Copy, Clone, Debug)]
+enum Coloring {
+    Auto,
+    Always,
+    Never,
 }
 
-/// Convert an `ExitStatus` into a `Result`.
-fn exit_to_result(exit: ExitStatus) -> StdResult<(), String> {
-    if exit.success() {
-        Ok(())
-    } else {
-        Err(exit.to_string())
+impl Coloring {
+    pub fn value(self) -> &'static str {
+        match self {
+            Coloring::Auto => "auto",
+            Coloring::Always => "always",
+            Coloring::Never => "never",
+        }
+    }
+
+    pub fn log_style(self) -> env_logger::WriteStyle {
+        match self {
+            Coloring::Auto => env_logger::WriteStyle::Auto,
+            Coloring::Always => env_logger::WriteStyle::Always,
+            Coloring::Never => env_logger::WriteStyle::Never,
+        }
     }
 }
 
-/// Log the given command to stdout if running in verbose mode.
-fn log_command(cmd: &Command, verbose: bool) {
-    if verbose {
-        println!("Executing: {:?}", cmd);
+impl std::str::FromStr for Coloring {
+    type Err = String;
+
+    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+        match s {
+            "auto" => Ok(Coloring::Auto),
+            "always" => Ok(Coloring::Always),
+            "never" => Ok(Coloring::Never),
+            _ => Err(format!("Invalid coloring: '{}'", s)),
+        }
     }
 }
diff --git a/src/meta.rs b/src/meta.rs
new file mode 100644
index 0000000..77635a3
--- /dev/null
+++ b/src/meta.rs
@@ -0,0 +1,116 @@
+use crate::{Invocation, Result};
+use failure::bail;
+use log::{info, debug};
+use std::path::Path;
+
+pub(crate) struct Meta<'a> {
+    packages: Vec<Package<'a>>,
+    target_dir: &'a Path,
+}
+
+pub(crate) struct Package<'a> {
+    name: &'a str,
+    lib_name: &'a str,
+}
+
+impl<'a> Meta<'a> {
+    #[allow(clippy::useless_let_if_seq)] // multiple variables are initialized
+    pub(crate) fn new(
+        invocation: &Invocation,
+        meta: &'a cargo_metadata::Metadata,
+    ) -> Result<Meta<'a>> {
+        let package_names: Vec<_>;
+        let staticlib_required;
+
+        if !invocation.packages.is_empty() {
+            package_names = invocation.packages.iter().map(|p| p.as_str()).collect();
+            staticlib_required = true;
+        } else {
+            package_names = meta.workspace_members.iter().map(|m| m.name()).collect();
+            // Require a staticlib for single-member workspaces unless `--all` was specified.
+            staticlib_required = meta.workspace_members.len() == 1 && !invocation.all;
+        }
+
+        debug!(
+            "Considering package(s) {:?}, `staticlib` target {}",
+            package_names,
+            if staticlib_required { "required" } else { "not required" }
+        );
+
+        let mut packages = vec![];
+
+        for &name in &package_names {
+            let package = match meta.packages.iter().find(|p| p.name == name) {
+                Some(p) => p,
+                None => bail!("No package metadata found for {:?}", name),
+            };
+
+            let lib_targets: Vec<_> = package
+                .targets
+                .iter()
+                .filter(|t| t.kind.iter().any(|k| k == "staticlib"))
+                .collect();
+
+            match lib_targets.as_slice() {
+                [] => {
+                    if !staticlib_required {
+                        debug!("Ignoring {:?} because it does not have a `staticlib` target", name);
+                        continue;
+                    }
+                    bail!("No library target found for {:?}", name);
+                }
+                [target] => {
+                    if target.crate_types.iter().any(|ct| ct == "staticlib") {
+                        packages.push((package, target.name.as_str()));
+                    } else {
+                        if !staticlib_required {
+                            debug!(
+                                "Ignoring {:?} because it does not have a `staticlib` crate type",
+                                name
+                            );
+                            continue;
+                        }
+                        bail!("No staticlib crate type found for {:?}", name);
+                    }
+                }
+                _ => bail!("Found multiple lib targets for {:?}", name),
+            }
+        }
+
+        let packages = packages
+            .iter()
+            .map(|(p, lib_name)| Package { name: p.name.as_str(), lib_name })
+            .collect::<Vec<_>>();
+
+        let package_names = packages.iter().map(|p| p.name).collect::<Vec<_>>();
+
+        if packages.is_empty() {
+            bail!(
+                "Did not find any packages with a `staticlib` target, considered {:?}",
+                package_names
+            );
+        }
+
+        info!("Will build universal library for {:?}", package_names);
+
+        Ok(Meta { packages, target_dir: Path::new(&meta.target_directory) })
+    }
+
+    pub(crate) fn packages(&self) -> &[Package<'a>] {
+        &self.packages
+    }
+
+    pub(crate) fn target_dir(&self) -> &'a Path {
+        self.target_dir
+    }
+}
+
+impl<'a> Package<'a> {
+    pub(crate) fn name(&self) -> &'a str {
+        self.name
+    }
+
+    pub(crate) fn lib_name(&self) -> &'a str {
+        self.lib_name
+    }
+}
diff --git a/src/msg_error.rs b/src/msg_error.rs
deleted file mode 100644
index dc5aa6e..0000000
--- a/src/msg_error.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use std::fmt;
-use std::result;
-
-/// A Result who's error type is `msg_error::Error`.
-pub type Result<T> = result::Result<T, Error>;
-
-/// An error consiting of a message.
-#[derive(Debug)]
-pub struct Error {
-    msg: String,
-}
-
-impl Error {
-    /// Create a new error with format `"$msg: $err"`.
-    pub fn new<E: fmt::Display>(msg: &str, err: E) -> Error {
-        Error {
-            msg: format!("{}: {}", msg, err),
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.msg)
-    }
-}
-
-/// Like `try!` but also takes a `format!` like message as the first argument and always returns
-/// a `msg_error::Result`.
-macro_rules! trm {
-    ($msg:tt; $expr:expr) => (trm!("{}", $msg; $expr));
-    ($($msg:expr),+ ; $expr:expr) => (match $expr {
-        ::std::result::Result::Ok(val) => val,
-        ::std::result::Result::Err(err) => {
-            let msg = format!($($msg),*);
-            let err = ::msg_error::Error::new(&msg, err);
-            return ::std::result::Result::Err(err);
-        }
-    });
-}
diff --git a/src/xcode.rs b/src/xcode.rs
new file mode 100644
index 0000000..6defc3d
--- /dev/null
+++ b/src/xcode.rs
@@ -0,0 +1,56 @@
+use crate::{Invocation, Result};
+use crate::meta::Meta;
+use failure::{bail, ResultExt};
+use log::warn;
+use std::env;
+use std::process::Command;
+
+pub(crate) fn integ(meta: &Meta, mut invocation: Invocation) -> Result<()> {
+    if is_release_configuration() {
+        invocation.release = true;
+    }
+
+    let cargo = crate::cargo::Cargo::new(&invocation);
+
+    match env::var("ACTION").with_context(|e| format!("Failed to read $ACTION: {}", e))?.as_str() {
+        "build" => {
+            crate::lipo::build(&cargo, meta, &targets_from_env()?)?;
+        }
+        action => warn!("Unsupported XCode action: {:?}", action),
+    }
+
+    Ok(())
+}
+
+fn targets_from_env() -> Result<Vec<&'static str>> {
+    let archs = env::var("ARCHS").with_context(|e| format!("Failed to read $ARCHS: {}", e))?;
+    Ok(archs
+        .split(" ")
+        .map(|a| a.trim())
+        .filter(|a| !a.is_empty())
+        .map(map_arch_to_target)
+        .collect::<Result<Vec<_>>>()
+        .with_context(|e| format!("Failed to parse $ARCHS: {}", e))?)
+}
+
+fn is_release_configuration() -> bool {
+    env::var("CONFIGURATION").map(|v| v == "Release").unwrap_or(false)
+}
+
+fn map_arch_to_target(arch: &str) -> Result<&'static str> {
+    match arch {
+        "armv7" => Ok("armv7-apple-ios"),
+        "arm64" => Ok("aarch64-apple-ios"),
+        "i386" => Ok("i386-apple-ios"),
+        "x86_64" => Ok("x86_64-apple-ios"),
+        _ => bail!("Unknown arch: {:?}", arch),
+    }
+}
+
+pub(crate) fn sanitize_env(cmd: &mut Command) {
+    cmd.env_clear();
+    cmd.envs(env::vars_os().filter(|&(ref name, _)| match name.to_str() {
+        Some(name) => !(name.ends_with("DEPLOYMENT_TARGET") || name.starts_with("SDK")),
+        None => false,
+    }));
+}


Test patch:
diff --git a/testdata/Readme.md b/testdata/Readme.md
new file mode 100644
index 0000000..3c29fae
--- /dev/null
+++ b/testdata/Readme.md
@@ -0,0 +1,12 @@
+# Test Data
+
+This directory contains Cargo projects to test `cargo-lipo` with:
+
+* `simple/`: Contains a single `staticlib`
+* `workspace/`: A workspace with multiple projects
+    * `buildutil`: To be used as a build dependency. Has itself a build script.
+    * `normal`: A "normal" rust library crate.
+    * `static1`: A simple `staticlib`, depends on `normal`.
+    * `static2build`: A `staticlib` with a build script. Library and build script both depend on `buildutil`.
+    * `static3bin`: Contains `staticlib`, that is also an `rlib`, as well as a `bin` target.
+* `xcode/`: A XCode project depending on all `staticlib`s from `workspace`.
diff --git a/testdata/simple/.gitignore b/testdata/simple/.gitignore
new file mode 100644
index 0000000..042776a
--- /dev/null
+++ b/testdata/simple/.gitignore
@@ -0,0 +1,2 @@
+/Cargo.lock
+/target/
diff --git a/testdata/simple/Cargo.toml b/testdata/simple/Cargo.toml
new file mode 100644
index 0000000..c479e08
--- /dev/null
+++ b/testdata/simple/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "simple"
+version = "0.1.0"
+authors = ["Tim Neumann <mail@timnn.me>"]
+edition = "2018"
+
+[lib]
+crate-type = ["staticlib"]
diff --git a/testdata/simple/src/lib.rs b/testdata/simple/src/lib.rs
new file mode 100644
index 0000000..355bd38
--- /dev/null
+++ b/testdata/simple/src/lib.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub extern "C" fn hello_from_simple() {
+    println!("Hello from Simple!");
+}
diff --git a/testdata/workspace/.gitignore b/testdata/workspace/.gitignore
new file mode 100644
index 0000000..042776a
--- /dev/null
+++ b/testdata/workspace/.gitignore
@@ -0,0 +1,2 @@
+/Cargo.lock
+/target/
diff --git a/testdata/workspace/Cargo.toml b/testdata/workspace/Cargo.toml
new file mode 100644
index 0000000..0c4ef1b
--- /dev/null
+++ b/testdata/workspace/Cargo.toml
@@ -0,0 +1,9 @@
+[workspace]
+
+members = [
+    "buildutil",
+    "normal",
+    "static1",
+    "static2build",
+    "static3bin",
+]
diff --git a/testdata/workspace/buildutil/Cargo.toml b/testdata/workspace/buildutil/Cargo.toml
new file mode 100644
index 0000000..840a53e
--- /dev/null
+++ b/testdata/workspace/buildutil/Cargo.toml
@@ -0,0 +1,5 @@
+[package]
+name = "buildutil"
+version = "0.1.0"
+authors = ["Tim Neumann <mail@timnn.me>"]
+edition = "2018"
diff --git a/testdata/workspace/buildutil/src/build.rs b/testdata/workspace/buildutil/src/build.rs
new file mode 100644
index 0000000..66a1e87
--- /dev/null
+++ b/testdata/workspace/buildutil/src/build.rs
@@ -0,0 +1,3 @@
+fn main() {
+    println!("Hello from Build Util build.rs!");
+}
diff --git a/testdata/workspace/buildutil/src/lib.rs b/testdata/workspace/buildutil/src/lib.rs
new file mode 100644
index 0000000..4c7bfa5
--- /dev/null
+++ b/testdata/workspace/buildutil/src/lib.rs
@@ -0,0 +1,3 @@
+pub fn hello_from_build_util() {
+    println!("Hello from Build Util!");
+}
diff --git a/testdata/workspace/normal/Cargo.toml b/testdata/workspace/normal/Cargo.toml
new file mode 100644
index 0000000..4b2a7d4
--- /dev/null
+++ b/testdata/workspace/normal/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "normal"
+version = "0.1.0"
+authors = ["Tim Neumann <mail@timnn.me>"]
+edition = "2018"
+
+[dependencies]
diff --git a/testdata/workspace/normal/src/lib.rs b/testdata/workspace/normal/src/lib.rs
new file mode 100644
index 0000000..1ee2a35
--- /dev/null
+++ b/testdata/workspace/normal/src/lib.rs
@@ -0,0 +1,3 @@
+pub extern "C" fn hello_from_normal() {
+    println!("Hello from Normal!");
+}
diff --git a/testdata/workspace/static1/Cargo.toml b/testdata/workspace/static1/Cargo.toml
new file mode 100644
index 0000000..da81cab
--- /dev/null
+++ b/testdata/workspace/static1/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "static1"
+version = "0.1.0"
+authors = ["Tim Neumann <mail@timnn.me>"]
+edition = "2018"
+
+[lib]
+crate-type = ["staticlib"]
+
+[dependencies]
+normal = { path = "../normal" }
diff --git a/testdata/workspace/static1/src/lib.rs b/testdata/workspace/static1/src/lib.rs
new file mode 100644
index 0000000..3a76bd3
--- /dev/null
+++ b/testdata/workspace/static1/src/lib.rs
@@ -0,0 +1,6 @@
+#[no_mangle]
+pub extern "C" fn hello_from_static1() {
+    println!("Calling Normal from Static 1!");
+    normal::hello_from_normal();
+    println!("Hello from Static 1!");
+}
diff --git a/testdata/workspace/static2build/Cargo.toml b/testdata/workspace/static2build/Cargo.toml
new file mode 100644
index 0000000..78571d9
--- /dev/null
+++ b/testdata/workspace/static2build/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "static2build"
+version = "0.1.0"
+authors = ["Tim Neumann <mail@timnn.me>"]
+edition = "2018"
+
+[lib]
+crate-type = ["staticlib"]
+
+[dependencies]
+buildutil = { path = "../buildutil" }
+
+[build-dependencies]
+buildutil = { path = "../buildutil" }
diff --git a/testdata/workspace/static2build/build.rs b/testdata/workspace/static2build/build.rs
new file mode 100644
index 0000000..9149c2e
--- /dev/null
+++ b/testdata/workspace/static2build/build.rs
@@ -0,0 +1,5 @@
+fn main() {
+    println!("Calling Build Util from Static 2 build.rs!");
+    buildutil::hello_from_build_util();
+    println!("Hello from Static 2 build.rs!");
+}
diff --git a/testdata/workspace/static2build/src/lib.rs b/testdata/workspace/static2build/src/lib.rs
new file mode 100644
index 0000000..f0f399d
--- /dev/null
+++ b/testdata/workspace/static2build/src/lib.rs
@@ -0,0 +1,6 @@
+#[no_mangle]
+pub extern "C" fn hello_from_static2() {
+    println!("Calling Build Util from Static 2!");
+    buildutil::hello_from_build_util();
+    println!("Hello from Static 2!");
+}
diff --git a/testdata/workspace/static3bin/Cargo.toml b/testdata/workspace/static3bin/Cargo.toml
new file mode 100644
index 0000000..e2f327b
--- /dev/null
+++ b/testdata/workspace/static3bin/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "static3bin"
+version = "0.1.0"
+authors = ["Tim Neumann <mail@timnn.me>"]
+edition = "2018"
+
+[lib]
+crate-type = ["rlib", "staticlib"]
diff --git a/testdata/workspace/static3bin/src/lib.rs b/testdata/workspace/static3bin/src/lib.rs
new file mode 100644
index 0000000..836fb0a
--- /dev/null
+++ b/testdata/workspace/static3bin/src/lib.rs
@@ -0,0 +1,10 @@
+pub fn internal_hello() {
+    println!("Internal Hello from Static 3!");
+}
+
+#[no_mangle]
+pub extern "C" fn hello_from_static3() {
+    println!("Calling Internal from Static 3 lib!");
+    internal_hello();
+    println!("Hello from Static 3 lib!");
+}
diff --git a/testdata/workspace/static3bin/src/main.rs b/testdata/workspace/static3bin/src/main.rs
new file mode 100644
index 0000000..85db05f
--- /dev/null
+++ b/testdata/workspace/static3bin/src/main.rs
@@ -0,0 +1,5 @@
+fn main() {
+    println!("Calling Internal from Static 3 bin!");
+    static3bin::internal_hello();
+    println!("Internal Hello from Static 3 bin!");
+}
diff --git a/testdata/xcode/.gitignore b/testdata/xcode/.gitignore
new file mode 100644
index 0000000..4c456b3
--- /dev/null
+++ b/testdata/xcode/.gitignore
@@ -0,0 +1,3 @@
+xcuserdata/
+
+/.xcode-lipo
diff --git a/testdata/xcode/cargo-lipo-test.xcodeproj/project.pbxproj b/testdata/xcode/cargo-lipo-test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..b30ab9d
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test.xcodeproj/project.pbxproj
@@ -0,0 +1,389 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 50;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		F633F83F21DBCE1800E5C165 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F633F83E21DBCE1800E5C165 /* AppDelegate.m */; };
+		F633F84221DBCE1800E5C165 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F633F84121DBCE1800E5C165 /* ViewController.m */; };
+		F633F84521DBCE1800E5C165 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F633F84321DBCE1800E5C165 /* Main.storyboard */; };
+		F633F84721DBCE1900E5C165 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F633F84621DBCE1900E5C165 /* Assets.xcassets */; };
+		F633F84A21DBCE1900E5C165 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F633F84821DBCE1900E5C165 /* LaunchScreen.storyboard */; };
+		F633F84D21DBCE1900E5C165 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F633F84C21DBCE1900E5C165 /* main.m */; };
+		F6FD7E5321DBDF47002F618C /* libstatic1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6FD7E5021DBDF47002F618C /* libstatic1.a */; };
+		F6FD7E5421DBDF47002F618C /* libstatic2build.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6FD7E5121DBDF47002F618C /* libstatic2build.a */; };
+		F6FD7E5521DBDF47002F618C /* libstatic3bin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6FD7E5221DBDF47002F618C /* libstatic3bin.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		F633F83A21DBCE1800E5C165 /* cargo-lipo-test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cargo-lipo-test.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		F633F83D21DBCE1800E5C165 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		F633F83E21DBCE1800E5C165 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		F633F84021DBCE1800E5C165 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
+		F633F84121DBCE1800E5C165 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
+		F633F84421DBCE1800E5C165 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+		F633F84621DBCE1900E5C165 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		F633F84921DBCE1900E5C165 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		F633F84B21DBCE1900E5C165 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		F633F84C21DBCE1900E5C165 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		F6A4608121DBEFA900C7F1D2 /* integration.bats.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = integration.bats.sh; path = ../../integration.bats.sh; sourceTree = "<group>"; };
+		F6FD7E5021DBDF47002F618C /* libstatic1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libstatic1.a; path = ../workspace/target/universal/debug/libstatic1.a; sourceTree = "<group>"; };
+		F6FD7E5121DBDF47002F618C /* libstatic2build.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libstatic2build.a; path = ../workspace/target/universal/debug/libstatic2build.a; sourceTree = "<group>"; };
+		F6FD7E5221DBDF47002F618C /* libstatic3bin.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libstatic3bin.a; path = ../workspace/target/universal/debug/libstatic3bin.a; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		F633F83721DBCE1800E5C165 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F6FD7E5321DBDF47002F618C /* libstatic1.a in Frameworks */,
+				F6FD7E5421DBDF47002F618C /* libstatic2build.a in Frameworks */,
+				F6FD7E5521DBDF47002F618C /* libstatic3bin.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		F633F83121DBCE1800E5C165 = {
+			isa = PBXGroup;
+			children = (
+				F633F83C21DBCE1800E5C165 /* cargo-lipo-test */,
+				F633F83B21DBCE1800E5C165 /* Products */,
+				F6FD7E4F21DBDF47002F618C /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		F633F83B21DBCE1800E5C165 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				F633F83A21DBCE1800E5C165 /* cargo-lipo-test.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		F633F83C21DBCE1800E5C165 /* cargo-lipo-test */ = {
+			isa = PBXGroup;
+			children = (
+				F633F83D21DBCE1800E5C165 /* AppDelegate.h */,
+				F633F83E21DBCE1800E5C165 /* AppDelegate.m */,
+				F633F84021DBCE1800E5C165 /* ViewController.h */,
+				F633F84121DBCE1800E5C165 /* ViewController.m */,
+				F633F84321DBCE1800E5C165 /* Main.storyboard */,
+				F633F84621DBCE1900E5C165 /* Assets.xcassets */,
+				F633F84821DBCE1900E5C165 /* LaunchScreen.storyboard */,
+				F633F84B21DBCE1900E5C165 /* Info.plist */,
+				F633F84C21DBCE1900E5C165 /* main.m */,
+			);
+			path = "cargo-lipo-test";
+			sourceTree = "<group>";
+		};
+		F6FD7E4F21DBDF47002F618C /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				F6A4608121DBEFA900C7F1D2 /* integration.bats.sh */,
+				F6FD7E5021DBDF47002F618C /* libstatic1.a */,
+				F6FD7E5121DBDF47002F618C /* libstatic2build.a */,
+				F6FD7E5221DBDF47002F618C /* libstatic3bin.a */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		F633F83921DBCE1800E5C165 /* cargo-lipo-test */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = F633F85021DBCE1900E5C165 /* Build configuration list for PBXNativeTarget "cargo-lipo-test" */;
+			buildPhases = (
+				F63A742221DBD3BD003E45B6 /* Run Script */,
+				F633F83621DBCE1800E5C165 /* Sources */,
+				F633F83721DBCE1800E5C165 /* Frameworks */,
+				F633F83821DBCE1800E5C165 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "cargo-lipo-test";
+			productName = "cargo-lipo-test";
+			productReference = F633F83A21DBCE1800E5C165 /* cargo-lipo-test.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		F633F83221DBCE1800E5C165 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1010;
+				ORGANIZATIONNAME = "Tim Neumann";
+				TargetAttributes = {
+					F633F83921DBCE1800E5C165 = {
+						CreatedOnToolsVersion = 10.1;
+					};
+				};
+			};
+			buildConfigurationList = F633F83521DBCE1800E5C165 /* Build configuration list for PBXProject "cargo-lipo-test" */;
+			compatibilityVersion = "Xcode 9.3";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = F633F83121DBCE1800E5C165;
+			productRefGroup = F633F83B21DBCE1800E5C165 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				F633F83921DBCE1800E5C165 /* cargo-lipo-test */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		F633F83821DBCE1800E5C165 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F633F84A21DBCE1900E5C165 /* LaunchScreen.storyboard in Resources */,
+				F633F84721DBCE1900E5C165 /* Assets.xcassets in Resources */,
+				F633F84521DBCE1800E5C165 /* Main.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		F63A742221DBD3BD003E45B6 /* Run Script */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+			);
+			name = "Run Script";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "export PATH=\"$HOME/.cargo/bin:$PATH\"\n\n# THIS IS A HACK AND REQUIRED WHEN DEVELOPING cargo-lipo\nif [ -f ./.xcode-lipo ]; then\n    export CARGO_LIPO=\"./.xcode-lipo lipo\"\nelse\n    export CARGO_LIPO=\"cargo lipo\"\nfi\n\n${CARGO_LIPO} --xcode-integ --all --manifest-path ../workspace/Cargo.toml\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		F633F83621DBCE1800E5C165 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F633F84221DBCE1800E5C165 /* ViewController.m in Sources */,
+				F633F84D21DBCE1900E5C165 /* main.m in Sources */,
+				F633F83F21DBCE1800E5C165 /* AppDelegate.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		F633F84321DBCE1800E5C165 /* Main.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				F633F84421DBCE1800E5C165 /* Base */,
+			);
+			name = Main.storyboard;
+			sourceTree = "<group>";
+		};
+		F633F84821DBCE1900E5C165 /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				F633F84921DBCE1900E5C165 /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		F633F84E21DBCE1900E5C165 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_BITCODE = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.1;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		F633F84F21DBCE1900E5C165 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_BITCODE = NO;
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.1;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		F633F85121DBCE1900E5C165 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "cargo-lipo-test/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				"LIBRARY_SEARCH_PATHS[arch=*]" = ../workspace/target/universal/debug;
+				PRODUCT_BUNDLE_IDENTIFIER = "me.timnn.cargo-lipo-test";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		F633F85221DBCE1900E5C165 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "cargo-lipo-test/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				"LIBRARY_SEARCH_PATHS[arch=*]" = ../workspace/target/universal/release;
+				PRODUCT_BUNDLE_IDENTIFIER = "me.timnn.cargo-lipo-test";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		F633F83521DBCE1800E5C165 /* Build configuration list for PBXProject "cargo-lipo-test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F633F84E21DBCE1900E5C165 /* Debug */,
+				F633F84F21DBCE1900E5C165 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		F633F85021DBCE1900E5C165 /* Build configuration list for PBXNativeTarget "cargo-lipo-test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F633F85121DBCE1900E5C165 /* Debug */,
+				F633F85221DBCE1900E5C165 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = F633F83221DBCE1800E5C165 /* Project object */;
+}
diff --git a/testdata/xcode/cargo-lipo-test.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/testdata/xcode/cargo-lipo-test.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..0baade5
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:cargo-lipo-test.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/testdata/xcode/cargo-lipo-test.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/testdata/xcode/cargo-lipo-test.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/testdata/xcode/cargo-lipo-test.xcodeproj/xcshareddata/xcschemes/cargo-lipo-test.xcscheme b/testdata/xcode/cargo-lipo-test.xcodeproj/xcshareddata/xcschemes/cargo-lipo-test.xcscheme
new file mode 100644
index 0000000..20c85df
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test.xcodeproj/xcshareddata/xcschemes/cargo-lipo-test.xcscheme
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1010"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "F633F83921DBCE1800E5C165"
+               BuildableName = "cargo-lipo-test.app"
+               BlueprintName = "cargo-lipo-test"
+               ReferencedContainer = "container:cargo-lipo-test.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F633F83921DBCE1800E5C165"
+            BuildableName = "cargo-lipo-test.app"
+            BlueprintName = "cargo-lipo-test"
+            ReferencedContainer = "container:cargo-lipo-test.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F633F83921DBCE1800E5C165"
+            BuildableName = "cargo-lipo-test.app"
+            BlueprintName = "cargo-lipo-test"
+            ReferencedContainer = "container:cargo-lipo-test.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "F633F83921DBCE1800E5C165"
+            BuildableName = "cargo-lipo-test.app"
+            BlueprintName = "cargo-lipo-test"
+            ReferencedContainer = "container:cargo-lipo-test.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/testdata/xcode/cargo-lipo-test/AppDelegate.h b/testdata/xcode/cargo-lipo-test/AppDelegate.h
new file mode 100644
index 0000000..4216eb5
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/AppDelegate.h
@@ -0,0 +1,17 @@
+//
+//  AppDelegate.h
+//  cargo-lipo-test
+//
+//  Created by Tim Neumann on 01.01.19.
+//  Copyright © 2019 Tim Neumann. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end
+
diff --git a/testdata/xcode/cargo-lipo-test/AppDelegate.m b/testdata/xcode/cargo-lipo-test/AppDelegate.m
new file mode 100644
index 0000000..d1a28c9
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/AppDelegate.m
@@ -0,0 +1,51 @@
+//
+//  AppDelegate.m
+//  cargo-lipo-test
+//
+//  Created by Tim Neumann on 01.01.19.
+//  Copyright © 2019 Tim Neumann. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+    // Override point for customization after application launch.
+    return YES;
+}
+
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
+}
+
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
+}
+
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+
+@end
diff --git a/testdata/xcode/cargo-lipo-test/Assets.xcassets/AppIcon.appiconset/Contents.json b/testdata/xcode/cargo-lipo-test/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..d8db8d6
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "76x76",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "76x76",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "83.5x83.5",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ios-marketing",
+      "size" : "1024x1024",
+      "scale" : "1x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/testdata/xcode/cargo-lipo-test/Assets.xcassets/Contents.json b/testdata/xcode/cargo-lipo-test/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/testdata/xcode/cargo-lipo-test/Base.lproj/LaunchScreen.storyboard b/testdata/xcode/cargo-lipo-test/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..bfa3612
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/testdata/xcode/cargo-lipo-test/Base.lproj/Main.storyboard b/testdata/xcode/cargo-lipo-test/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..942f0bc
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+        </scene>
+    </scenes>
+</document>
diff --git a/testdata/xcode/cargo-lipo-test/Info.plist b/testdata/xcode/cargo-lipo-test/Info.plist
new file mode 100644
index 0000000..16be3b6
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/Info.plist
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIMainStoryboardFile</key>
+	<string>Main</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>
diff --git a/testdata/xcode/cargo-lipo-test/ViewController.h b/testdata/xcode/cargo-lipo-test/ViewController.h
new file mode 100644
index 0000000..f6ec2cc
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/ViewController.h
@@ -0,0 +1,15 @@
+//
+//  ViewController.h
+//  cargo-lipo-test
+//
+//  Created by Tim Neumann on 01.01.19.
+//  Copyright © 2019 Tim Neumann. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ViewController : UIViewController
+
+
+@end
+
diff --git a/testdata/xcode/cargo-lipo-test/ViewController.m b/testdata/xcode/cargo-lipo-test/ViewController.m
new file mode 100644
index 0000000..c1d7dc3
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/ViewController.m
@@ -0,0 +1,23 @@
+//
+//  ViewController.m
+//  cargo-lipo-test
+//
+//  Created by Tim Neumann on 01.01.19.
+//  Copyright © 2019 Tim Neumann. All rights reserved.
+//
+
+#import "ViewController.h"
+
+@interface ViewController ()
+
+@end
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view, typically from a nib.
+}
+
+
+@end
diff --git a/testdata/xcode/cargo-lipo-test/main.m b/testdata/xcode/cargo-lipo-test/main.m
new file mode 100644
index 0000000..c54ea06
--- /dev/null
+++ b/testdata/xcode/cargo-lipo-test/main.m
@@ -0,0 +1,24 @@
+//
+//  main.m
+//  cargo-lipo-test
+//
+//  Created by Tim Neumann on 01.01.19.
+//  Copyright © 2019 Tim Neumann. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+void hello_from_static1(void);
+void hello_from_static2(void);
+void hello_from_static3(void);
+
+int main(int argc, char * argv[]) {
+    hello_from_static1();
+    hello_from_static2();
+    hello_from_static3();
+
+    @autoreleasepool {
+        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+    }
+}