What is Xcode test build path? - xcode

In Xcode, pressing ⌘B (build target) can build the project, it will generate the build in the path ~/Library/Developer/Xcode/DerivedData/{AppName}-{hash}.
How could I know the whole path of the build (with the hash value) by a script? Can I find that path in my .xcodeproj?
When I use ⇧⌘U (build test target only), where can I find the test target build?

The build paths can be controlled using BUILT_PRODUCTS_DIR , PROJECT_TEMP_DIR , CONFIGURATION_BUILD_DIR and CONFIGURATION_TEMP_DIR etc . https://help.apple.com/xcode/mac/11.4/#/itcaec37c2a6
There's no need to extract them from some non-public file format specification.
If you must do it, init a temporary git repo with a xcodeproj file in it. Commit it. Make a change in one of the variables and then run git diff.

How could I know the whole path of the build (with the hash value) by a script?
Change to the same folder where your project or workspace is
Run xcodebuild -showBuildSettings
May need to add the proper scheme or target. See man xcodebuild
See sample below to find by script
When I ... build for test target only, where can I find the test target build?
It will be in the same folder with a name similar to <Test_Target_Name>-Runner.app. This is useful as you can use for Cloud device testing services.
# This example works with Xcode project with a single scheme
# Echo to stdout
xcodebuild -showBuildSettings
xcodebuild -showBuildSettings | grep CONFIGURATION_BUILD_DIR
# save to a variable for use in your script
# A little brutal, so I'm open to other ways to do this.
CONFIGURATION_BUILD_DIR=$(xcodebuild -showBuildSettings 2> /dev/null | grep CONFIGURATION_BUILD_DIR | sed 's/[ ]*CONFIGURATION_BUILD_DIR = //')
echo $CONFIGURATION_BUILD_DIR
If you are using Xcode Server Bots
cd ${XCS_PRIMARY_REPO_DIR}
xcodebuild -showBuildSettings
Sample output:
/Users/roblabs/Library/Developer/Xcode/DerivedData/openmaptiles-ios-demo-eectbiabcmhajpdbcoqnaipiaqpd/Build/Products/Release-iphoneos
As noted in https://stackoverflow.com/a/57512068,
The default value is $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
For further documentation on the build setting properties, see Build Setting Reference at developer.apple.com. The link that #puio listed is also useful.

Related

Xcode scheme pre-action script not running

Hit build and nothing gets printed in build log. What gives?
Xcode Version 8.2.1 (8C1002)
Pre-action takes place before the build, so output doesn't go to the build log, it goes to stdErr. You can copy the output to a file:
exec > ${PROJECT_DIR}/prebuild.log 2>&1
echo "hello world"
To get the environment variables to work, you also need to set "Provide build settings from" to the appropriate target.
That should write hello world to a file named "prebuild.log" in your project folder.
for XCode versions < 13.2
If you want these activities to end up in the build log, consider adding a run script to your target's build phase instead.
for XCode versions >= 13.2
The XCode build log now includes a Run pre-actions section. If you don't redirect to a file, those messages will end up as the last item in a 'Run custom shell script' in this section - access via the XCode Report Navigator.
To add to the answer, https://stackoverflow.com/a/42497746/1058199, it's important to not clutter up the project.pbxproj (where build scripts go) or your scheme file (where these scripts go) as much as possible.
With this in mind, I create a Build-Scripts folder in the project root where I put the app build scripts and pre-action scripts. This folder is dragged into the root of the project as a folder so that any script I add to it is automatically added to project.
Assuming that your pre-action script is called That_pre-action_script.sh, this is what I put in Pre-actions script based on the approved answer.
say "Pre build scripts running."
exec > "${PROJECT_DIR}/prebuild.log" 2>&1
echo "Starting build scheme Pre-actions"
"${PROJECT_DIR}/Build-Phases/That_pre-action_script.sh"
As a test, make sure to echo some message from your script so you can see it in the prebuild.log file.
Hope this helps.
And don't forget to chmod u+x your script in the terminal so that it will run.
The important part is if you can't make sure if your build script is running or not. This is where the say command us useful so that you know it's actually being issued before a build.
It's a good idea to put quotes around the path to the script in case there are any space characters (or otherwise) in the path to your project.

Variable for path to XCode's SharedPrecompiledHeaders folder

During our iOS client build we run a clean to prevent/reduce failures. But last week all our build servers failed with this error
fatal error: malformed or corrupted AST file: 'could not find file 'worspace/file_name.h' referenced by AST file'
It seemed that file_name.h was no longer required and a developer removed the svn external which brought it in. But the AST files still held a reference to it - despite the clean.
After investigating I found it was the files in the following folder
var/folders/f3/bznwl6md2bx82f1fv_kkdzl00000gn/C/com.apple.DeveloperTools/5.0.2-5A3005/Xcode/SharedPrecompiledHeaders
Deleting SharedPrecompiledHeaders fixed the issue. At the time I manually did this.
But I'd like a way to automate it. Is there an environmental variable/alternative that can be used to find this directory? I noticed it varies between machines.
The environment variable you are looking for is SHARED_PRECOMPS_DIR
The final solution was to place the shared precomps dir within the checkout. This allowed the build servers to completely clean the workspace between builds.
Achieved this by passing in the SHARED_PRECOMPS_DIR to xcodebuild.
e.g.
xcodebuild -project ProjectName -target "Target" -configuration Configuration -sdk SDKName SHARED_PRECOMPS_DIR=/absolute/path/to/checkout
By passing this value in at the command line the SHARED_PRECOMPS_DIR was set for all projects. i.e. Including Dependent Projects.
Lane's answer is correct. If you need to retrieve this value from the command line parse the output of
xcodebuild -project myProj.xcodeproj -target "myTarg" -showBuildSettings
For further details see How do I print a list of "Build Settings" in Xcode project?

