Abhinav
Abhinav

Reputation: 38142

Facing lipo error while creating a single fat file

I am trying to create a single .a file which will contain 3 different .a files so that I could share only one .a file. This is the command I am using

lipo -create -output ./libOutput.a ./libInput1.lib ./libInput2.lib ./libInput3.lib

but I am getting this lipo error:

./libInput1.lib and ./libInput2.lib have the same architectures (i386) and can't be in the same fat output file

Any idea how to get rid of this?

Upvotes: 9

Views: 10748

Answers (5)

Myrddin
Myrddin

Reputation: 81

Go the target YourLibUniversal/Build Phases/Run script

Then look if the script mentions SIMULATOR_DIR_32 and SIMULATOR_DIR_64 If yes, remove theses references and just set one reference SIMULATOR_DIR

I had:

SIMULATOR_DIR_32=${SYMROOT}/${CONFIGURATION}-iphonesimulator-i386
SIMULATOR_DIR_64=${SYMROOT}/${CONFIGURATION}-iphonesimulator-x86_64
...
lipo -create "${DEVICE_DIR}/lib${LIB_NAME}.a" "${SIMULATOR_DIR_32}/lib${LIB_NAME}.a" "${SIMULATOR_DIR_64}/lib${LIB_NAME}.a" -output "${INSTALL_DIR}/lib${LIB_NAME}Universal.a"

I changed it to that:

SIMULATOR_DIR=${SYMROOT}/${CONFIGURATION}-iphonesimulator-x86_64
...
lipo -create "${DEVICE_DIR}/lib${LIB_NAME}.a" "${SIMULATOR_DIR}/lib${LIB_NAME}.a" -output "${INSTALL_DIR}/lib${LIB_NAME}Universal.a"

Upvotes: 0

xaphod
xaphod

Reputation: 6794

OK, I got it working. Here is my (entire) version of the run script

# Taken from Ray Wenderlich tutorial: http://www.raywenderlich.com/65964/create-a-framework-for-ios

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"

OUTPUT_LOCATION="${HOME}/Desktop"
if [ ! -w ${OUTPUT_LOCATION} ] ; then OUTPUT_LOCATION="${XCS_OUTPUT_DIR}" ; fi
if [ ! -w ${OUTPUT_LOCATION} ] ; then OUTPUT_LOCATION="/tmp" ; fi
if [ ! -w ${OUTPUT_LOCATION} ] ; then echo "Couldn't find anywhere to write! Dying."; exit 1 ; fi

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

echo "RW_SDK_PLATFORM is ${RW_SDK_PLATFORM}"

# 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

echo "RW_SDK_VERSION is ${RW_SDK_VERSION}"

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

echo "RW_OTHER_PLATFORM is ${RW_OTHER_PLATFORM}"

# 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

echo "BUILT_PRODUCTS_DIR is ${BUILT_PRODUCTS_DIR}"
echo "RW_OTHER_BUILT_PRODUCTS_DIR is ${RW_OTHER_BUILT_PRODUCTS_DIR}"

# remove alias and copy, if it's archive
UNINSTALLED_PRODUCTS_DIRECTORY="${BUILT_PRODUCTS_DIR}/../../IntermediateBuildFilesPath/UninstalledProducts"

if [ -d "$UNINSTALLED_PRODUCTS_DIRECTORY" ]; then
    echo "Looks like we're archiving, fixing aliases..."
    rm "${BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}"
    cp "${UNINSTALLED_PRODUCTS_DIRECTORY}/${RW_INPUT_STATIC_LIB}" "${BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}"
fi

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

if [ -d "$UNINSTALLED_PRODUCTS_DIRECTORY" ]; then
    echo "Looks like we're archiving, fixing aliases..."
    rm "${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}"
    cp "${UNINSTALLED_PRODUCTS_DIRECTORY}/${RW_INPUT_STATIC_LIB}" "${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}"
fi

# 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
ditto "${RW_FRAMEWORK_LOCATION}" "${OUTPUT_LOCATION}/${RW_FRAMEWORK_NAME}.framework"

# Copy the resources bundle
ditto "${BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.bundle" \
"${OUTPUT_LOCATION}/${RW_FRAMEWORK_NAME}.bundle"

echo "DONE. ***** FINAL FRAMEWORK AND BUNDLE WERE COPIED HERE: ${OUTPUT_LOCATION} *****"

Upvotes: 2

fpesce
fpesce

Reputation: 71

A workaround that worked for me (because I couldn't figure out what part of the building process was creating an additional architecture target to the compilation):just remove the architecture from one of the two .a libraries.

First, you can list the architecture with a simple file command:

$ file libwhatever.a
libwhatever.a: Mach-O universal binary with 4 architectures
libwhatever.a (for architecture armv7): current ar archive random library
libwhatever.a (for architecture armv7s): current ar archive random library
libwhatever.a (for architecture arm64): current ar archive random library
libwhatever.a (for architecture i386): current ar archive random library

$ file libfoo.a
libfoo.a: Mach-O universal binary with 2 architectures
libfoo.a (for architecture i386): current ar archive random library
libfoo.a (for architecture x86_64): current ar archive random library

Then, this workaround is just about removing the i386 arch from the first libwhatever.a (which was supposed to be just for arm* arch in my case anyway).

lipo -remove i386 libwhatever.a -output /tmp/libwhatever.a
mv /tmp/libwhatever.a libwhatever.a

and then you can create/merge your .a files without any warning.

Upvotes: 6

Lucas Goossen
Lucas Goossen

Reputation: 517

So this is the second time I have been here. The answer did not fix my problem. What I have found is that this is actually a bug in Xcode. What has happened both times is that I come and find this answer and that is not my problem and then I'm messing around for hours trying to figure out what's going on and the next thing I know Xcode crashes. Open up Xcode again and magic the problem is gone.

So I am adding my answer to help me remember this next time.

Upvotes: 5

SwiftWarrior
SwiftWarrior

Reputation: 1964

I just had that same error message, and it was due to the fact that I had my architecture set to "other" and had typed in arm6. To fix the problem I simply changed my architecture setting to one of the default values, in my case I picked Standard (arm6 arm7). The Architectures setting can be found in your project build settings.

Upvotes: 4

Related Questions