Skip to main content

Overview

Project.swift is the manifest file that defines an Xcode project in Tuist. It specifies the project’s name, targets, schemes, settings, and dependencies using a declarative Swift DSL.

Location

Each Project.swift file should be placed in the directory where you want to generate the Xcode project:
/MyApp/Project.swift       # Generates MyApp.xcodeproj
/MyFramework/Project.swift # Generates MyFramework.xcodeproj

Basic structure

import ProjectDescription

let project = Project(
    name: "MyApp",
    targets: [
        .target(
            name: "MyApp",
            destinations: .iOS,
            product: .app,
            bundleId: "dev.tuist.MyApp",
            infoPlist: .default,
            sources: ["Sources/**"],
            dependencies: []
        )
    ]
)

Properties

name

name
String
required
The name of the project. Also used as the file name of the generated Xcode project (e.g., MyApp.xcodeproj).

organizationName

organizationName
String?
default:"nil"
The name of the organization used by Xcode as copyright information in file headers.

classPrefix

classPrefix
String?
default:"nil"
The prefix for class files Xcode generates when you create a project or class file.

options

options
Options
default:".options()"
Project-level options such as automatic schemes generation, text settings, and development region.

packages

packages
[Package]
default:"[]"
Swift Packages used by the project. Specify remote or local packages as dependencies.

targets

targets
[Target]
required
The targets of the project. Each target represents an app, framework, library, or test bundle.

schemes

schemes
[Scheme]
default:"[]"
Custom schemes for the project. Default schemes for each target are generated automatically unless disabled in options.

settings

settings
Settings?
default:"nil"
The build settings and configuration for the project. When nil, uses Xcode defaults.

fileHeaderTemplate

fileHeaderTemplate
FileHeaderTemplate?
default:"nil"
The custom file header template for Xcode built-in file templates.

additionalFiles

additionalFiles
[FileElement]
default:"[]"
Additional files to include in the project (e.g., documentation, configuration files) that aren’t part of any target.

resourceSynthesizers

resourceSynthesizers
[ResourceSynthesizer]
default:".default"
Resource synthesizers that generate type-safe accessors for resources like images, strings, and fonts.

Defining targets

Targets are the building blocks of your project. Each target produces a single product:
.target(
    name: "App",
    destinations: .iOS,
    product: .app,
    bundleId: "dev.tuist.App",
    infoPlist: "Config/App-Info.plist",
    sources: ["Sources/**"],
    resources: [
        "Resources/**",
        .folderReference(path: "Stubs")
    ],
    dependencies: [
        .target(name: "Framework"),
        .project(target: "SharedKit", path: "../SharedKit"),
        .external(name: "Alamofire")
    ]
)

Target properties

  • name: The target’s name
  • destinations: Platforms the target supports (.iOS, .macOS, .tvOS, .visionOS, .watchOS)
  • product: The product type (.app, .framework, .staticLibrary, etc.)
  • bundleId: The bundle identifier
  • infoPlist: Info.plist configuration
  • sources: Source file patterns
  • resources: Resource file patterns
  • dependencies: Dependencies on other targets, projects, or packages

Schemes

Schemes define how to build, run, test, and archive your targets:
Scheme(
    name: "App-Debug",
    shared: true,
    buildAction: .buildAction(targets: ["App"]),
    testAction: .targets(["AppTests"]),
    runAction: .runAction(
        executable: "App",
        arguments: .arguments(
            launchArguments: [
                .launchArgument(name: "-UITestingEnabled", isEnabled: true)
            ]
        )
    )
)

Dependencies

Target dependencies

.target(name: "Framework")

Project dependencies

.project(target: "SharedKit", path: "../SharedKit")

External dependencies (Swift Packages)

.external(name: "Alamofire")

SDK dependencies

.sdk(name: "CloudKit", type: .framework, status: .required)

Settings

