1

I try to build static framework.

So I run following commands:

for device

xcodebuild
           -project MyAppLib.xcodeproj
           -sdk iphoneos
           -target $PRODUCT_FRAMEWORK
           -configuration Release clean build

for simulator

xcodebuild
           -project MyAppLib.xcodeproj
           -sdk iphonesimulator
           -target $PRODUCT_FRAMEWORK
           -configuration Release clean build

However when I try to run lipo:

lipo -create build/Release-iphonesimulator/MyAppLib.framework/MyAppLib 
      build/Release-iphoneos/MyAppLib.framework/MyAppLib 
     -output MyAppLib.framework

I get an error:

fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: build/Release-iphonesimulator/MyAppLib.framework/MyAppLib and build/Release-iphoneos/MyAppLib.framework/MyAppLib have the same architectures (i386) and can't be in the same fat output file

From Xcode I success to build it but from CLI both have the same structure.

$ file MyAppLib.framework gives me:

MyAppLib.framework: Mach-O universal binary with 4 architectures: [i386: current ar archive] [arm_v7: current ar archive] [x86_64: current ar archive] [arm64]
MyAppLib.framework (for architecture i386): current ar archive
MyAppLib.framework (for architecture armv7):    current ar archive
MyAppLib.framework (for architecture x86_64):   current ar archive
MyAppLib.framework (for architecture arm64):    current ar archive

enter image description here


If I try to run only for one platform, the build is succeeded but I get strange framework that I cannot even explore it:

enter image description here

Edit:

Multiplatform script:

set -e

# If we're already inside this script then die
if [ -n "$RW_MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then
exit 0
fi
export RW_MULTIPLATFORM_BUILD_IN_PROGRESS=1

RW_FRAMEWORK_NAME=${PROJECT_NAME}
RW_INPUT_STATIC_LIB="lib${PROJECT_NAME}.a"
RW_FRAMEWORK_LOCATION="${BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework"

function build_static_library {
    # Will rebuild the static library as specified
    #     build_static_library sdk
    xcrun xcodebuild -project "${PROJECT_FILE_PATH}" \
    -target "${TARGET_NAME}" \
    -configuration "${CONFIGURATION}" \
    -sdk "${1}" \
    ONLY_ACTIVE_ARCH=NO \
    BUILD_DIR="${BUILD_DIR}" \
    OBJROOT="${OBJROOT}" \
    BUILD_ROOT="${BUILD_ROOT}" \
    SYMROOT="${SYMROOT}" $ACTION
}

function make_fat_library {
    # Will smash 2 static libs together
    #     make_fat_library in1 in2 out
    xcrun lipo -create "${1}" "${2}" -output "${3}"
}

# 1 - Extract the platform (iphoneos/iphonesimulator) from the SDK name
if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then
RW_SDK_PLATFORM=${BASH_REMATCH[1]}
else
echo "Could not find platform name from SDK_NAME: $SDK_NAME"
exit 1
fi

# 2 - Extract the version from the SDK
if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]; then
RW_SDK_VERSION=${BASH_REMATCH[1]}
else
echo "Could not find sdk version from SDK_NAME: $SDK_NAME"
exit 1
fi

# 3 - Determine the other platform
if [ "$RW_SDK_PLATFORM" == "iphoneos" ]; then
RW_OTHER_PLATFORM=iphonesimulator
else
RW_OTHER_PLATFORM=iphoneos
fi

# 4 - Find the build directory
if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$RW_SDK_PLATFORM$ ]]; then
RW_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${RW_OTHER_PLATFORM}"
else
echo "Could not find other platform build directory."
exit 1
fi

# Build the other platform.
build_static_library "${RW_OTHER_PLATFORM}${RW_SDK_VERSION}"

# If we're currently building for iphonesimulator, then need to rebuild
#   to ensure that we get both i386 and x86_64
if [ "$RW_SDK_PLATFORM" == "iphonesimulator" ]; then
build_static_library "${SDK_NAME}"
fi

