I managed to use Xcconfig to build my app, but as in the config itself, I need to specify such as...
ARCHS = $(ARCHS_STANDARD_32_BIT)
SDKROOT = iphoneos
So I have two files, such as Debug-Simulator.xcconfig and Debug-Device.xcconfig.
But in the XCode, I can only attach one Debug and one Release XCodeConfig, so how to auto change the configuration automatically without I change the Debug configuration manually?
You can conditionalize lines of your .xcconfig file based on the SDK name. For instance...
ARCHS[sdk=iphoneos*] = armv7
ARCHS[sdk=iphonesimulator*] = $(ARCHS_STANDARD_32_BIT)
I think that's what you're looking for here, right? I'm not sure the full extent of these predicates' syntax, but the above works for me when trying to change build settings beteen Simulator and Device.
You can even use this to conditionalize for multiple versions of SDK, like they do here: Base.xcconfig
Are you using Command-line?
xcodebuild -configuration Debug ...
xcodebuild -configuration Release ..
You can refer to the usage of xcodebuild.
Options:
-usage print full usage
-verbose provide additional status output
-project NAME build the project NAME
-target NAME build the target NAME
-alltargets build all targets
-workspace NAME build the workspace NAME
-scheme NAME build the scheme NAME
-configuration NAME use the build configuration NAME for building each target
-xcconfig PATH apply the build settings defined in the file at PATH as overrides
-arch ARCH build each target for the architecture ARCH; this will override architectures defined in the project
-sdk SDK use SDK as the name or path of the base SDK when building the project
-parallelizeTargets build independent targets in parallel
-jobs NUMBER specify the maximum number of concurrent build operations
-showsdks display a compact list of the installed SDKs
-list lists the targets and configurations in a project, or the schemes in a workspace
-find BINARY display the full path to BINARY in the provided SDK
-version display the version of Xcode; with -sdk will display info about one or all installed SDKs
Related
I have an Xcode 10 - iOS12 swift project that links against My own framework (also Xcode 10 + iOS12).
The app project is referencing my framework project as a sub-project reference.
My Framework project references PromiseKit.framework (a universal framework - fat library), made using the following build script:
# Merge Script
# 1
# Set bash script to exit immediately if any commands fail.
set -e
# 2
# Setup some constants for use later on.
FRAMEWORK_NAME="PromiseKit"
# 3
# If remnants from a previous build exist, delete them.
if [ -d "${SRCROOT}/build" ]; then
rm -rf "${SRCROOT}/build"
fi
# 4
# Build the framework for device and for simulator (using
# all needed architectures).
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch arm64 only_active_arch=no defines_module=yes -sdk "iphoneos"
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 only_active_arch=no defines_module=yes -sdk "iphonesimulator"
# 5
# Remove .framework file if exists on Desktop from previous run.
if [ -d "${SRCROOT}/${FRAMEWORK_NAME}.framework" ]; then
rm -rf "${SRCROOT}/${FRAMEWORK_NAME}.framework"
fi
# 6
# Copy the device version of framework to Desktop.
cp -r "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${SRCROOT}/${FRAMEWORK_NAME}.framework"
# 7
# Replace the framework executable within the framework with
# a new version created by merging the device and simulator
# frameworks' executables with lipo.
lipo -create -output "${SRCROOT}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"
# 8
# Copy the Swift module mappings for the simulator into the
# framework. The device mappings already exist from step 6.
cp -r "${SRCROOT}/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${SRCROOT}/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule"
# 9
# Delete the most recent build.
if [ -d "${SRCROOT}/build" ]; then
rm -rf "${SRCROOT}/build"
fi
When I go to archive my Parent App Project using Xcode 10 (And also 9.4.1) with Bitcode ON (that contains My Framework reference, and PromiseKit Fat library), I get the following error on the Signing stage: (Failed to verify bitcode in PromiseKit.framework/PromiseKit: error Cannot extract bundle from /var/folders..../(x86_64) - which suggests that it's simulator slice related)
If I turn the "Rebuild from Bitcode" option in the Organizer to OFF, then I get a different error: (Code signing "PromiseKit.framework" failed)
However, if I use Xcode 9.4.1 With Bitcode OFF, then it exports and signs fine.
Why is it trying to individually re-sign sub frameworks, and what can I do to alleviate the issues? I need the archiving to work normally with Xcode 10, along with any future third party dependencies being added to my framework target. (This is the first dynamic framework dependency added to my Framework target. Before I was "baking in" - in-boarding all 3rd parties for ease of development purposes, but PromiseKit is difficult to inboard due to extensive dependencies on Objective-c).
The Xcode Archive log is:
{
code = 330;
description = "Failed to resolve linkage dependency PromiseKit x86_64 -> #rpath/libswiftFoundation.dylib: Unknown arch x86_64";
info = {
};
level = WARN;
},
{
code = 330;
description = "Failed to resolve linkage dependency PromiseKit x86_64 -> #rpath/libswiftObjectiveC.dylib: Unknown arch x86_64";
info = {
};
level = WARN;
},
{
code = 0;
description = "Failed to verify bitcode in PromiseKit.framework/PromiseKit:\nerror: Cannot extract bundle from /var/folders/q5/hm9v_6x53lj0gj02yxqtkmd40000gn/T/IDEDistributionOptionThinning.RJD/Payload/MyAppName.app/Frameworks/PromiseKit.framework/PromiseKit (x86_64)\n\n";
info = {
};
level = ERROR;
type = "malformed-payload";
}
);
Some other solutions I tried was using a Project Reference to PromiseKit, instead of a Framework reference, however this doesn't work - in that I still need a framework reference from my main project, because I will get "library not loaded" error at runtime, if running without a FW reference. Same issue occurs when archiving while using a project reference.
Try this! It worked for me and many other people:
Goto
Build phases > Add > New Run Script Phase
The code should work for any default shell, but I recommend just using /bin/sh
and include the following code:
# Type a script or drag a script file from your workspace to insert its path.
# skip if we run in debug
if [ "$CONFIGURATION" == "Debug" ]; then
echo "Skip frameworks cleaning in debug version"
exit 0
fi
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[#]}"
rm "${EXTRACTED_ARCHS[#]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
It seems hat some frameworks ship architectures, that will not be used in the application.
Xcode will refuse to sign them. The above script removes unused architectures.
Credits: Some guy at GitHub, I can't find the exact source anymore.
Same issue here. The only workaround I've found is to use static library instead of framework.
In case you are not able to use static library, you'd better file a bug report to Apple.
This is what worked for me,
I have application and 2 in-house built frameworks, say A $ B.
Application needs A, but A needs B and since Apple doesn't recommend nesting frameworks, so both A and B had to be included in the app.
This is what my Xcode project looks like.
SOLUTION
In the application, under Frameworks, Libraries and Embedded Content, select Embed & Sign for all necessary frameworks. (as shown below)
But for all the custom framework projects, under Frameworks and Libraries section, select Do Not Embed. (as shown below)
This fixed the issue for me
I am not able to build a project from command line in the latest Xcode 8 beta version. Can you please let me know the "xcodebuild" commands for Xcode 8 beta version to build a project through command line. previous commands which we used in previous versions of Xcode does not work now. Every time it throws and error : "Check dependencies
Signing for MyTestApp3 requires a development team. Select a development team in the Target Editor.
Code signing is required for product type 'Application' in SDK 'iOS 10.0'"
Command i used to build - xcodebuild -project MyTestApp3.xcodeproj -sdk iphoneos -configuration Release clean build DEBUG_INFORMATION_FORMAT=dwarf-with-dsym DSTROOT=build GCC_GENERATE_DEBUGGING_SYMBOLS=YES SHARED_PRECOMPS_DIR=build OBJROOT=build SYMROOT=build PROVISIONING_PROFILE_SPECIFIER= CODE_SIGN_IDENTITY="iPhone Distribution: Our Distribution Certificate".
Did you try DEVELOPMENT_TEAM command line parameter?
It can also be set in Xcode (General and Build Settings tabs).
I found the solution by this answer!
Mybe you also want to know how to get the 10-digit team id. Well, I found it in the output of command
xcodebuild -showBuildSettings -project <YourProject> |grep DEVELOPMENT_TEAM
I've built a framework in Swift. The framework uses Cocoapods, one of the pods is written in Objective C.
I also use a custom script to make the framework a fat framework so it supports 32/64 bit systems. (This runs in a separate target on the project and I'm wondering if that has something to do with it?)
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
if [ "true" == ${ALREADYINVOKED:-false} ]
then
echo "RECURSION: Detected, stopping"
else
export ALREADYINVOKED="true"
// 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) 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 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}"
fi
When I create this fat framework and put it into a project I'd like to use it on the compiler always fails b/c the project can't see the objective C cocoa pod module.
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ld: framework not found Pusher for architecture x86_64
It is not found for any architecture when I change the build platform.
Any solution where I can produce a framework that I can use in a separate Xcode project (for all iOS or OS X) would be awesome.
You can't run xcodebuild with -target when using CocoaPods. When you use -target, Xcode will only consider the active project and fail to pull in the Pod dependencies, similar to if you just opened the project file in Xcode and tried building.
You should be running xcodebuild -workspace "${PROJECT_NAME}.xcworkspace" -scheme "${PROJECT_NAME}" ..., assuming that CocoaPods generated the workspace and Xcode generated a scheme using the target name. You will also need to make sure your scheme is marked as shared if running this on another device.
Once your framework is built you will need to include it and the frameworks it depends on in apps that will be using it. For your framework, that means including it in General > Embedded Binaries and General > Linked Frameworks and Libraries. For frameworks you depend on, (e.g. AlamoFire), you could instruct users to include it in their Podfile, you could package it and ship it along with your framework, or you could do both and let the user do what works for them.
Apparently you are missing the 64bit architecture for Simulator.
When you build a target from Xcode, depending on what kind of simulator you have selected - the produced library will contains i386 or x86_64 respectively for selected 32bit or 64bit version of the simulator.
I guess that the cli build is producing only i386 version.
You can try to set the architectures in the script:
xcodebuild -target "${PROJECT_NAME}" ARCHS="i386 x86_64" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
As an alternative You can try to build by hand using 64bit simulator (iPhone 5S +), then extract the missing architecture and then put it into the final library using lipo command.
I've used to build my project with
xcodebuild -proj MyProject.xcodeproj -target MyTarget - configuration Debug -sdk iphonesimulator4.3
this works(it builds fine) but when I hit run in xcode, it recompiles.
(with xcode3, there was no need to rebuild once I build using command line)
I suspect xcode build use workspace/scheme rather than project/target.
How do I find out the workspace name that my current xcode project is using?
Thank you
edit
Chetan's links gave me directions what to look for.
xcode4 stores build output in ~/Library/...
whereas xcodebuild -project .. saves build output in project's build directory.
(if you want the workspace capability, you can't use the build directory for build output)
I created a workspace containing my project and ran
xcodebuild -workspace myWorkSpace -scheme myScheme
this saves build output in ~/Library/...../Debug-iphoneos
whereas xcode4 run button from the same workspace and same scheme saves output in
~/Library/..../Debug-iphonesimulator
any guess on why xcodebuild command uses Debug-iphoneos? :(
edit2
xcodebuild -workspace myWorkSpace -scheme myScheme -sdk iphonesimulator4.3
specifying sdk solved it
I know it isn't strictly the answer to your question, but you can configure the output directory of your build using the CONFIGURATION_BUILD_DIR environment variable.
Source: http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/0-Introduction/introduction.html#//apple_ref/doc/uid/TP40003931-CH1-SW1
Can everything which is done through Xcode GUI be done through command line, like changing app name, changing provisional profile, distribution profile? If yes then how. May be it can be done through xcodebuild , but till now i am only able to compile through xcodebuild.
Yes. Building can be done through xcodebuild:
$ xcodebuild -help
Usage: xcodebuild [-project <projectname>] [-activetarget] [-alltargets] [-target <targetname>]... [-parallelizeTargets] [-activeconfiguration] [-configuration <configurationname>] [-sdk <sdkfullpath>|<sdkname>] [-xcconfig <filepath>] [<buildsetting>=<value>]... [<buildaction>]...
xcodebuild [-version [-sdk [<sdkfullpath>|<sdkname>] [<item>] ]
xcodebuild [-showsdks]
xcodebuild [-find <binary> -sdk <sdkfullpath>|<sdkname>]
xcodebuild [-list]
…but I see you already know that. The application name can be changed by simply editing the Info.plist file. And I think you can change the profiles by hacking the *.pbxproj file (it’s a regular text file). You can save a copy of the project file, change a profile through the IDE and then diff the new version and the saved copy to see the changes:
$ find . -name '*.pbxproj'
./Source/Foo.xcodeproj/project.pbxproj
$ cp Source/Foo.xcodeproj/project.pbxproj ~/Desktop
# …now changing the profile through IDE…
$ diff Source/Foo.xcodeproj/project.pbxproj ~/Desktop/project.pbxproj
517d516
< "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "…";
534d532
< "PROVISIONING_PROFILE[sdk=iphoneos*]" = "…";
But it depends on what you are trying to do. You could switch the profiles much easier by setting different profiles for different build modes (Debug/Distribution/Whatever).