Skip to the content.

Project Spec

The project spec can be written in either YAML or JSON. All the examples below use YAML.

Some of the YAML examples below don’t show all the required properties. For example not all target examples will have a platform or type, even though they are required.

You can also use environment variables in your configuration file, by using ${SOME_VARIABLE} in a string.

Project

Include

One or more specs can be included in the project spec. This can be used to split your project spec into multiple files, for easier structuring or sharing between multiple specs. Included specs can also include other specs and so on.

Include can either be a list of includes or a single include. They will be merged in order and then the current spec will be merged on top.

An include can be provided via a string (the path) or an object of the form:

Include Object

By default specs are merged additively. That is for every value:

This merging behaviour can be overridden on a value basis. If you wish to replace a whole value (set a new dictionary or new array instead of merging them) then just affix :REPLACE to the key

include:
  - base.yml
name: CustomSpec
targets:
  MyTarget: # target lives in base.yml
    sources:REPLACE:
      - my_new_sources

Note that target names can also be changed by adding a name property to a target.

Options

options:
  deploymentTarget:
    watchOS: "2.0"
    tvOS: "10.0"
  postGenCommand: pod install

GroupOrdering

Describe an order of groups. Available parameters:

options:
  groupOrdering: 
    - order: [Sources, Resources, Tests, Support files, Configurations]
    - pattern: '^.*Screen$'
      order: [View, Presenter, Interactor, Entities, Assembly]

In this example, we set up the order of two groups. First one is the main group, i.e. the project, note that in this case, we shouldn’t set pattern option and the second group order is for groups whose names ends with Screen.

FileType

Default settings for file extensions. See Sources for more documentation on properties. If you overwrite an extension that XcodeGen already provides by default, you will need to provide all the settings.

Breakpoints

breakpoints:
  - type: ExceptionBreakpoint
    enabled: true
    ignoreCount: 0
    continueAfterRunningActions: false

Breakpoint Action

actions:
  - type: Sound
    sound: Blow

Configs

Each config maps to a build type of either debug or release which will then apply default Build Settings to the project. Any value other than debug or release (for example none), will mean no default Build Settings will be applied to the project.

configs:
  Debug: debug
  Beta: release
  AppStore: release

If no configs are specified, default Debug and Release configs will be created automatically.

Setting Groups

Setting groups are named groups of Build Settings that can be reused elsewhere. Each preset is a Settings schema, so can include other groups or define settings by configs.

settingGroups:
  preset_generic:
    CUSTOM_SETTING: value_custom
  preset_debug:
    BUILD_SETTING: value_debug
  preset_release:
    base:
      BUILD_SETTING: value_release
  preset_all:
    groups:
      - preset_generic
    configs:
      debug:
        groups:
          - preset_debug
      release:
        groups:
          - preset_release

targets:
  Application:
    settings:
      groups: 
        - preset_all

Settings

Settings correspond to Build Settings tab in Xcode. To display Setting Names instead of Setting Titles, select Editor -> Show Setting Names in Xcode.

Settings can either be a simple map of Build Settings [String:String], or can be more advanced with the following properties:

settings:
  GENERATE_INFOPLIST_FILE: NO
  CODE_SIGNING_ALLOWED: NO
  WRAPPER_EXTENSION: bundle

Don’t mix simple maps with groups, base and configs. If groups, base, configs are used then simple maps is silently ignored.

In this example, CURRENT_PROJECT_VERSION will be set, but MARKETING_VERSION will be ignored:

settings:
  MARKETING_VERSION: 100.0.0
  base:
    CURRENT_PROJECT_VERSION: 100.0
settings:
  base:
    PRODUCT_NAME: XcodeGenProduct
  configs:
    debug:
      CODE_SIGN_IDENTITY: iPhone Developer
      PRODUCT_BUNDLE_IDENTIFIER: com.tomtom.debug_app
    release:
      CODE_SIGN_IDENTITY: iPhone Distribution
      PRODUCT_BUNDLE_IDENTIFIER: com.tomtom.app
      PROVISIONING_PROFILE_SPECIFIER: "Xcodegen Release"
  groups:
    - my_settings

Settings are merged in the following order: groups, base, configs (simple maps are ignored).

Target

Product Type

This will provide default build settings for a certain product type. It can be any of the following:

Platform

This will provide default build settings for a certain platform. It can be any of the following:

Note that when we use supported destinations with Xcode 14+ we can avoid the definition of platform that fallbacks to the auto value.

Multi Platform targets

You can also specify an array of platforms. This will generate a target for each platform. If deploymentTarget is specified for a multi platform target, it can have different values per platform similar to how it’s defined in Options. See below for an example. If you reference the string ${platform} anywhere within the target spec, that will be replaced with the platform.

