Skip to content

Instantly share code, notes, and snippets.

@mtauraso
Last active November 15, 2023 15:44
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save mtauraso/95a49eeb8e5b4335dd2b to your computer and use it in GitHub Desktop.
Save mtauraso/95a49eeb8e5b4335dd2b to your computer and use it in GitHub Desktop.
Xcodebuild flags in CI

Xcodebuild flag reference for CI:

Required flags:

-project OR -workspace

What xcode project/workspace file we're using. If you specify a project on the command-line and that project has an associated workspace, the project is still aware of its existence within the workspace. As an example, worspace level schemes will be available to xcodebuild even if you specify a project on the command line.

-scheme

Specify the scheme to use for build. Schemes specify multiple build/test targets along with environment args and command line parameters. Schemes must be marked "shared" in the xcode UI in order to be available to xcodebuild. For any particular build/test action there is a default configuration when you use a scheme from the Xcode UI.

-configuration

This needs to be specified on the command line even if the scheme specifies a default configuration. Why? There's a xcode-project-level config "Use config for command line builds" that overrides the config listed in the scheme when you use xcodebuild.

-destination="magic string"

Tells xcodebuild what platform + architecture we're building on. OSX, Simulator, real device. You can specify individual devices or simulators specifically with "id=UUID" syntax. See below

Example Destinations:

  • "id=UUID" Specify a particular simulator or device by UUID
  • "generic/platform=iOS" Build for a device
  • "platform=iOS Simulator,name=iPhone 5" Select a simulator automatically that has the given name.

ACTION: build, test, archive

What these do is set up in "Edit Scheme" inside of Xcode.app. Archive is special in that it uses stricter header + library search paths. Sometimes the library search paths are sloppy because a sub-project has SKIP_INSTALL set to "false". When "SKIP_INSTALL" is false, libraries are copied during the build action. This copying doesn't happen on archive action resulting in a failure to find the library.

Useful flags:

-resultBundlePath

Outputs a machine-readable xcodebuild log to the given directory. This is output as a plist and an older (pre xcode6) binary format.

-derivedDataPath

Set the derived data path to a known location. Useful for making sure its cleared when you expect.

-PBXBuildsContinueAfterErrors

Turn off xcode's default of continuing after errors to make logs more readable, and make it easier to find the failure that broke the build.

-showBuildSettings

Use in place of an action to dump all the environment-like variables that xcode uses for a build. Useful for testing the effect of particular flag combinations on xcodebuild.

-exportArchive

Run xcodebuild on a previously created .xcarchive file, does not accept other flags or take a workspace/project as a main object. It allows you to export a packaged application for iOS. Calling the packaging process this way allows your CI system to be decoupled from changes to the packaging format. Swift and Watch apps have so-far broken folks using the PackageApplication method.

Helpers

xcrun simctl

Lists simulators, also allows you to create and delete them. Useful to get the UUID for passing to the destination flag, and for creating blank simulators.

xcode-select

Use as root to select the active version of Xcode. xcrun and xcodebuild both respect the system-wide default.

Environment vars in xcodebuild

Environment variables in xcodebuild's environment are not passed through to xcode run-script actions. A default set is assembled from the system configuration as if you had started bash in Terminal.app.

An easy way to get environment variables into a run-script action is to pass them on the command line as project settings.

Corrections

This is a work in progress, that contains my current understanding of xcodebuild flags. Comments are welcome, especially if you have a reproduce case or experiment on a particular version of xcode that can pin down the behavior.

@Peter-Schorn
Copy link

Peter-Schorn commented Apr 30, 2021

Could you be more specific about how to pass environment variables? I have a Swift Package that I'm trying to test via github actions. If I pass the variables as project settings, how do I access them from code in my tests?

@CyberMew
Copy link

CyberMew commented Oct 22, 2021

-PBXBuildsContinueAfterErrors seems like an invalid option in my testing.

Adding "SWIFT_FLAGS=-D TEST_INTERNAL" works as well. Or now we use SWIFT_ACTIVE_COMPILATION_CONDITIONS instead (see: https://fdp.io/blog/2018/03/18/active-compilation-conditions-for-xcode/). In your xcconfig you can do SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) TEST_FLAG or if via xcodebuild, we can add 'SWIFT_ACTIVE_COMPILATION_CONDITIONS=$(inherited) TEST_INTERNAL' to the end as well. Note you need the inherited or it will override all your custom flags in your xcconfig and project settings.

@Peter-Schorn
Copy link

@CyberMew but these are all boolean flags, right? Can I pass string values?

@CyberMew
Copy link

@Peter-Schorn can you share more on what you want to do? What do you mean by a string? How would you do it “normally” in Xcode?

@Peter-Schorn
Copy link

How would you do it “normally” in Xcode?

In the Xcode scheme editor, you can specify environment variables, which are key-value pairs of strings. See here.

What do you mean by a string?

My project uses the Spotify web API, and I need to pass the API keys as environment variables. These are the string values I'm referring to. For example, I'm looking for something like

xcodebuild ... -env CLIENT_ID=abc123

@CyberMew
Copy link

Ah ok so it’s just environment variables. I believe you can simply do CLIENT_ID=abc123 xcodebuild ..., and xcodebuild will have access to it accordingly, and your process info code should pick it up. Let me know how it goes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment