building for iOS Simulator, but linking in object file built for macOS, file '..customLib.a' for architecture x86_64

I am stuck with this linking error for days. I recently updated to Xcode12 and my project building and running fine for real devices. But when I try to run for Simulator I am getting this error.

Code Block
building for iOS Simulator, but linking in object file built for macOS, file '..customLib.a' for architecture x86_64

My customLib is a .a library built with Xcode12 too.
Code Block
lipo -info customLib.a 
Architectures in the fat file: customLib.a are: armv7 armv7s i386 x86_64 arm64 

How to resolve this issue?


The issue here is that the customLib.a is built for macOS, not the simulator. You can see this by examining the binary with otool:

Code Block
sh-3.2$ cat helloworld.c 
#include <stdio.h>
int main(void) {
  printf("Hello, world!\n");
  return 0;
sh-3.2$ cc -c helloworld.c -o helloworld.o 
sh-3.2$ otool -lv helloworld.o | grep -A5 LC_BUILD
   cmdsize 24
  platform macos
       sdk 11.0
     minos 11.0
    ntools 0

To resolve this you need to make sure you are building customLib.a for the iPhoneSimulator in order to use it an iPhone simulator target. You can do that by switching customLib.a's base SDK to iOS and then building a simulator binary.

I suspect that the root cause of this that customLib.a is configured to try to create a single library that can be included in macOS, iOS and iOS simulator projects by including artifacts for each platform as different slices. This has never been supported, but it often worked in practice because all of our platforms were "close enough" in terms of their ABIs. As we have introduced new platforms like tvOS and watchOS this has become more difficult to do. A few years ago we introduced a supported way to do this via XCFramework.
@Developer Tools Engineer,

My library's Base SDK is already set to iOS and I need to get a .a file that supports both iOS real device and simulators. If I only build for simulators I am getting only architectures for simulators.

Here is my Post Script to make an universal .a
Code Block
# define output folder environment variable
# Step 1. Build Device and Simulator versions
xcodebuild -target CustomLib ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target CustomLib -configuration ${CONFIGURATION} -sdk iphonesimulator -arch x86_64 -arch i386 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
# make sure the output directory exists
# Step 2. Create universal binary file using lipo
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a"

I don't know why the library is building for macOS.


otool -lv customLib.a | grep -A5 LC_BUILD produces no output for me. Need suggestion.

Without looking at your build logs I can't tell you why your x86 slices are built for macOS instead of the simulator. I would be interested to see the arguments that Xcode is passing to the compiler when building the source files in your static archive. The one thing I can thing of is that is your Deployment Target is set to an old enough release then the binary will have to use the older style version information. You can check for that like this:

Code Block
otool -lv customLib.a | grep -A5 LC_VERSION_MIN_

Hopefully that should provide a hint as to what is going on.

Also, as I said in my first answer, using lipo to merge together simulator and native binaries has never been supported, though it happens to work most of the time. You should migrate to using an XCFramework which can be used to distribute your native and simulator archives together. XCFramework is described in this WWDC talk (it is not a Swift specific technology, despite the name of the talk).
@Developer Tools Engineer

The library produced by lipo tool has no issue when used by a simple Sample app (Swift5). But it produces that issue for a large hybrid app (objc+Swift). Any chances of misconfigurations of my app that is using the .a file?

In my case, I was linking static libraries into my app, and I had OTHER_LDFLAGS=-all_load in my build settings. This causes Xcode to load all members of any static archive library with an x86_64 architecture. So Xcode erroneously tried to link some macOS static libs into my (Intel) iOS Simulator executable.

Removing the -all_load linker flag resolved my issue.

See forum post about Linker "duplicate symbol" warnings. This worked for me