The generated targets by default will have a suffix of _${platform} applied, you can change this by specifying a platformSuffix or platformPrefix.

If no PRODUCT_NAME build setting is specified for a target, this will be set to the target name, so that this target can be imported under a single name.

targets:
  MyFramework:
    sources: MyFramework
    platform: [iOS, tvOS]
    deploymentTarget:
      iOS: 9.0
      tvOS: 10.0
    type: framework
    settings:
      base:
        INFOPLIST_FILE: MyApp/Info.plist
        PRODUCT_BUNDLE_IDENTIFIER: com.myapp
        MY_SETTING: platform ${platform}
      groups:
        - ${platform}

The above will generate 2 targets named MyFramework_iOS and MyFramework_tvOS, with all the relevant platform build settings. They will both have a PRODUCT_NAME of MyFramework

Supported Destinations

This will provide a mix of default build settings for the chosen platform destinations. It can be any of the following:

targets:
  MyFramework:
    type: framework
    supportedDestinations: [iOS, tvOS]
    deploymentTarget:
      iOS: 9.0
      tvOS: 10.0
    sources:
      - path: MySources
        inferDestinationFiltersByPath: true
      - path: OtherSources
        destinationFilters: [iOS]

Note that the definition of supported destinations can be applied to almost every type of bundle making everything more easy to manage (app targets, unit tests, UI tests etc). App targets currently do not support the watchOS destination. Create a separate target using platform for watchOS apps. See Apple’s Configuring a multiplatform app for details.

Sources

Specifies the source directories for a target. This can either be a single source or a list of sources. Applicable source files, resources, headers, and .lproj files will be parsed appropriately.

A source can be provided via a string (the path) or an object of the form:

Target Source

targets:
  MyTarget:
    sources: MyTargetSource
  MyOtherTarget:
    supportedDestinations: [iOS, tvOS]
    sources:
      - MyOtherTargetSource1
      - path: MyOtherTargetSource2
        inferDestinationFiltersByPath: true
        name: MyNewName
        excludes:
          - "ios/*.[mh]"
          - "configs/server[0-2].json"
          - "*-Private.h"
          - "**/*.md" # excludes all files with the .md extension
          - "ios/**/*Tests.[hm]" # excludes all files with an h or m extension within the ios directory.
        compilerFlags:
          - "-Werror"
          - "-Wextra"
      - path: MyOtherTargetSource3
        destinationFilters: [iOS]
        compilerFlags: "-Werror -Wextra"
      - path: ModuleMaps
        buildPhase:
          copyFiles:
            destination: productsDirectory
            subpath: include/$(PRODUCT_NAME)
      - path: Resources
        type: folder
      - path: Path/To/File.asset
        resourceTags: [tag1, tag2]

Dependency

A dependency can be one of a 6 types:

Linking options:

Implicit Framework options:

This only applies to framework dependencies. Implicit framework dependencies are useful in Xcode Workspaces which have multiple .xcodeproj that are not embedded within each other yet have a dependency on a framework built in an adjacent .xcodeproj. By having Find Implicit Dependencies checked within your scheme Build Options Xcode can link built frameworks in BUILT_PRODUCTS_DIR.

Carthage Dependency

Carthage frameworks are expected to be in CARTHAGE_BUILD_PATH/PLATFORM/FRAMEWORK.framework where:

To link an XCFramework produced by Carthage (in CARTHAGE_BUILD_PATH/FRAMEWORK.xcframework), use a normal framework: dependency. The helper logic provided by this dependency type is not necessary.

All the individual frameworks of a Carthage dependency can be automatically found via findFrameworks: true. This overrides the value of Options.findCarthageFrameworks. Otherwise each one will have to be listed individually. Xcodegen uses .version files generated by Carthage in order for this framework lookup to work, so the Carthage dependencies will need to have already been built at the time XcodeGen is run.

If any applications contain carthage dependencies within itself or any dependent targets, a carthage copy files script is automatically added to the application containing all the relevant frameworks. A FRAMEWORK_SEARCH_PATHS setting is also automatically added

Carthage officially supports static frameworks. In this case, frameworks are expected to be in CARTHAGE_BUILD_PATH/PLATFORM/Static/FRAMEWORK.framework. You can specify linkType to static to integrate static ones.

projectReferences:
  FooLib:
    path: path/to/FooLib.xcodeproj
targets:
  MyTarget:
    supportedDestinations: [iOS, tvOS]
    dependencies:
      - target: MyFramework
        destinationFilters: [iOS]
      - target: FooLib/FooTarget
      - framework: path/to/framework.framework
        destinationFilters: [tvOS]
      - carthage: Result
        findFrameworks: false
        linkType: static
        destinationFilters: [iOS]
      - sdk: Contacts.framework
      - sdk: libc++.tbd
      - sdk: libz.dylib
  MyFramework:
    type: framework

