i'v been working for hours for this 'little' problem.I tried to create a universal library and i managed to get 3 set of architecture, when i check my universal lib with lipo -info
armv7 i386 arm64
and with file command
Mach-O universal binary with 3 architectures
(for architecture armv7): current ar archive random library
(for architecture i386): current ar archive random library
(for architecture arm64): current ar archive random library
my shell script to create universal lib ;
# define output folder environment variable
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# Step 1. Build Device and Simulator versions
xcodebuild -target libTest ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target libTest ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator -arch i386 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# 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"
# Last touch. copy the header files. Just for convenience
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/"
my build settings;
build active architecture only - NO
Architectures;
$(ARCHS_STANDARD)
x86_64 (i added this)
Valid architectures;
armv7s
x86_64
armv7
arm64
i386
I tried everything and it still seems failed.How can I create a fat file with all these architectures?
Related
I am creating a universal framework by taking reference from https://agilewarrior.wordpress.com/2016/12/22/how-to-create-universal-static-library-ios/ but while running i am getting
Shell Script Invocation Error like below :
here is my configuration:
Here is my script for creating universal framework:
# define output folder environment variable
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# Step 1. Build Device and Simulator versions
xcodebuild -target ${PROJECT_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target ${PROJECT_NAME} -configuration ${CONFIGURATION} -sdk iphonesimulator -arch x86_64 -arch i386 -arch armv7 -arch armv7s -arch arm64 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# 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"
echo "Universal library can be found here:"
echo ${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a
# Last touch. copy the header files. Just for convenience
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/"
The above script is working in my another framework.but in current project it is giving error.
Environment: XCode 7.0.1
Module: Objective-C
Bundle Type: Framework
Hi, I am trying to create a framework to support armv7, armv7s, arm64, i386 and x86_64. I am using aggregate to make the fat library. Inside the aggregate script, i am running two xcodebuild commands 1. for armv7, armv7s and arm64 and 2. for i386 and x86_64 architectures. Also, I have set Enable Bitcode=YES and Other C Flags=-fembed-bitcode under target build settings. As a precautionary mesasure, i am adding ENABLE_BITCODE=YES and OTHER_CFLAGS="-fembed-bitcode" options to the xcodebuild command
My xcode build commands are as follows -
#Build The framework Target for iPhoneOS
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${AN_TARGET}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphoneos
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="armv7 armv7s arm64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION
#Build The framework Target for iPhoneSimulator
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${AN_TARGET}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphonesimulator
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_SIMULATOR_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="i386 x86_64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION
after running the above two commands, i am combining these two builds to make a fat framework binary using the below command
# create a fat Framework
lipo -create
"${IPHONE_DEVICE_BUILD_DIR}/${PROJECT_NAME}.framework/${PROJECT_NAME}"
"${IPHONE_SIMULATOR_BUILD_DIR}/${PROJECT_NAME}.framework/${PROJECT_NAME}" -
output "${FRAMEWORK_FOLDER}/${AN_END_USER_FRAMEWORK_NAME}"
The issue iam facing is after the lipo is created, i am unable to use it in the bitcode enabled application. After running the otool -l framework_binary | grep -LLVM, i do not see the bitcode enabled flags or __LLVM.
Lipo removes bitcode from the fat binary. Is there a way i can retain bitcode while running the lipo command?
Correction: Based on the reply from Nestor, i ran the otool command as otool -l -arch armv7 framework_binary | grep LLVM and much to my surprise, i could see the segname __LLVM clang. However when i integrate the same fat framework binary into my project, it builds fine on simulator however throws the following error while running on device - ld: 'MyBinary' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture armv7
Happily it's just a problem with otool's reporting, not lipo; you have to add the -arch parameter:
otool -arch arm64 -l myLipoOutput.a
Source: http://www.openradar.me/radar?id=6301306440384512
This is something weird, there are not many documentation for do this, at the end I use this command:
xcodebuild -project ${PROJECT_NAME}.xcodeproj -target ${FRAMEWORK_NAME} ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode FRAMEWORK_SEARCH_PATHS="${FRAMEWORK_SEARCH_PARTH} ${SRCROOT}/**" -sdk ${SIMULATOR_SDK} -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-${SIMULATOR_SDK} 2>&1
xcodebuild -project ${PROJECT_NAME}.xcodeproj -target ${FRAMEWORK_NAME} -sdk ${DEVICE_SDK} ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode FRAMEWORK_SEARCH_PATHS="${FRAMEWORK_SEARCH_PARTH} ${SRCROOT}/**" -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-${DEVICE_SDK} 2>&1
Add the BITCODE_GENERATION_MODE=bitcode flag to the xcodebuild command
Try to use archive for the arm slices instead of build
xcodebuild -scheme "${SCHEME}" -workspace "${WORKSPACE}" -configuration "${CONFIGURATION}" -sdk iphoneos ARCHS="arm64 armv7 armv7s" CONFIGURATION_BUILD_DIR="${CONFIGURATION_BUILD_DIR}/arm" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO archive
After that run lipo to merge the simulator and the arm ones.
And after that run otool -arch arm64 -l myLipoOutput.a and it should work.
It looks like a bug in Xcode 7.0.1 . I've had the same issue and downgrading Xcode to version 7 fixed it.
Update:
Actually it may be a bug in Xcode 7 that was fixed in 7.0.1 - this SO answer solved the issue for me.
I need to build dynamic library as framework. I have building settings as follows:
ARCHS: armv7 armv7s arm64 i386 x86_64
ONLY_ACTIVE_ARCH: NO
VALID_ARCHS: arm64 armv7 armv7s x86_64 i386
I built target for ios device, and used lipo -info to check the architectures, the result is :
Architectures in the fat file: dyl are: armv7s armv7 arm64
So, does xcode can not build for both i386 and arm?
You need to select iOS simulator and build a framework for i386 arch. Then you can use lipo -create command to merge the two framework into one.
There is a way of doing it without exiting the Xcode. First you need to identify the latest iOS versions (64 bits) do not support i386 architecture. So if you still need i386 compatible framework, you have to build your project by selecting an old iOS version. I tried with iOS 10.
Next thing that you have to do is, add all the architectures that you need under Valid Architectures filed in the Build Settings.
Then, add a Run Script with your lipo commands to create the FAT file. (Following script I've taken from the Internet sometime back & credit goes to those who wrote that)
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/."
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
fi
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 6. Convenience step to open the project's directory in Finder
open "${PROJECT_DIR}"
Finally what you have to do is, build the framework by selecting Generic iOS Device option.
Then to verify, run the lipo -info command
While i am integrating libcurl, getting the following issue.
Undefined symbols for architecture i386:
"_SSLClose", referenced from:
_Curl_darwinssl_close in libcurl.a(libcurl_la-curl_darwinssl.o)
"_SSLCopyPeerTrust", referenced from:
_darwinssl_connect_common in libcurl.a(libcurl_la-curl_darwinssl.o)
"_SSLCreateContext", referenced from:
_darwinssl_connect_common in libcurl.a(libcurl_la-curl_darwinssl.o)
_darwinssl_connect_common in libcurl.a(libcurl_la-curl_darwinssl.o)
_Curl_darwinssl_close in libcurl.a(libcurl_la-curl_darwinssl.o)
"_SSLGetBufferedReadSize", referenced from:
The static library that you have added libcurl.a is meant for device. you are trying to build your application for simulator (i386 is for Mac). Either change your libcurl.a or build your application for Device would solve your problem.
I once ran this an issue like this with another library. The problem is that the simulator runs on an x86 processor and the actual device is on ARM, you actually need two separate builds of the library in the project. One for the simulator and one for ARM. If you are targeting ARM-64, you will need a build for it too.
Replace this in your Run Script... Hope this will fix
define output folder environment variable
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
Step 1. Build Device and Simulator versions
xcodebuild -target GEOAuthAuthentication ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target GEOAuthAuthentication -configuration ${CONFIGURATION} -sdk iphonesimulator -arch i386 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target GEOAuthAuthentication -configuration ${CONFIGURATION} -sdk iphonesimulator -arch x86_64 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" TARGET_BUILD_DIR="./build-x86_64"
make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
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" "./build-x86_64/lib${PROJECT_NAME}.a"
Last touch. copy the header files. Just for convenience
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/"
Check in your Targets->Build Phases-> Link Binary With Labraries is all required frameworks and libraries added
Few days ago i create static-library (Universal) that work's fine with Xcode5.0 SDK7. After Update Xcode5.1 with SDK7.1 that not work if i select simulator iPhone Retina(4-inch 64-bit). Then i am going to update my lib with Bellow setting change.
I do the same for three Target:-
For sporting simulator as well as device i put Universal lib and in to this i run script this:-
After this i Build Again lib and used as i done Before in to my project. But still getting same issue with iPhone Retina(4-inch 64-bit) Undefined symbols for architecture x86_64:
So, My question is that is there any additional change required for updating lib for arm64 or i did any mistake in above step. Please current me if i am wrong.
what change needed for update my static-library for supporting 64Bit architecture
NOTE:
I am asking for my own created Library Update. i am not using third-party Library.
Update
I used this lipo -info testingLibImport/libLibNSlog.a command in to my Terminal that output is:
Architectures in the fat file: testingLibImport/libLibNSlog.a are: armv7 armv7s i386 arm64
Another solution I found with XCode 6.4 is to add ONLY_ACTIVE_ARCH=NO and not specify the architecture. So
xcodebuild -target TargetName ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
Will build i386 and x86_64 architectures in your library.
Here's my full universal lib run script to build all the architectures.
# define output folder environment variable
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# Step 1. Build Device and Simulator versions
xcodebuild -target TargetName ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target TargetName ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# 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"
# Last touch. copy the header files. Just for convenience
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/"
I too ran into the same problem yesterday and after lot of googling and trying on different solutions, i gave up and tried on my own. All i could understand from the different solutions provided was that when i run "lipo -info library.a" it was not built for x86_64 architecture. So, decided to give up the aggregate approach and made a simple attempt.
as advised in this post, i added armv7, armv7s and arm64 to the architectures.
build the static library project with iphone simulator (32 bit)
build the static library project with iphone simulator (64 bit)
build the static library project with iOS device
go to the build path (under derived data)
copied both simulator and device output to a common folder
used lipo command in terminal window to create the universal library
lipo command: lipo -create -output newlibraryname.a simulatorlibraryname.a devicelibraryname.a
integrated the newly created universal static library and it WORKED!!!
After lots of stuff i got solution. some of xcode dont know there is automatic appear Standard architectures (including 64-bit) (armv7,armv7s,arm64) but in my case there is not option into my Static Library Project. so i am going to add this Manually like:-
and select this Option:-
After this i re-Build My static Library and used in to in my project that working fine now. and I also checked with lipo command in to terminal that output going to different now:-
testingLibImport/libLibNSlog.a are: armv7 armv7s i386 x86_64 arm64
Sorry for posting another solution so late. I had found this solution long time back when i was trying to find a solution that would save me from the manual work of creating a universal library using lipo command every time i had to build the universal library.
So, here is the another approach, for those using aggregate approach to build the universal library
just make one small change as mentioned below in your aggregate script for simulator to build the universal library -
xcodebuild -target ProductName -configuration ${CONFIGURATION} -sdk iphonesimulator ARCHS="i386 x86_64" BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}"
Please observe the inclusion of multiple architectures instead of using single architecture approach -
xcodebuild -target ProductName -configuration ${CONFIGURATION} -sdk iphonesimulator -arch i386 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}"
Just ARCHS="i386 x86_64" will do the magic for you.
You can confirm this by using the following lipo command
lipo -info newLibraryName.a
Hope this saves time for many others like me!!!