First touches of using Tuist for Xcode Project generation

Alexander Holley
The Startup
Published in
6 min readMay 23, 2020

Simple Xcode Project generation to collaborate with your team and a lot more.

Photo by Zan on Unsplash

This is my first post on Medium. My wish is to share my experiences, thoughts and ideas. In this article, I would like to introduce you to the Tool Tuist. I hope somebody might find it a useful resource and will therefore keep it short and informative.

The first part will give you insight and show you what the advantages of Tuist can be. I will explain my motivations for using it and provide you with a hands-on guide on how to set Tuist up for a small project.

Motivation

When working together on the development of an iOS App, conflicts of the project file can occur very quickly.

To avoid this we can have our project files generated automatically. This is where Tuist comes into play. With Tuist we can generate the project locally based on a certain configuration.

This means that the *.xcodeproj and *.xcworkspace can be added to the .gitignore file!

Tuist can be used for all project types which can be developed with Xcode.

What is Tuist and why should we use it?

We don’t want to spend time on things that can be automated and try to avoid conflicts in SCM.

Tuist was created in 2018 and used for example at Soundcloud. It has more than 2800 Commits and 40 contributors. In the documentation Tuist was explained with:

Tuist is a command line tool that helps you generate, maintain and interact with Xcode projects.

Related Links

  1. Website: https://tuist.io/
  2. Docs: https://tuist.io/docs/usage/getting-started/
  3. Github: https://github.com/tuist

Tuist is as already mentioned as a tool to generate Xcode projects automatically. It is configured with a Project.swift file and can be executed in the terminal. After that, only the configuration needs to be added to the SCM — the project data should be removed from the SCM.

Having a Swift file is Tuist is a major advantage. Opening the Project.swift file in Xcode facilitates all of the compiler’s features to simplify the editing process.

For example:

Here we can look directly at which configuration options we have and how to use them.

There’s a lot of cool stuff, but let’s talk a little bit more about the features of Tuist.

You can install Tuist with the following command:

bash <(curl -Ls https://install.tuist.io)

The most essential commands

  • Initialize a basic project:

tuist init --platform ios

  • Easily generate the Project with:

tuist generate

Tuist looks for all files in the project directory and creates the appropriate project and workspace file based on the configuration.

  • Edit configuration with Xcode:

tuist edit

An important question is which dependency systems could be used. And there is a lot of support here:
- Target dependency.
- framework dependency
- library dependency
- System libraries
- CocoaPods
- Carthage
- SPM (Swift Package Manager)
- XCFrameworks

The documentation is solid and a growing community is available.

Let’s go through an example configuration.

Example

Here’s a little test project I’ve been using to evaluate Tuist with.

On the base of this project, I will try to explain the first features and how to get started.

Installation

First, you need to install Tuist on your Mac. To do this, simply go to the terminal and enter the following.

bash <(curl -Ls https://install.tuist.io)

After this is finished we can now take care of the project.

Project default setup

I have created a new empty project using Xcode. Then I adjusted the structure of the project and deleted unimportant files.

I’ve added R.swift to my Podfile (https://github.com/mac-cain13/R.swift) as a dependency.

I want my project to be monitored with Swiftlint to ensure my code quality. Since I have Swiftlint installed on my Mac locally, I don’t need to do anything else but to use Swiftlint in my project.

However, we could do many things here with Tuist to control the environment of the development machines. I will show you this in another post. If someone wants to see something about this already now, take a look at https://tuist.io/docs/commands/up/ and read the official documentation.

To add both frameworks we need to add “Build Phases”. I put two scripts in the “Scripts” folder.

The content of the RSwiftRunScript.sh is:

"$PODS_ROOT/R.swift/rswift" generate "$SCRIPT_OUTPUT_FILE_0"

The content of the SwiftLintRunScript.sh is:

if which swiftlint > /dev/null; then
swiftlint
else
echo "SwiftLint not installed?"
fi

Create the file and leave it for now. I will explain in the next point how we use it.

I have also added a .gitignore file to prevent me from adding the project files.

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Xcode ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
### Xcode Patch ###
*.xcodeproj/*
!*.xcodeproj/project.pbxproj
!*.xcodeproj/xcshareddata/
!*.xcworkspace/contents.xcworkspacedata
/*.gcno
### Projects ###
*.xcodeproj
*.xcworkspace
### Tuist derived files ###
graph.dot
Derived/

First configuration

Create a Project.swift file in the root of the project.

In my test project, the file has the following content. The configuration is explained below the picture.

(https://github.com/tomminges/TuistSample/blob/master/Project.swift)

Lines 3–15:

  • Configures the “Build Phases” here we specify the path to the file and if needed input/output parameters/files.

Lines 18:

  • Here we set the Project-Name.

Lines 19:

  • Here we set the Organization Name.

Lines 20–25:

  • In these lines, we define our project Configurations which we need for our future schemas.
    I use four possible variants here.
  1. Debug — development
  2. Intern — intern test releases
  3. Extern — extern test releases
  4. Release — AppStore release

Lines 26–55

  • This is where we declared the projects we want to see in our workspace.
    Line 36 shows how to integrate simple CocoaPods-dependencies, which are automatically installed during the generation process.

Attention:

Something I haven’t said is: We need to specify the paths of our source files here. I divided them into Resources and Sources. This is for a better overview and Tuist needs this to add the content of the folders to the project.

This means that we don’t add files to the project manually, but Tuist searches for all files and adds them automatically!

Lines 58–82:

  • All schema definitions and the corresponding configurations.

Lines 85–87

  • Here you can specify files that do not exist at the beginning or are located in a different folder than the specified paths.

Generate it! Let the magic happens :)

Go to your Terminal and navigate to the Project Root. And set

tuist generate

That´s it!

The project files are now shown and can be opened normally via Xcode.

Now you can simply commit your changes and conflicts are limited to the essential things of the project. After checking out, each developer only needs to call tuist generate within the terminal and is then ready to start with the development.

Conclusion

After the first days with Tuist, I am visibly surprised. It is a lot of fun to work with and simplifies my work in many ways. I am also a big fan of XcodeGen and would recommend both tools to everyone.

XcodeGen is a similar tool (https://github.com/yonaskolb/XcodeGen), it also helps to automate the creation of project files. At first glance, here is one difference in how we write the configuration.
XCodeGen uses a YAML or JSON file and Tuist has a Swift file as configuration.

I am very excited to see which new features and improvements the future development of the tool will provide us with. Especially since Tuist offers much more than just project generation.

I hope you like my first article and Tuist. If you have any questions or suggestions, feel free to write to me or leave a comment.

Sources

Sample Project: https://github.com/tomminges/TuistSample

Images created with Visual Studio Code and CodeSnap Plugin.

Thanks for reading and if you have any questions or anything else you can contact me.

--

--