building for iOS, but linking in object file built for iOS Simulator, for architecture arm64

0

I am building an iOS App using a personal C++ library mylib.a , With the current Xcode version (13.1) When I include this library in my Frameworks and try to run on physical iOS device I have the following issue :

building for iOS, but linking in object file built for iOS Simulator, for architecture arm64

When I include my library built with a previous XCode version (I think it was Xcode 11) the app builds and runs on the device. Because I use the AppTrackingTransparency.framework I can no longer build my SDK with XCode 11.

The issue appears both on Mac intel and M1.

I tried in build settings :

  • Exclude architecture arm64 for Any IOS Simulator for Debug and Release
  • Set the Supported Platform to iphoneos only
  • Set Architectures on $(ARCHS_STANDARD) and set Build Active Architecture Only on to YES

How do you build mylib.a?

The most common cause of problems like this is a mix up between target architecture (arm64, x86_64, and so on) and target platform (Mac, iOS, iOS Simulator). If, for example, you built your static library for the macOS platform, it would include the arm64 architecture that but code wouldn’t work on the iOS or iOS Simulator platforms.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I have a main makefile to compile my lib: sdklib.a :

all: sdklib.a

sdklib_arm64.a: FORCE
	$(MAKE) -f makefile.iphone TARGET=arm64 all

sdklib_armv7.a: FORCE
	$(MAKE) -f makefile.iphone TARGET=armv7 all

sdklib_armv7s.a: FORCE
	$(MAKE) -f makefile.iphone TARGET=armv7s all

FORCE:

sdklib.a: sdklib_arm64.a sdklib_armv7s.a sdklib_armv7.a
	lipo -create -output sdklib.a sdklib_arm64.a sdklib_armv7s.a sdklib_armv7.a

And my makefile.iphone is :

# Compiler to use. Can be g++ or clang++
CXX = clang

all: sdklib_$(TARGET).a

TMPDIR=tmp_$(TARGET)
PLATFORM_BASE=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk

COMMON_FLAGS = -Isrc/main/cpp -Isrc/main/objc -I../api/tmp_$(TARGET)/src/main/proto -I../protobuf/src/main/cpp \
-Wno-unused-command-line-argument \
-arch $(TARGET) \
-emit-llvm \
-mios-simulator-version-min=6.1 \
-fobjc-abi-version=2 \
-isysroot $(PLATFORM_BASE) \
-stdlib=libc++ \
-pthread -DHAVE_PTHREAD -DGOOGLE_PROTOBUF_NO_RTTI -fPIC -fno-rtti \
-fobjc-arc \
-framework AdSupport \
-framework AppTrackingTransparency \
-framework CoreLocation \
-framework CoreMotion \
-framework Foundation \
-framework UIKit \
-framework SystemConfiguration \
-Wall -Wno-deprecated-declarations -Werror


OBJC_FLAGS = $(COMMON_FLAGS)
CPP_FLAGS = $(COMMON_FLAGS) -std=c++11

# Compiler flags to generate dependencies (.newdep) files.
# .newdep files are then renames as .dep
DEPFLAGS = -MT $@ -MMD -MP -MF $(TMPDIR)/$*.newdep

CC_COMPILE = $(CXX) $(DEPFLAGS) $(CPP_FLAGS) -c
M_COMPILE = $(CXX) $(DEPFLAGS) $(OBJC_FLAGS) -c
MM_COMPILE = $(CXX) $(DEPFLAGS) $(CPP_FLAGS) -c

# After compilation rename the .newdep files. This avoid a failing compilation to
# corrupt the dependency stuff.
POSTCOMPILE = mv -f $(TMPDIR)/$*.newdep $(TMPDIR)/$*.dep

LDFLAGS_COMMON := -lprotobuf -lstdc++ -lpthread

# Linker flags. On server use the server lib with all protos, on phone use only phone visible ones.
LDFLAGS_LIB := ../api/libapi.a $(LDFLAGS_COMMON)

# Shell commands to build tmp directory tree as a clone of sources tree.
$(shell find src/main/cpp -type d | grep -v $(TMPDIR) | xargs -I {} mkdir -p $(TMPDIR)/{})
$(shell find src/main/objc -type d | grep -v $(TMPDIR) | xargs -I {} mkdir -p $(TMPDIR)/{})

# Rules to compile
$(TMPDIR)/%.o: %.cc
$(TMPDIR)/%.o: %.cc
	$(CC_COMPILE) $(OUTPUT_OPTION) $<
	$(POSTCOMPILE)

$(TMPDIR)/%.o: %.m
$(TMPDIR)/%.o: %.m
	$(M_COMPILE) $(OUTPUT_OPTION) $<
	$(POSTCOMPILE)

$(TMPDIR)/%.o: %.mm
$(TMPDIR)/%.o: %.mm
	$(MM_COMPILE) $(OUTPUT_OPTION) $<
	$(POSTCOMPILE)

# Include all dependency files.
-include $(shell find $(TMPDIR) -name '*.dep')

# Scan folder for cc files.
CC_SRC = $(shell find src/main/cpp -name '*.cc')
M_SRC = $(shell find src/main/objc -name '*.m')
MM_SRC = $(shell find src/main/objc -name '*.mm')

# Generate .o names for all .cc, .mm and .m files.
OBJS=$(addprefix $(TMPDIR)/,$(CC_SRC:.cc=.o)) $(addprefix $(TMPDIR)/,$(MM_SRC:.mm=.o)) $(addprefix $(TMPDIR)/,$(M_SRC:.m=.o))

# Methods to remove items from a list if they match or does not match a string.
FILTER_OUT = $(foreach v,$(2),$(if $(findstring $(1),$(v)),,$(v)))
FILTER_OUT_NOT = $(foreach v,$(2),$(if $(findstring $(1),$(v)),$(v),))

SDKLIB_OBJS = $(call FILTER_OUT,_test., $(call FILTER_OUT,_tool., $(OBJS)))

# Static target for tests.
sdklib_$(TARGET).a: $(SDKLIB_OBJS)
	ar rcs sdklib_$(TARGET).a $(SDKLIB_OBJS)

clean:
	rm -f sdklib_$(TARGET).a
	rm -rf $(TMPDIR)

I have a main makefile to compile my lib

In that case here’s my general recipe for fixing such problems:

  1. In Xcode, create a new dummy project that builds the type of thing you want to build. In this case that means starting with the iOS > Static Library template.

  2. Build that.

  3. Verify that the result works in your environment.

  4. Look at the build log in the Reports navigator.

  5. Find the commands Xcode used to build the target.

  6. Compare those to the command generated by your makefile.

  7. Update your makefile to match Xcode until things work (-:

Be aware that iOS and the iOS Simulator are different platforms. If you want your SDK to support the simulator:

  • Do this twice, once for each platform.

  • Integrate the results into a single XCFramework.

Similarly for Mac Catalyst.

Remember that each platform may support multiple architectures — the list of architectures varies based on your deployment target — so this means running your build N times, one for each architecture on each platform. Moreover, an architecture like arm64 is supported on multiple platforms, so you’ll need multiple arm64 builds.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

building for iOS, but linking in object file built for iOS Simulator, for architecture arm64
 
 
Q