One of the advantages of defining your projects in Swift is that we can leverage Xcode and the Swift compiler to safely edit the projects with syntax auto-completion and documentation.
Editing your projects is easy; position yourself in a directory where there’s a project defined and run the following command:
It will open a temporary Xcode project with the manifests and the project description helpers. After making changes you can run the target from Xcode and it will call
tuist generate for you.
The project is deleted automatically once you are done with editing. If you wish to generate and keep the project in the current directory, you can run the command passing the
tuist edit --permanent
That will generate a
Manifest.xcodeproj project that you can open manually.
In projects with an established architecture, developers might want to bootstrap new components or features that are consistent with the project.
scaffold you can define your own templates and also templates that Tuist provides to generate a basic structure of your module!
To define templates, you can run
tuist edit and then create a directory under
Tuist/Templates that represents your template. Templates need a manifest file,
Template.swift that describes the template:
import ProjectDescriptionlet nameAttribute: Template.Attribute = .required("name")let template = Template(description: "Custom template",attributes: [nameAttribute,.optional("platform", default: "ios"),],files: [.string(path: "Project.swift",contents: "My template contents of name \(nameAttribute)"),.file(path: "generated/Up.swift",templatePath: "generate.stencil"),],)
This template would then be called like this:
tuist scaffold name_of_template --name Name --platform macos
Since platform is an optional argument, we can also call the command without the
--platform macos argument.
.files don’t provide enough flexibility, you can leverage the Stencil templating language via the
Templates can import project description helpers. Just add
import ProjectDescriptionHelpers at the top, and extract reusable logic into the helpers.
One of the benefits of making the definition of projects explicit, is that we can run checks on them and uncover configuration issues that otherwise would be bubbled up by the build system later on. Tuist follows the principle of the sooner we detect the errors, the less time developers will have to spend. For that reason, we provide a command that developers can run either locally or on CI to ensure their projects have a valid configuration:
Please note that there are checks that only the compiler and the build system can do.
In other words,
those will only be uncover by compiling the app with Xcode or
When projects grow, it becomes hard to visualize the dependencies between all the targets that are part of the project. Fortunately, Tuist provides a command,
tuist graph, that loads your project dependencies graph and exports it in a representable format.
Being in a directory that contains a workspace or project manifest, run the following command:
The command will output a human-readable file,
graph.dot that describes the dependencies graph using the DOT description language.
Graphviz is a command line tool that take the
.dot graph and convert it into an image.
brew install graphvizdot -Tpng graph.dot > graph.png
Alternatively, you can use online services like this one that renders your graph on a website.
Xcode projects often have dependencies with system tools like SwiftLint, Carthage, or Sourcery. Those are dependencies that need to be installed/pulled and properly configured in the developer environment for the project to run.
Most projects include a list of steps in the
README file for developers to follow:
1. Clone the repository.2. Install Carthage if it's not already installed.3. Install `brew install swiftlint`.4. Run `carthage update`.5. Open the project.
It’s a tedious process that can break without you noticing it. Moreover, each project usually has its own set of non-standard steps, which makes inconvenient jumping from one project to another.
The good news is that Tuist offers a command, tuist up that helps you define your project dependencies and then takes care of the configuration process for you.
To define your project dependencies, we need to create a new
Setup.swift manifest file:
import ProjectDescriptionlet setup = Setup([.homebrew(packages: ["swiftlint"]),.carthage(platforms: [.iOS])])
We have turned the markdown steps that we saw before into up commands in the setup manifest. When you run
tuist up, Tuist translates those declarations into actual commands that are executed in your system.
Moreover, it assesses whether those dependencies are already met in the environment, and if they are, it skips them. For instance, if the Carthage dependencies exist and are up to date, it doesn’t run the Carthage update command.
Tuist offers the following set of commands.
It installs the given Homebrew packages if they don’t exist in the system.
Configures Homebrew tap repositories. It also installs Homebrew if it’s not available in the system.
It runs Carthage dependencies for those dependencies that don’t exist or that are outdated.
It installs all the packages in a Mintfile if they don’t exist in the system.
.custom(name: "Name", meet: ["./install.sh"], isMet: ["test", "mytool"])
Besides the built-in commands, you can define yours using the custom option. It takes the following arguments:
- Name: Name of the command
- Meet: Command to run in the system to configure the environment.
- Met: Command to run in the system to verify whether the environment is already configure. A 0 exit code means that the environment is already configured.
If you have ideas of other built-in commands that Tuist could offer, don’t hesitate to open an issue with your ideas.