I'm trying to understand how building frameworks works more in general. I created a new framework project in Xcode 10 and I can see in Build Settings arm64 armv7 armv7s all defined in Valid Architectures. When I make a build for Generic iOS Device and use lipo -info I get only armv7 arm64 and no armv7s. I tried to do it from the command line as well:
xcodebuild -configuration Release -sdk iphoneos -target FrameworkExample ONLY_ACTIVE_ARCH=NO BUILD_DIR="BUILD_DIR"
I also tried manually passing each architecture
-arch armv7s -arch arm64 -arch armv7 but I only got armv7 and arm64 again.
I also tried using destination
-destination generic/platform=iOS
Same result.
My project's Deployment Target and Framework Targets are both set to 8.0.
Related
I am creating Framework, I used aggregate target in that framework where we can write shell script to Build the framework for device as well as simulator based on script based on that i will have executable framework that can be imported in any project and we can use that class and method of framework.
But issue is that when we create executable framework with "schema device" then i can able to run on all device but if i make build using particular iOS5/iOS6 simulator then it will run only selected iOS5/iOS6 simulator in client project.
if i have created framework build using iOS5 simulator and if i run that framework in client project and i used iOS6 simulator it gives Undefined symbols for architecture x86_64.
I need shell script which support both architecture i386 and x86_64 means my framework should be executable for all device and all simulator in client project.
Any insights into this would be really helpful.
Create aggregate target and inside its Build Phases -> Run script write script to:
Build 2 separate frameworks:
1. Framework with architectures for mobile devices (armv7, arm64, etc.)
2. Framework with architectures for simulator (i386 and x86_64).
For example:
xcodebuild -workspace MyApp.xcworkspace -scheme MyFrameworkScheme -arch i386 -arch x86_64 ONLY_ACTIVE_ARCH=NO -sdk iphonesimulator -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator BUILD_DIR=${BUILD_DIR}
xcodebuild -workspace MyApp.xcworkspace -scheme MyFrameworkScheme -arch armv7 -arch armv7s -arch arm64 ONLY_ACTIVE_ARCH=NO -sdk iphoneos -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos BUILD_DIR=${BUILD_DIR}
Then, use lipo to merge the libraries inside both frameworks to a fat library, and replace one of them inside the framework => you have a fat framework.
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'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?
Preface: I did look at similar questions and none of the answers seemed to fix my problem.
I am trying to build my xcode (version 5.1.1) project using:
xcodebuild clean build -sdk iphonesimulator7.0 -arch "armv7s" ONLY_ACTIVE_ARCH=NO,
when I run this I get: No architectures to compile for (ARCHS=armv7s, VALID_ARCHS=i386 x86_64) as an error. I tried the above command with all of the VALID_ARCHS (rm64 armv7 armv7s) as inputs. So I then tried running this command:
xcodebuild clean build -sdk iphonesimulator7.0 -arch "i386" ONLY_ACTIVE_ARCH=NO
and I then get No architectures to compile for (ARCHS=i386, VALID_ARCHS=arm64 armv7 armv7s) as an error. I tried running the above command with all the other VALID_ARCHS (i386 x86_64) and no luck with that either. I don't know why these architecture errors are occurring. I have cocoapods in my project, and the first answer in the link above didn't fix my issue.
You can override your default variables:
Try to use this:
xcodebuild clean build -sdk iphonesimulator7.0 -arch "i386" ONLY_ACTIVE_ARCH=NO VALID_ARCHS="i386 x86_64"
If you building for Simulator - always build for i386/x86_64.
Go to your project settings (not targets). Then open Build Settings and add a value to Valid architectures: i386
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!!!