-
-
Save atereshkov/df107336a076d5f34bc4b2a9eb6f9ad5 to your computer and use it in GitHub Desktop.
If you've got something like this: | |
file was built for arm64 which is not the architecture being linked (x86_64): | |
Than this gist is for you. | |
Let's say you have already developed the framework itself and just want to build the binary | |
and distribute it through the Cocoapods. | |
1. Make sure your framework "Deployment Target" is equal to all the dependencies from your podspec file. | |
2. In your framework target -> "Build Settings" -> "Skip install" set to No | |
3. In build schemes drop down choose your framework -> "Edit scheme" -> "Archive" -> "Post-actions" -> | |
Click "+" sign | |
4. From the "Provide build settings from" drop down choose your target. | |
5. Paste the script below: | |
exec > /tmp/${PROJECT_NAME}_archive.log 2>&1 | |
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal | |
if [ "true" == ${ALREADYINVOKED:-false} ] | |
then | |
echo "RECURSION: Detected, stopping" | |
else | |
export ALREADYINVOKED="true" | |
# make sure the output directory exists | |
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" | |
#mkdir -p "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework" | |
echo "Building for iPhoneSimulator" | |
xcodebuild -workspace "${WORKSPACE_PATH}" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone XS' ONLY_ACTIVE_ARCH=NO ARCHS='i386 x86_64' BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" BITCODE_GENERATION_MODE=bitcode clean build | |
# Step 1. Copy the framework structure (from iphoneos build) to the universal folder | |
echo "Copying to output folder" | |
cp -R "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/" "${UNIVERSAL_OUTPUTFOLDER}" | |
# Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory | |
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/." | |
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then | |
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule" | |
fi | |
# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory | |
echo "Combining executables" | |
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${EXECUTABLE_PATH}" | |
echo "Combining executables end" | |
# Step 4. Create universal binaries for embedded frameworks | |
for SUB_FRAMEWORK in $( ls "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks" ); do | |
BINARY_NAME="${SUB_FRAMEWORK%.*}" | |
echo "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" | |
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" | |
done | |
# Step 5. Convenience step to copy the framework to the project's directory | |
echo "Copying to project dir" | |
yes | cp -Rf "${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}" | |
open "${PROJECT_DIR}" | |
fi | |
6. Tick "Shared" checkbox at the very bottom. | |
7. !!! Select real device from the devices drop down (let's say your iPhone). Run "Product" -> "Archive" | |
8. Wait for the Organaizer window, then wait for a while and if everything is fine | |
the project root will be opened in the finder. | |
9. You'll have MyKit.framework file in the project root folder. | |
10. You can open MyKit.framework, navigate to "Modules" -> "MyKit.swiftmodule" and make sure you have all the | |
architectures (In my case for deployment target 10 there are 4 architectures: arm, arm64, i386, x86_64) | |
====== | |
In order to make the pod availiable through the Cocoapods, make the default pod setup as for usual pods. | |
Then make sure you have copied the .framework file to the (let's say) "Framework" folder. | |
You'll have .git folder, "Framework" folder, "LICENSE" file, "MyKit.podspec" files in the pod folder. | |
Your podspec file should looks similar to this: | |
Pod::Spec.new do |s| | |
s.name = "MyKit" | |
s.version = "1.0.0" | |
s.summary = "MyKit for iOS" | |
s.description = <<-DESC | |
MyKit for iOS. | |
DESC | |
s.homepage = "https://github.com/atereshkov/mykit" | |
s.license = "MIT" | |
s.author = "Alexander Tereshkov" | |
s.platform = :ios, "10.0" | |
s.source = { :git => "https://github.com/atereshkov/mykit.git", :tag => "#{s.version}" } | |
s.frameworks = 'UIKit', 'WebKit' | |
s.dependency 'Alamofire', '~> 4.8' | |
s.ios.vendored_frameworks = "Framework/MyKit.framework" | |
s.swift_version = "4.2" | |
end | |
====== | |
Then run "pod lib init" from the pod root folder | |
-> MyKit (1.0.0) | |
- NOTE | xcodebuild: note: Using new build system | |
- NOTE | [iOS] xcodebuild: note: Planning build | |
- NOTE | [iOS] xcodebuild: note: Constructing build description | |
- NOTE | [iOS] xcodebuild: warning: Skipping code signing because the target does not have an Info.plist file. (in target 'App') | |
And if you got the "MyKit passed validation." phrase, then everything is fine. | |
Just relax and continue with the default procedure of pod publication through the Cocoapods. | |
https://guides.cocoapods.org/making/making-a-cocoapod.html |
Pod::Spec.new do |s| | |
s.name = "MyKit" | |
s.version = "1.0.0" | |
s.summary = "MyKit for iOS" | |
s.description = <<-DESC | |
MyKit for iOS. | |
DESC | |
s.homepage = "https://github.com/atereshkov/mykit" | |
s.license = "MIT" | |
s.author = "Alexander Tereshkov" | |
s.platform = :ios, "10.0" | |
s.source = { :git => "https://github.com/atereshkov/mykit.git", :tag => "#{s.version}" } | |
s.frameworks = 'UIKit', 'WebKit' | |
s.dependency 'Alamofire', '~> 4.8' | |
s.ios.vendored_frameworks = "Framework/MyKit.framework" | |
s.swift_version = "4.2" | |
end |
exec > /tmp/${PROJECT_NAME}_archive.log 2>&1 | |
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal | |
if [ "true" == ${ALREADYINVOKED:-false} ] | |
then | |
echo "RECURSION: Detected, stopping" | |
else | |
export ALREADYINVOKED="true" | |
# make sure the output directory exists | |
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" | |
#mkdir -p "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework" | |
echo "Building for iPhoneSimulator" | |
xcodebuild -workspace "${WORKSPACE_PATH}" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone XS' ONLY_ACTIVE_ARCH=NO ARCHS='i386 x86_64' BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" BITCODE_GENERATION_MODE=bitcode clean build | |
# Step 1. Copy the framework structure (from iphoneos build) to the universal folder | |
echo "Copying to output folder" | |
cp -R "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/" "${UNIVERSAL_OUTPUTFOLDER}" | |
# Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory | |
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/." | |
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then | |
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule" | |
fi | |
# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory | |
echo "Combining executables" | |
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${EXECUTABLE_PATH}" | |
echo "Combining executables end" | |
# Step 4. Create universal binaries for embedded frameworks | |
for SUB_FRAMEWORK in $( ls "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks" ); do | |
BINARY_NAME="${SUB_FRAMEWORK%.*}" | |
echo "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" | |
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" | |
done | |
# Step 5. Convenience step to copy the framework to the project's directory | |
echo "Copying to project dir" | |
yes | cp -Rf "${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}" | |
open "${PROJECT_DIR}" | |
fi |
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
OUTPUT_FOLDER=${PROJECT_DIR}
make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
Step 1. Build Device and Simulator versions. This also includes the full bitcode generation of the framework
xcodebuild BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO clean build
xcodebuild BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO clean build
Step 2. Copy the framework structure (from iPhones build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
Step 3. Copy Swift modules (from iphonesimulator build) to the copied framework directory
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
Step 4. Create a 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" "${OUTPUT_FOLDER}"
Step 6. Convenience step to open the project's directory in Finder
open "${OUTPUT_FOLDER}"
I'm running this script to build a framework with cocoapods earlier in Xcode 10.3 it's working fine, But in new Xcode 11.2.1, this script is not working. can you please find me a workaround.
error ->
error: no such file or directory: '/Users/username/Documents/GitHub/sdkname/GenaratefremeWork/Pods/@/Users/username/Library/Developer/Xcode/DerivedData/SDK-ddyylnfmgscnezeppcqlekfbplzy/Build/Intermediates.noindex/SDK.build/Debug-iphoneos/SDK.build/Objects-normal/arm64/SDK.SwiftFileList'
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
I tried the above script with post actions but no luck not working with Xcode 11.2.1, can you please provide the script that works in the latest Xcode.
This is the right version if product_name differs from target_name:
exec > /tmp/${PROJECT_NAME}_archive.log 2>&1
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
echo ${UNIVERSAL_OUTPUTFOLDER}
if [ "true" == ${ALREADYINVOKED:-false} ]
then
echo "RECURSION: Detected, stopping"
else
export ALREADYINVOKED="true"
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
#mkdir -p "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework"
echo "Building for iPhoneSimulator"
xcodebuild -workspace "${WORKSPACE_PATH}" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator -destination "generic/platform=iOS Simulator" ONLY_ACTIVE_ARCH=NO ARCHS='x86_64' BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" BITCODE_GENERATION_MODE=bitcode clean build
# Step 1. Copy the framework structure (from iphoneos build) to the universal folder
echo "Copying to output folder"
cp -R "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/" "${UNIVERSAL_OUTPUTFOLDER}"
# Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PRODUCT_NAME}.framework/Modules/${PRODUCT_NAME}.swiftmodule/."
echo "Simulator dir ${SIMULATOR_SWIFT_MODULES_DIR}"
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PRODUCT_NAME}.framework/Modules/${PRODUCT_NAME}.swiftmodule"
fi
# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory
echo "Combining executables"
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${EXECUTABLE_PATH}"
echo "Combining executables end"
# Step 4. Create universal binaries for embedded frameworks
for SUB_FRAMEWORK in $( ls "${UNIVERSAL_OUTPUTFOLDER}/${PRODUCT_NAME}.framework/Frameworks" ); do
BINARY_NAME="${SUB_FRAMEWORK%.*}"
echo "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${PRODUCT_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}"
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PRODUCT_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}"
done
# Step 5. Convenience step to copy the framework to the project's directory
echo "Copying to project dir"
yes | cp -Rf "${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}"
open "${PROJECT_DIR}"
fi
hey thanks for your script, but I am having trouble using it with my framework which has a dependency. like I can not go to my framework project and click archive as the dependency is not added here in my project but marked as s.dependancy in the pod spec and thus client has to add it. so archive fails. can you help me with shipping the fat framework through the cocoa pod with dependencies? thanks in advance for your kind reply. basically, the dependency I added was app auth and it was built in objective c. and i couldn't find fat library for it and i added only the device framework, so once the archive has done i could see only arm64 related modules but not simulator one.
In iPhone XS only device modules added in framework
when i switched to iPhone 6, simulator modules added to framework
also tried iPhone X nothing happened like iPhone XS