# Join the 2 static libs into 1 and push into the .framework
make_fat_library "${BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \
"${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \
"${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}"

# Ensure that the framework is present in both platform's build directories
cp -a "${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}" \
"${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework/Versions/A/${RW_FRAMEWORK_NAME}"

# Copy the framework to the user's desktop
ditto "${RW_FRAMEWORK_LOCATION}" "${HOME}/Desktop/${RW_FRAMEWORK_NAME}.framework"
snaggs
  • 5,543
  • 17
  • 64
  • 127
  • I wonder that Xcode spits out all architectures with the settings shown. I suspect you are running a Build Phase Script. If not: Add `i386,x86_64` to your valid architectures and set `Build Active Architecture Only` to `NO` for `Release`. Also: what is the `file`output from. The Xcode build or the CLI build? Also, what is wrong with the "strange framework"? – shallowThought Dec 06 '16 at 20:16
  • @shallowThought I have `Build Active Architecture Only` `YES` for both Debug and Release. I also posted `Multiplatform script`. DO I need to run build static framework for both iOS and simulator? Under `strange framework` I mean that `MyAppLib.framework` is a file and not folder . – snaggs Dec 06 '16 at 20:27
  • If you want to use this library in an app, you want to be able to use it on a device and also debug your app in simulator. So yes, you do want to build for device and simulator. – shallowThought Dec 06 '16 at 20:42
  • Your build script does create a fat lib already. No need to do it again. The output is `MyAppLib.framework`. This looks all good. You should still add `i386,x86_64` to your valid architectures This is your static library, wrapped in a `framewor`. `MyAppLib.framework` should be a directory, not a file. In Terminal: `ls -la` the containing folder. Does it look like this (start with a "d" for directory): `drwxr-xr-x6 yorName staff 204 Dec 5 14:09 MyAppLib.framework`? – shallowThought Dec 06 '16 at 20:44
  • @shallowThought no, `MyApp.framework` is a file: `-rw-r--r--`. The script I posted generates `MyApp.framework` on my desktop but `lipo -create ...` command generates file instead package. Ill try to run `lipo` on framework files created on my desctop – snaggs Dec 06 '16 at 21:43
  • @shallowThought I tried and got error: `have the same architectures (armv7) and can't be in the same fat output file`. Looks like I need define somehow different architectures for iOS and simulator. I also added `i386,x86_64` – snaggs Dec 06 '16 at 21:53
  • @shallowThought if script runs `make_fat_library` do I need to run `lipo` at all? if framework contains all 4 arch. maybe what script built is enough, no matter for iOS or simulator. It looks the same – snaggs Dec 06 '16 at 22:07
  • You do not need to run `lipo`or anything else. If I am right, the script magically handles all for you. Everything is fine. `MyAppLib.framework` _is_ your static lib. You do not have a problem. :-) – shallowThought Dec 06 '16 at 22:43
  • @shallowThought thank you for clear description and your efforts – snaggs Dec 07 '16 at 07:38

1 Answers1

1

Solution:

You do not have a problem. The MyAppLib.framework that appears after building your project is your static library, containing slices for all required architectures.

No need to use lipo after building your project.

Issue:

Your build script "automatically" builds your target twice, once for devices and once for simulators. Afterwards it merges both build artefacts to one fat lib (make_fat_library) using lipo.

Afterwards it copies the result around to:

#Ensure that the framework is present in both platform's build directories

As a result, you have a fat lib framework in both build directories.

Now you are trying to merge those two (already merged) fat libs. As both contain the same slices you get the error.

shallowThought
  • 19,212
  • 9
  • 65
  • 112
  • I am also facing the similar architecture related issues in my project please go through the below link and help me out for this issue. https://stackoverflow.com/questions/59613498/flutter-app-is-not-x86-64-running-lipo-info-app-is-architecture-arm64 – Dhaval Kansara Jan 06 '20 at 14:12