---
title: Migrate an Xcode project
titleTemplate: :title · Migrate· Start · Guides · Tuist
description: Xcode プロジェクトを Tuist プロジェクトに移行する方法を学びます
---

# Xcode プロジェクトの移行 {#migrate-an-xcode-project}

Xcode プロジェクトの移行 {#migrate-an-xcode-project} このプロセスがどれほど退屈かは、プロジェクトの複雑さによって異なります。

As you probably know, Xcode projects can become messy and complex over time: groups that don't match the directory structure, files that are shared across targets, or file references that point to nonexisting files (to mention some). All that accumulated complexity makes it hard for us to provide a command that reliably migrates project.

Moreover, manual migration is an excellent exercise to clean up and simplify your projects. Not only the developers in your project will be thankful for that, but Xcode, who will be faster processing and indexing them. Once you have fully adopted Tuist, it will make sure that projects are consistently defined and that they remain simple.

In the aim of easing that work, we are giving you some guidelines based on the feedback that we have received from the users.

## Create project scaffold {#create-project-scaffold}

First of all, create a scaffold for your project with the following Tuist files:

::: code-group

```js [Tuist.swift]
import ProjectDescription

let tuist = Tuist()
```

```js [Project.swift]
import ProjectDescription

let project = Project(
    name: "MyApp-Tuist",
    targets: [
        /** Targets will go here **/
    ]
)
```

```js [Tuist/Package.swift]
// swift-tools-version: 5.9
import PackageDescription

#if TUIST
    import ProjectDescription

    let packageSettings = PackageSettings(
        // Customize the product types for specific package product
        // Default is .staticFramework
        // productTypes: ["Alamofire": .framework,]
        productTypes: [:]
    )
#endif

let package = Package(
    name: "MyApp",
    dependencies: [
        // Add your own dependencies here:
        // .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
        // You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
    ]
)
```

:::

`Project.swift` is the manifest file where you'll define your project, and `Package.swift` is the manifest file where you'll define your dependencies. The `Tuist.swift` file is where you can define project-scoped Tuist settings for your project.

> [!TIP] PROJECT NAME WITH -TUIST SUFFIX
> To prevent conflicts with the existing Xcode project, we recommend adding the `-Tuist` suffix to the project name. You can drop it once you've fully migrated your project to Tuist.

## Build and test the Tuist project in CI {#build-and-test-the-tuist-project-in-ci}

To ensure the migration of each change is valid, we recommend extending your continuous integration to build and test the project generated by Tuist from your manifest file:

```bash
tuist install
tuist generate
tuist build -- ...{xcodebuild flags} # or tuist test
```

## Extract the project build settings into `.xcconfig` files {#extract-the-project-build-settings-into-xcconfig-files}

Extract the build settings from the project into an `.xcconfig` file to make the project leaner and easier to migrate. You can use the following command to extract the build settings from the project into an `.xcconfig` file:

```bash
mkdir -p xcconfigs/
tuist migration settings-to-xcconfig -p MyApp.xcodeproj -x xcconfigs/MyApp-Project.xcconfig
```

Then update your `Project.swift` file to point to the `.xcconfig` file you've just created:

```swift
import ProjectDescription

let project = Project(
    name: "MyApp",
    settings: .settings(configurations: [
        .debug(name: "Debug", xcconfig: "./xcconfigs/MyApp-Project.xcconfig"), // [!code ++]
        .release(name: "Release", xcconfig: "./xcconfigs/MyApp-Project.xcconfig"), // [!code ++]
    ]),
    targets: [
        /** Targets will go here **/
    ]
)
```

Then extend your continuous integration pipeline to run the following command to ensure that changes to build settings are made directly to the `.xcconfig` files:

```bash
tuist migration check-empty-settings -p Project.xcodeproj
```

## Extract package dependencies {#extract-package-dependencies}

Extract all your project's dependencies into the `Tuist/Package.swift` file:

```swift
// swift-tools-version: 5.9
import PackageDescription

#if TUIST
    import ProjectDescription

    let packageSettings = PackageSettings(
        // Customize the product types for specific package product
        // Default is .staticFramework
        // productTypes: ["Alamofire": .framework,]
        productTypes: [:]
    )
#endif

let package = Package(
    name: "MyApp",
    dependencies: [
        // Add your own dependencies here:
        // .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
        // You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
        .package(url: "https://github.com/onevcat/Kingfisher", .upToNextMajor(from: "7.12.0")) // [!code ++]
    ]
)
```

> [!TIP] PRODUCT TYPES
> You can override the product type for a specific package by adding it to the `productTypes` dictionary in the `PackageSettings` struct. By default, Tuist assumes that all packages are static frameworks.

## Determine the migration order {#determine-the-migration-order}

We recommend migrating the targets from the one that is the most dependent upon to the least. You can use the following command to list the targets of a project, sorted by the number of dependencies:

```bash
tuist migration list-targets -p Project.xcodeproj
```

Start migrating the targets from the top of the list, as they are the ones that are the most depended upon.

## Migrate targets {#migrate-targets}

Migrate the targets one by one. We recommend doing a pull request for each target to ensure that the changes are reviewed and tested before merging them.

### Extract the target build settings into `.xcconfig` files {#extract-the-target-build-settings-into-xcconfig-files}

Like you did with the project build settings, extract the target build settings into an `.xcconfig` file to make the target leaner and easier to migrate. You can use the following command to extract the build settings from the target into an `.xcconfig` file:

```bash
tuist migration settings-to-xcconfig -p MyApp.xcodeproj -t TargetX -x xcconfigs/TargetX.xcconfig
```

### Define the target in the `Project.swift` file {#define-the-target-in-the-projectswift-file}

Define the target in `Project.targets`:

```swift
import ProjectDescription

let project = Project(
    name: "MyApp",
    settings: .settings(configurations: [
        .debug(name: "Debug", xcconfig: "./xcconfigs/Project.xcconfig"),
        .release(name: "Release", xcconfig: "./xcconfigs/Project.xcconfig"),
    ]),
    targets: [
        .target( // [!code ++]
            name: "TargetX", // [!code ++]
            destinations: .iOS, // [!code ++]
            product: .framework, // [!code ++] // or .staticFramework, .staticLibrary...
            bundleId: "io.tuist.targetX", // [!code ++]
            sources: ["Sources/TargetX/**"], // [!code ++]
            dependencies: [ // [!code ++]
                /** Dependencies go here **/ // [!code ++]
                /** .external(name: "Kingfisher") **/ // [!code ++]
                /** .target(name: "OtherProjectTarget") **/ // [!code ++]
            ], // [!code ++]
            settings: .settings(configurations: [ // [!code ++]
                .debug(name: "Debug", xcconfig: "./xcconfigs/TargetX.xcconfig"), // [!code ++]
                .debug(name: "Release", xcconfig: "./xcconfigs/TargetX.xcconfig"), // [!code ++]
            ]) // [!code ++]
        ), // [!code ++]
    ]
)
```

> [!NOTE] TEST TARGETS
> If the target has an associated test target, you should define it in the `Project.swift` file as well repeating the same steps.

### Validate the target migration {#validate-the-target-migration}

Run `tuist build` and `tuist test` to ensure the project builds and tests pass. Additionally, you can use [xcdiff](https://github.com/bloomberg/xcdiff) to compare the generated Xcode project with the existing one to ensure that the changes are correct.

### Repeat {#repeat}

Repeat until all the targets are fully migrated. Once you are done, we recommend updating your CI and CD pipelines to build and test the project using `tuist build` and `tuist test` commands to benefit from the speed and reliability that Tuist provides.

## Troubleshooting {#troubleshooting}

### Compilation errors due to missing files. {#compilation-errors-due-to-missing-files}

If the files associated to your Xcode project targets were not all contained in a file-system directory representing the target, you might end up with a project that doesn't compile. Make sure the list of files after generating the project with Tuist matches the list of files in the Xcode project, and take the opportunity to align the file structure with the target structure.