SDK Dependency

targets:
  MyTestTarget:
    dependencies:
      - target: MyFramework
      - framework: path/to/framework.framework
      - sdk: Contacts.framework
      - sdk: Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest
        root: DEVELOPER_DIR
  MyFramework:
    type: framework

Package dependency

packages:
  Yams:
    url: https://github.com/jpsim/Yams
    majorVersion: 2.0.0
  SwiftPM:
    url: https://github.com/apple/swift-package-manager
    branch: swift-5.0-branch
targets:
  App:
    dependencies:
      - package: Yams 
      - package: SwiftPM
        product: SPMUtility

Depending on multiple products from a package:

packages:
  FooFeature:
    path: Packages/FooFeature
targets:
  App:
    dependencies:
      - package: FooFeature
        products:
          - FooDomain
          - FooUI

Config Files

Specifies .xcconfig files for each configuration.

configFiles:
  Debug: debug.xcconfig
  Release: release.xcconfig
targets:
  App:
    configFiles:
      Debug: App/debug.xcconfig
      Release: App/release.xcconfig

Plist

Plists are created on disk on every generation of the project. They can be used as a way to define Info.plist or .entitlement files. Some Info.plist properties are generated automatically.

targets:
  App:
    info:
      path: App/Info.plist
      properties:
        UISupportedInterfaceOrientations: [UIInterfaceOrientationPortrait]
        UILaunchStoryboardName: LaunchScreen
    entitlements:
      path: App/App.entitlements
      properties:
        com.apple.security.application-groups: group.com.app

Build Tool Plug-ins

To add Build Tool Plug-ins, you need to add information about plugins to Target:

Each plugin includes information:

Сonnect the plugin to the desired target:

targets:
  App:
    buildToolPlugins:
      - plugin: MyPlugin
        package: MyPackage

Don’t forget to add a package containing the plugin we need:

packages:
  MyPackage:
    url: https://github.com/MyPackage
    from: 1.3.0

Build Script

Run script build phases can be added at 3 different points in the build:

Each script can contain:

Either a path or script must be defined, the rest are optional.

A multiline script can be written using the various YAML multiline methods, for example with | as below:

targets:
  MyTarget:
    preBuildScripts:
      - path: myscripts/my_script.sh
        name: My Script
        inputFiles:
          - $(SRCROOT)/file1
          - $(SRCROOT)/file2
        inputFileLists:
          - $(SRCROOT)/inputFiles.xcfilelist
        outputFiles:
          - $(DERIVED_FILE_DIR)/file1
          - $(DERIVED_FILE_DIR)/file2
        outputFileLists:
          - $(SRCROOT)/outputFiles.xcfilelist
        discoveredDependencyFile: $(DERIVED_FILE_DIR)/target.d
    postCompileScripts:
      - script: swiftlint
        name: Swiftlint
      - script: |
      		command do
      		othercommand
    postBuildScripts:
      - path: myscripts/my_final_script.sh
        name: My Final Script

Build Rule

targets:
  MyTarget:
    buildRules:
      - filePattern: "*.xcassets"
        script: generate_assets.py
      - fileType: sourcecode.swift
        script: pre_process_swift.py
      - filePattern: "*.txt"
        name: My Build Rule
        compilerSpec: com.apple.xcode.tools.swift.compiler
        outputFiles:
          - $(SRCROOT)/Generated.swift
        runOncePerArchitecture: false

Target Scheme

This is a convenience used to automatically generate schemes for a target based on different configs or included tests. If you want more control check out the top level Scheme.

For example, the spec below would create 3 schemes called:

Each scheme would use different build configuration for the different build types, specifically debug configs for run, test, and analyze, and release configs for profile and archive. The MyUnitTests target would also be linked.

configs:
  Test Debug: debug
  Staging Debug: debug
  Production Debug: debug
  Test Release: release
  Staging Release: release
  Production Release: release
targets:
  MyApp:
    scheme:
      testTargets:
        - MyUnitTests
      configVariants:
        - Test
        - Staging
        - Production
      gatherCoverageData: true
      coverageTargets:
        - MyTarget1
        - ExternalTarget/OtherTarget1
      commandLineArguments:
        "-MyEnabledArg": true
        "-MyDisabledArg": false
      environmentVariables:
        MY_ENV_VAR: VALUE
  MyUnitTests:
    sources: Tests

Legacy Target

By providing a legacy target, you are opting in to the “Legacy Target” mode. This is the “External Build Tool” from the Xcode GUI. This is useful for scripts that you want to run as dependencies of other targets, but you want to make sure that it only runs once even if it is specified as a dependency from multiple other targets.

