Cross Compiling on iOS Using Cargo Not Working for Device Architectures (Arm7, Armv7s, Arm64)


#1

I’m using Cargo to build my Rust libraries for iOS architectures (i386-apple-ios x86_64-apple-ios armv7-apple-ios armv7s-apple-ios aarch64-apple-ios). I’m having problems building for the iOS device architectures (Arm7, Arm7s, and Arm64). I’m getting errors regarding missing standard library components (e.g., memcpy, memset, etc.) The build works for the simulators though. I believe it’s related to the gcc is called. The gcc that’s in my PATH would work for the simulator, but not for the device.

I’ve tried two approaches for cross compiling using Cargo:

  1. Installing the Rustup toolchain targets for all the iOS architectures.
  2. Building Rustc with my configuration set to the targets of all the iOS architectures (…/configure --target=armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,aarch64-apple-ios,x86_64-apple-ios --prefix=$HOME/rustc-ios) per https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/.

When I tried approach #1, I get the following errors:

Undefined symbols for architecture armv7:

  "memset", referenced from:
      ___aeabi_memset in libtest_sst.a(aeabi_memset.o)
      ___aeabi_memclr in libtest_sst.a(aeabi_memset.o)
     (maybe you meant: ___aeabi_memset)
  "memcpy", referenced from:
      ___aeabi_memcpy in libtest_sst.a(aeabi_memcpy.o)
     (maybe you meant: ___aeabi_memcpy)
  "memcmp", referenced from:
      ___aeabi_memcmp in libtest_sst.a(aeabi_memcmp.o)
     (maybe you meant: ___aeabi_memcmp)
  "___aeabi_dsub", referenced from:
      ___aeabi_drsub in libtest_sst.a(aeabi_drsub.o)
  "___aeabi_fsub", referenced from:
      ___aeabi_frsub in libtest_sst.a(aeabi_frsub.o)
  "__aeabi_fcmplt", referenced from:
      ___aeabi_cfcmple in libtest_sst.a(aeabi_cfcmp.o)
     (maybe you meant: ___aeabi_fcmplt)
  "__aeabi_fcmpeq", referenced from:
      ___aeabi_cfcmple in libtest_sst.a(aeabi_cfcmp.o)
     (maybe you meant: ___aeabi_fcmpeq)
  "__aeabi_cfcmpeq_check_nan", referenced from:
      ___aeabi_cfcmpeq in libtest_sst.a(aeabi_cfcmp.o)
     (maybe you meant: ___aeabi_cfcmpeq_check_nan)
  "memmove", referenced from:
      ___aeabi_memmove in libtest_sst.a(aeabi_memmove.o)
     (maybe you meant: ___aeabi_memmove)
  "__aeabi_dcmpeq", referenced from:
      ___aeabi_cdcmple in libtest_sst.a(aeabi_cdcmp.o)
     (maybe you meant: ___aeabi_dcmpeq)
  "__aeabi_cdcmpeq_check_nan", referenced from:
      ___aeabi_cdcmpeq in libtest_sst.a(aeabi_cdcmp.o)
     (maybe you meant: ___aeabi_cdcmpeq_check_nan)
  "__aeabi_cfcmple", referenced from:
      ___aeabi_cfcmpeq in libtest_sst.a(aeabi_cfcmp.o)
      ___aeabi_cfrcmple in libtest_sst.a(aeabi_cfcmp.o)
     (maybe you meant: ___aeabi_cfcmple)
  "__aeabi_dcmplt", referenced from:
      ___aeabi_cdcmple in libtest_sst.a(aeabi_cdcmp.o)
     (maybe you meant: ___aeabi_dcmplt)
  "__aeabi_cdcmple", referenced from:
      ___aeabi_cdcmpeq in libtest_sst.a(aeabi_cdcmp.o)
      ___aeabi_cdrcmple in libtest_sst.a(aeabi_cdcmp.o)
     (maybe you meant: ___aeabi_cdcmple)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

When I tried approach #2, I get the following errors:

Undefined symbols for architecture armv7:

  "___aeabi_fsub", referenced from:
      ___aeabi_frsub in libtest_sst.a(aeabi_frsub.c.o)
  "___aeabi_dsub", referenced from:
      ___aeabi_drsub in libtest_sst.a(aeabi_drsub.c.o)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

My Makefile for producing the final static library looks like this:

ARCHS = i386-apple-ios x86_64-apple-ios armv7-apple-ios armv7s-apple-ios aarch64-apple-ios
LIB = libtest.a

all: $(LIB)

.PHONY: $(ARCHS)
$(ARCHS): %:
        cargo build --verbose --no-default-features --features=no_network --target $@

$(LIB): $(ARCHS)
        lipo -create -output $@ $(foreach arch,$(ARCHS),$(wildcard target/$(arch)/debug/$(LIB)))

My Cargo.toml looks like this:

[package]
name = "test"
version = "0.1.0"
authors = ["test <test@test.com>"]

build = "build.rs"

[lib]
name = "test"
crate-type = ["staticlib"]

[features]

default = ["hyper"]
no_network = []

[build-dependencies]
serde_codegen = "*"

[dependencies]
# error-chain = "*"
hyper = { version = "*", optional = true }
libc = "*"
murmur3 = "*"
quick-error = "*"
serde = "*"
serde_json = "*"
time = "*"
url = "*"

#2

crosspost on stackoverflow: http://stackoverflow.com/questions/38448682/missing-standard-library-components-when-cross-compiling-rust-for-ios-device-arc