Define build settings at the project level:
let project = Project(
    name: "MyApp",
    settings: .settings(
        base: [
            "DEVELOPMENT_TEAM": "ABC123",
            "CODE_SIGN_STYLE": "Manual"
        ],
        configurations: [
            .debug(name: "Debug"),
            .release(name: "Release")
        ]
    ),
    targets: [...]
)

Swift Packages

Include Swift Packages in your project:
let project = Project(
    name: "MyApp",
    packages: [
        .remote(
            url: "https://github.com/Alamofire/Alamofire",
            requirement: .upToNextMajor(from: "5.0.0")
        ),
        .local(path: "../LocalPackage")
    ],
    targets: [
        .target(
            name: "App",
            destinations: .iOS,
            product: .app,
            bundleId: "dev.tuist.App",
            sources: ["Sources/**"],
            dependencies: [
                .external(name: "Alamofire")
            ]
        )
    ]
)

Examples

Simple iOS app

import ProjectDescription

let project = Project(
    name: "MyApp",
    organizationName: "MyCompany",
    targets: [
        .target(
            name: "MyApp",
            destinations: .iOS,
            product: .app,
            bundleId: "com.mycompany.myapp",
            infoPlist: .default,
            sources: ["Sources/**"],
            resources: ["Resources/**"],
            dependencies: []
        )
    ]
)

App with framework and tests

import ProjectDescription

let project = Project(
    name: "MyApp",
    targets: [
        .target(
            name: "App",
            destinations: .iOS,
            product: .app,
            bundleId: "dev.tuist.App",
            infoPlist: .default,
            sources: ["App/Sources/**"],
            resources: ["App/Resources/**"],
            dependencies: [
                .target(name: "Framework")
            ]
        ),
        .target(
            name: "Framework",
            destinations: .iOS,
            product: .framework,
            bundleId: "dev.tuist.Framework",
            infoPlist: .default,
            sources: ["Framework/Sources/**"],
            dependencies: []
        ),
        .target(
            name: "AppTests",
            destinations: .iOS,
            product: .unitTests,
            bundleId: "dev.tuist.AppTests",
            infoPlist: .default,
            sources: ["App/Tests/**"],
            dependencies: [
                .target(name: "App")
            ]
        )
    ]
)

Multi-platform target

import ProjectDescription

let project = Project(
    name: "MultiPlatformApp",
    targets: [
        .target(
            name: "App",
            destinations: [.iPhone, .iPad, .macOS],
            product: .app,
            bundleId: "dev.tuist.App",
            infoPlist: .default,
            sources: ["Sources/**"],
            resources: ["Resources/**"],
            dependencies: []
        )
    ]
)

With custom schemes

import ProjectDescription

let project = Project(
    name: "MyApp",
    targets: [
        .target(
            name: "App",
            destinations: .iOS,
            product: .app,
            bundleId: "dev.tuist.App",
            infoPlist: .default,
            sources: ["Sources/**"],
            dependencies: []
        ),
        .target(
            name: "AppTests",
            destinations: .iOS,
            product: .unitTests,
            bundleId: "dev.tuist.AppTests",
            infoPlist: .default,
            sources: ["Tests/**"],
            dependencies: [.target(name: "App")]
        )
    ],
    schemes: [
        Scheme(
            name: "App-Debug",
            shared: true,
            buildAction: .buildAction(targets: ["App"]),
            testAction: .targets(["AppTests"]),
            runAction: .runAction(executable: "App")
        ),
        Scheme(
            name: "App-Release",
            shared: true,
            buildAction: .buildAction(targets: ["App"]),
            runAction: .runAction(
                executable: "App",
                configuration: "Release"
            )
        )
    ]
)

Best practices

Modular structure

Break large projects into multiple smaller projects for better build times and organization.

Glob patterns

Use glob patterns for sources and resources to automatically include new files.

Shared settings

Define common settings in a shared location and reference them across targets.

Test targets

Create separate test targets for unit tests and UI tests.