Aggregate Target

This is used to override settings or run build scripts in specific targets

Target Template

This is a template that can be referenced from a normal target using the templates property. The properties of this template are the same as a Target. Any instances of ${target_name} within each template will be replaced by the final target name which references the template. Any attributes defined within a targets templateAttributes will be used to replace any attribute references in the template using the syntax ${attribute_name}.

targets:
  MyFramework:
    templates: 
      - Framework
    templateAttributes:
      frameworkName: AwesomeFramework
    sources:
      - SomeSources
targetTemplates:
  Framework:
    platform: iOS
    type: framework
    sources:
      - ${frameworkName}/${target_name}

Scheme

Schemes allows for more control than the convenience Target Scheme on Target

Build

targets:
  MyTarget: all
  FooLib/FooTarget: [test, run]
parallelizeBuild: true
buildImplicitDependencies: true

Common Build Action options

The different actions share some properties:

Execution Action

Scheme run scripts added via preActions or postActions. They run before or after a build action, respectively, and in the order defined. Each execution action can contain:

A multiline script can be written using the various YAML multiline methods, for example with |. See Build Script.

Run Action

Test Action

Test Target

A target can be one of a 2 types:

As syntax sugar, you can also specify Testable Target Reference without target.

Other Parameters

Testable Target Reference

A Testable Target Reference can be one of 3 types:

Archive Action

Simulate Location

targets:
  MyTarget:
    fileGroups:
      - location.gpx

Note that the path the gpx file will be prefixed according to the schemePathPrefix option in order to support both .xcodeproj and .xcworkspace setups. See Options.

Scheme Management

Environment Variable

schemes:
  Production:
    build:
      targets:
        MyTarget1: all
        MyTarget2: [run, archive]
    run:
      config: prod-debug
      commandLineArguments:
        "-MyEnabledArg": true
        "-MyDisabledArg": false
      environmentVariables:
        RUN_ENV_VAR: VALUE
    test:
      config: prod-debug
      commandLineArguments:
        "-MyEnabledArg": true
        "-MyDisabledArg": false
      gatherCoverageData: true
      coverageTargets:
        - MyTarget1
        - ExternalTarget/OtherTarget1
        - package: LocalPackage/TestTarget
      targets: 
        - Tester1 
        - name: Tester2
          parallelizable: true
          randomExecutionOrder: true
          skippedTests: [Test/testExample()]
        - package: APIClient/APIClientTests
          parallelizable: true
          randomExecutionOrder: true
      environmentVariables:
        - variable: TEST_ENV_VAR
          value: VALUE
          isEnabled: false
    profile:
      config: prod-release
    analyze:
      config: prod-debug
    archive:
      config: prod-release
      customArchiveName: MyTarget
      revealArchiveInOrganizer: false

Test Plan

For now test plans are not generated by XcodeGen and must be created in Xcode and checked in, and then referenced by path. If the test targets are added, removed or renamed, the test plans may need to be updated in Xcode.

schemes:
  TestTarget:
    test:
      testPlans:
        - path: app.xctestplan
          defaultPlan: true

Scheme Template

This is a template that can be referenced from a normal scheme using the templates property. The properties of this template are the same as a Scheme. This functions identically in practice to Target Template. Any instances of ${scheme_name} within each template will be replaced by the final scheme name which references the template. Any attributes defined within a scheme’s templateAttributes will be used to replace any attribute references in the template using the syntax ${attribute_name}.

schemes:
  MyModule:
    templates:
      - FeatureModuleScheme
    templateAttributes:
      testTargetName: MyModuleTests

schemeTemplates:
  FeatureModuleScheme:
    templates:
      - TestScheme
    build:
      targets:
       ${scheme_name}: build

  TestScheme:
    test:
      gatherCoverageData: true
      targets:
        - name: ${testTargetName}
          parallelizable: true
          randomExecutionOrder: true

The result will be a scheme that builds MyModule when you request a build, and will test against MyModuleTests when you request to run tests. This is particularly useful when you work in a very modular application and each module has a similar structure.

Swift Package

Swift packages are defined at a project level, and then linked to individual targets via a Dependency.

Remote Package

Local Package

packages:
  Yams:
    url: https://github.com/jpsim/Yams
    from: 2.0.0
  Ink:
    github: JohnSundell/Ink
    from: 0.5.0
  RxClient:
    path: ../RxClient
  AppFeature:
    path: ../Packages
    group: Domains/AppFeature

Project Reference

Project References are defined at a project level, and then you can use the project name to refer its target via a Scheme

projectReferences:
  YamsProject:
    path: ./Carthage/Checkouts/Yams/Yams.xcodeproj
schemes:
  TestTarget:
    build:
      targets:
        YamsProject/Yams: ["run"]