xcodebuild archives all targets instead of one - ios

I need to archive a specific scheme from my xcodeproj. To do this I run
xcodebuild archive \
-scheme $SCHEME \
-target $TARGET \
-archivePath $ARCHIVE_PATH
Although I explicitly define a scheme and target, the resulting xcarchive contains both targets and the follow-up IPA export call complains with
error: the archive at path '<path>.xcarchive' is not a single-bundle archive
** EXPORT FAILED **
Why does xcodebuild produce an archive with multiple bundles?

It was a problem with the project's schemes. I created new Schemes by duplicating the original one instead of adding a new one. The resulting scheme then listed 2 targets in the build section instead of one (only god knows why) and Xcode would not let me remove the other target.
Once I removed all schemes and created them from scratch everything worked just fine.

One more scenario when this happens is when your sub-project(Target dependency) has Skip Install set to No in build settings.
To find which sub-project, check the content inside the archive. Products folder should have only one product.
In my case a sub-project was a dynamic library and was added in the archive under /<path to archive>/Products/usr/lib/<library> path.

Related

What could cause code coverage enabled builds to fail?

Summary
I'm trying to get a code coverage report from my project. However when I try to build and run tests, there is no CodeCoverage folder created in the derived data folder.
How am I trying to do this?
I am running xcodebuild as follows:
xcodebuild \
-workspace <some_workspace> \
-scheme <some_scheme> \
-destination <some_destination> \
-derivedDataPath <some_path> \
-enableCodeCoverage YES \
build test
What is the problem?
For my workspace/project it fails at the very end with a line:
xcodebuild: error: Failed to build workspace <some_workspace> with scheme <some_scheme>.
Reason: Could not determine bundle identifier for <some_test_target>'s TEST_HOST: "<some_path>/Build/Intermediates/CodeCoverage/Products/Debug-iphonesimulator/<some_product>.app"
At first it seemed directly linked to the TEST_HOST issue, but that's not the case here.
There is simply no CodeCoverage folder:
<some_path>/Build/Intermediates/CodeCoverage
What have I tried?
I tried the same with a clean new project, same running the same xcodebuild command, which succeeds. Within the Build/Intermediates/ folder exists the CodeCoverage folder.
However, in my own project, which is more complex, the Build/Intermediates/ folder contains a bunch of *.build folders (related to the app and the various frameworks, HockeySDK.build for example) and PrecompiledHeaders but no CodeCoverage folder.
When looking through the output of xcodebuild I never see a reference to the CodeCoverage folder for my project. However, for the test project, the first mention is at:
Write auxiliary files
/bin/mkdir -p /<some_path>/Build/Intermediates/CodeCoverage/Intermediates/<some_project>.build/Debug-iphonesimulator/<some_project>.build/Objects-normal/x86_64
For my project I see:
Write auxiliary files
/bin/mkdir -p /<some_path>/Build/Intermediates/<some_project>.build/Debug-iphonesimulator/<some_project>.build/Objects-normal/x86_64
Workaround
Something else that seemed to 'trick' it into working is to set the Host Application to None. After doing this it builds and tests, but tests fail due to the lack of host. However, this causes the CodeCoverage folder to be created, and if the Host Application is correctly set again, running the build and tests works fine, with a code coverage report produced.
You have to assure the package name is equal in all configurations. Xcode modifies it in case you are using unsupported characters. For instance Xcode replaces "-" with "_".
In all configurations, go to:
Project -> Build Settings -> Product Module
and set the exact same name without spaces.

How to get the Xcode build directory?

How do I get the URL or url string to the build directory of a workspace or a project? I don't want to set it myself to know what it is instead I want to know the default set by Xcode.
How to get the directory programmatically?
If you need the build directory path for use within an Xcode build script (Build Phases > Run Script), then use the following variable:
$TARGET_BUILD_DIR
For an exhaustive list of all variables exposed by Xcode in build scripts, follow this answer:
$ xcodebuild -project myProject.xcodeproj -target "myTarget" -showBuildSettings
Building up on Daniel Jones answer above, to get the BUILD_DIR of a workspace, you should run:
xcodebuild -workspace ios/myApp.xcworkspace -scheme myApp
-showBuildSettings | grep BUILD_DIR
example of response:
BUILD_DIR = /Users/Olivier/Library/Developer/Xcode/DerivedData/myApp-ceetrcnutlegngflgvvfjaaaycrc/Build/Products
Select you project in the Xcode. On the right side select "Build Settings". Select desired target and under "Build Locations" you will find paths for debug, release and distribution configurations. These paths are relative to your "Deriver Data" directory. To open that directory in Finder, do the following.
Xcode menu: Window->Organizer. When you get "Organizer" window, on the left side select you project and on the right side you will get "Derive Data" path. Clicking on the arrow at the end of the "Derived Data" path you will open that directory in the Finder.
If you want a build directory path to use in some Pre-actions or Post-actions scripts, then variable name for it can be found in Quick Help Inspector, once you clicked on desired build directory in "Build Locations".

Why when generating .app file, xcode needs to be open?

