xcodebashmach-ouniversal-binarylipo

Xcode universal library build phase - Lipo can't find files


I've read several tutorials and guides on how to have Xcode create a universal library. Basically you add an aggregate target with a bash script build phase to build the separate targets and lipo them together.

I have my own small script (which works because of how I named my targets) but for some reason lipo can't find the files;

fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: can't open input file: /Users/username/Projects/project/plugins/build/Release-iphoneos/libproject-plugins.a /Users/username/Projects/project/plugins/build/Release-macos/libproject-plugins.a (No such file or directory)

However when I

  1. Run the exact same lipo command right after the failed build, everything works and the files are found.
  2. Add bash logic in my script to wait for the file creation the issue persists.
  3. Replace the lipo in my script with a simple ls, the files are there.

So I'm not sure what goes wrong, it doesn't seem like xcodebuild only creates the files after lipo is called (as I first thought).

The script;

targets=$(xcodebuild -list | sed -n '/Targets/,/^$/p' | grep -v -e 'Targets:\|all\|^$')
target_results=""

for target in $targets; do
    xcodebuild ${ACTION} -target $target -configuration ${CONFIGURATION}
    target_results="$target_results ${PROJECT_DIR}/build/${CONFIGURATION}-$target/libproject-plugins.a"
done

xcrun lipo -create "$target_results" -o "${PROJECT_DIR}/plugins-universal.a"

Solution

  • This is a bash problem/mistake.
    You're passing all the file names as a single argument to lipo, so it's gonna look for a single file named /Users/username/Projects/project/plugins/build/Release-iphoneos/libproject-plugins.a /Users/username/Projects/project/plugins/build/Release-macos/libproject-plugins.a.

    You should use an array for the file names instead.

    Applied to your script:

    targets=$(xcodebuild -list | sed -n '/Targets/,/^$/p' | grep -v -e 'Targets:\|all\|^$');
    target_results=();
    
    for target in $targets; do
        xcodebuild ${ACTION} -target $target -configuration ${CONFIGURATION};
        target_results+=("${PROJECT_DIR}/build/${CONFIGURATION}-$target/libproject-plugins.a");
    done;
    
    xcrun lipo -create "${target_results[@]}" -o "${PROJECT_DIR}/plugins-universal.a";