Making a CI server build all XCode targets as .ipa's

I'm looking into TeamCity and Jenkins, for a CI server.
My goal is this: every time someone commits a change to our repo, the CI server builds all targets in the project as .ipa's - ready for downloading/installing on a device.
I got Teamcity and Jenkins up and running, using a Mac mini as a build slave. That part of it is working fine.
Using Jenkins XCode plugin, I succeeded in building all targets as .ipa's.
I havent had such luck with Teamcity. The XCode plugin doesnt allow building all targets. Rather, you have to specify which targets you want to build, in each build configuration.
I approached the makers of Teamcity, and they gave me some convoluted method involving meta runners and a lot of duplication, in order to accomplish my goal.
Instead of relying on plugins, I'd rather build the .ipa's using shell scripting. However, as I'm not a script ninja, I can't figure out how to go about this.
I can figure out how to build one target via scripting, but it illudes me how make it build them all. Everytime I create a new target in the project, I don't want to have to add it at the CI server. The server should be able to automatically build all targets in the project.
...Maybe someone has a better solution? Any help is much appreciated.
What you should do (codes are bash script snippets, ready to run on OS X, you don't need to install anything except Xcode's CLI/Command Line Tools):
if you want to do this for every Xcode project file you have in your repository you should first search for these (if you have a specific Xcode project you can skip this)
for path in $(find . -type d -name '*.xcodeproj' -or -name '*.xcworkspace')
do
after this you can query all the shared (!) schemes through Xcode's command line tool
if [[ "$project" == *".xcodeproj" ]]; then
xcodebuild_output=($(xcodebuild -list -project "$project"))
else
xcodebuild_output=($(xcodebuild -list -workspace "$project"))
fi
now you have all the schemes so you can simply xcodebuild them one-by-one
Here's a bash script we developed to search for every Xcode project and every scheme configuration in a repository: https://github.com/concretebuilder/steps-cocapods-and-repository-validator/blob/master/find_schemes.sh
Note: you need to mark you schemes as shared to get xcodebuild (the command line interface of Xcode) list them.

xcodebuild: find where the output app file is

Is there anyway to specify where to put the output file (ie .app) for xcodebuild? By default it is in:
/Users/myusername/Library/Developer/Xcode/DerivedData/Project-crkyjjbuqqnqqvfxehsjsarzlbbr/Build/Products/Release-iphoneos/Project.app
As I need to find the output Project.app file, if there is no way to specify the path, can I use a script to look for that "/Users/myusername/Library/Developer/Xcode/DerivedData/" folder and inside it find the one with latest modified date and prefix "Project-"? What does the script look like?
Thanks
Override the CONFIGURATION_BUILD_DIR environment variable in an xcodebuild argument. For instance, this command would put its build products under "/tmp/sportsball/":
xcodebuild -workspace Sportsball.xcworkspace -scheme "Sportsball Debug" -configuration Debug clean build CONFIGURATION_BUILD_DIR=/tmp/sportsball/

xcodebuild commands give different results when run from the command line than when run from within Jenkins

I'm setting up a CI system using Jenkins and was finding that the build was failing because xcodebuild reports there are no schemes when I was executing the line
-xcodebuild -workspace XXX -scheme NNN.
I couldn't figure out why this could be happening, so to eliminate something screwy being up with my workspace I created a new project template using XCode and found that I am getting a difference in behavior for any xcodebuild command and for any workspace/project.
The template project was called scrap and if from the terminal command line I run this command for example:
xcodebuild -list
It outputs
Information about project "scrap":
Targets:
scrap
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
Schemes:
scrap
But if I run xcodebuild -list from within Jenkins then the output instead is:
Building in workspace /Users/Shared/Jenkins/Home/workspace/scrap
[scrap] $ /bin/sh -xe /var/folders/ph/s6dvlfq9769741g_yzmjlmz000007c/T/hudson3765407964219991487.sh
+ xcodebuild -list
Information about project "scrap":
Targets:
scrap
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
This project contains no schemes.
This is the most simple of jenkins jobs - all I do is create a new job, set it to a free-style software project, then add a build step of Execut shell and add the xcodebuild -list command, that's it.
Why is xcodebuild saying there are no schemes when there are? And why is it behaving differently when run from within Jenkins?
Figured out that all you need to do is to set the scheme to be shared.
Scheme > Manage Schemes
Make sure "Shared" is checked.
This will then generate out a new folder/file .../xcshareddata/xcschemes/???.xcscheme
Check this file into your source control and scheme should now appear on your jenkins box.
you must ignore your .xcodeproj/xcuserdata/.xcuserdatad in your .gitignore file.
xcodebuild -list get schemes from .xcodeproj/xcuserdata/.xcuserdatad/xcschemes.
jenkins server has no this file so get no schemes,you can open *.xcodeproj in your jenkins server,it will create the file and then do xcodebuild -list can get the current schemes.I have the same problem and solved by the method above.

Resources