I'm writing a script to build and generate an .app file from an specific target and scheme (to work with simulator). I was using something like:
DEVELOPER_DIR=$xcode_app_path/Contents/Developer xcodebuild -sdk iphonesimulator -scheme "${SCHEME}" -target "${TARGET}" ONLY_ACTIVE_ARCH=NO CONFIGURATION_BUILD_DIR="${build_folder}" clean build
The problem is, that I need to open XCode for the code above to work, otherwise will show me a message telling me that:
xcodebuild: error: The project 'Project-name' does not contain a scheme named "${SCHEME}"
I still yet, don't understand what is XCode doing in background. But if I open the IDE and run the script, works. If I open and later close it, and run the script works. It's not working if the project hasn't been opened first with XCode ¬¬
Any suggestion would be appreaciated
If someone is facing the same experience, this is what I found out. And works.
Well, apparently when you create a new scheme through command line, by default is not "shared". So when you start to link to the folder
xcshareddata --> xcschemes
(trying to build with command line, for example) there's nothing to link with. Xcode do this automaticaly under the hood when you open your project...
The guys from CocoaPods were facing the same issue, so they created a Ruby gem that shares the scheme and place the file in his xcscheme folder:
This is the repo: https://github.com/CocoaPods/Xcodeproj
Also, thanks to this post and this post I found out how to use xcodeproj gem, and change the shared option with a script that I put downhere:
require 'xcodeproj'
xcproj = Xcodeproj::Project.open("MyProject.xcodeproj")
xcproj.recreate_user_schemes
xcproj.save

Target Properties changes by xcodebuild command

How can i manipulate my iOS Target Properties by xcodebuild command tool ?
In example, i have one project with one target and with Facebook SDK Key in Target Properties in Info tab
FacebookAppID: 01234567891234
And with console command xcodebuild i'm compiling two Apps with Developer and Production provisions with two console commands:
For Developer:
xcodebuild -project Projectname.xcodeproj clean install OBJROOT=ObjRoot ... CODE_SIGN_IDENTITY={iPhoneDeveloper} PROVISIONING_PROFILE="Dev.mobileprovision"
For Distribution:
xcodebuild -project Projectname.xcodeproj clean install OBJROOT=ObjRoot ... CODE_SIGN_IDENTITY={iPhoneProduction} PROVISIONING_PROFILE="Prod.mobileprovision"
And i need use in Developer one FacebookAppID, and in Production a other FacebookAppID, and how i can change my command lines for realize this?
Thanks
Arguments to xcodebuild are best used for values that change every time they're invoked, like a destination directory that includes a build number.
For data as foundational as a Facebook app ID, I'd recommend using your build configurations, e.g. "Debug" and "Release". Create a user-defined build setting (in Xcode 5.0.2, Editor -> Add Build Setting -> Add User-Defined Setting) named something like "FACEBOOK_ID", and in your Info.plist, set your desired key's value to ${FACEBOOK_ID}. In your target's build settings, define FACEBOOK_ID differently for your Debug and Release configurations. Your code then now has to pull the current value out of Info.plist at runtime.
If you really want to override build settings as arguments to xcodebuild, you can do so, just by adding "FACEBOOK_ID=12341234" to the end of the command, but this only works if you've done the work I just described to make FACEBOOK_ID into a configuration-specific build setting. I can't think of any sound reasons to keep this kind of app data outside of a build configuration.
If build configurations are new to you, I'd suggest starting with WWDC 2012 session 408, "Working with Schemes and Projects in Xcode".

xcodebuild workspace and scheme

I am a little confused as to what happens with the xcodebuild command line tool when you specify a workspace and scheme.
I understand how a configured scheme works in the XCode IDE GUI. The build action lists the targets to build and for each action (Analyze, Test, Run, Profile, Archive), you select which one you want the build action to execute for.
So if I have each action (Analyze, Test, Run, Profile, Archive) selected in the build action for building, what happens when I execute the below command.
xcodebuild clean install -workspace MyWorkspace.xcworkspace -scheme MyScheme
-configuration AdHoc SYMROOT=PATH DSTROOT=PATH...
It searches for MyScheme.xcscheme in the main xcodeproj which has all this configuration specified when editing the scheme in XCode.
What does xcodebuild read in from this file? Does it just build the configured target with the AdHoc configuration and disregard everything else?
You're almost there, but your syntax is a bit off.
According to the man page:
xcodebuild -workspace workspacename -scheme schemename [-configuration configurationname]
[-sdk [sdkfullpath | sdkname]] [buildaction ...] [setting=value ...]
[-userdefault=value ...]
Where buildaction is one of the following:
buildaction ...
Specify a build action (or actions) to perform on the target. Available build actions are:
build Build the target in the build root (SYMROOT). This is the default build action.
archive Archive a scheme from the build root (SYMROOT). This requires specifying a scheme.
test Test a scheme from the build root (SYMROOT). This requires specifying a scheme.
installsrc Copy the source of the project to the source root (SRCROOT).
install Build the target and install it into the target's installation directory in the dis-
tribution root (DSTROOT).
clean Remove build products and intermediate files from the build root (SYMROOT).
In the Xcode IDE, you choose the buildaction to run through the Product menu, or by clicking and holding the round button on the top left of the IDE (Run = Play triangle, Test = wrench icon, etc).
Also, be careful to note where xcodebuild is looking for your build scheme - it can either be in your .xcproj OR your .xcworkspace file, depending on which one you created.
(If you didn't manually create a workspace, you will have a .xcproj file).
You can also ascertain which schemes you have via your 'Manage Schemes' setting in Xcode.

Resources