-
Notifications
You must be signed in to change notification settings - Fork 127
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2a5a3da
commit 22dbe23
Showing
2 changed files
with
92 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
--- | ||
title: A declarative approach to Xcode projects | ||
author: | ||
- Riccardo Cipolleschi | ||
date: 2023-06-19 | ||
--- | ||
|
||
# RFC0672: A declarative approach to Xcode projects | ||
|
||
## Summary | ||
|
||
Managing Xcodeproj files is error prone and time consuming as Xcode generates random UUIDs to identify entities in the project. | ||
|
||
Historically, we had trouble with updates, especially when we were modifying the scripts in the Xcode build script phases: those changes are buried in a wall of text that the `Xcodeproj` is and they are easy to miss. | ||
|
||
It also uses a proprietary syntax: it is not a XML, a JSON or anything standard. Preexistent tools can't really highlight changes in a meaningful way, making the Xcodeproj files just a wall of test which can feel daunting for the final user. | ||
|
||
The current proposal suggests to move away from manually managing `Xcodeproj` files in favor of a more declarative description. There are different tools in the OSS space that allows to describe the project declaratively and that then reads that description and generate a valid Xcodeproj accordingly. | ||
|
||
The suggested too is [Tuist.io](https://tuist.io): it allows to describe the project in Swift, leveraging type checking, syntax highlights and code completion. It also uses the default language for Apple development, which is familiar to all the iOS developers and it is executable code, providing more flexibility than a pure markup language. | ||
|
||
## Basic example | ||
|
||
You can have a look at it in action in this PR: | ||
|
||
- https://github.com/facebook/react-native/pull/37952 | ||
|
||
The idea is to describe the project with a declarative approach using Swift. Tuist allows you to load the `Project.swift` file in an instance of Xcode throught the `tuist edit` command. This allows to leverage code completion, type checking and syntax highlight to ensure the correctness of the project. | ||
|
||
## Motivation | ||
|
||
Managing Xcodeproj files is error prone and time consuming. Those files are source of frustrations for teams using them and they have been reported as one of the main pain point when users have to migrate to a new version of React Native. | ||
|
||
Xcode generates projects using random UUIDs to identify the objects that constitutes a project and to refer to them in the project description file itself. These UUIDs are a nightmare to work with, especially when large teams use the same project's file: when two engineers adds two files in the same project, Xcode may create two different UUIDs for the same file and it is usually messy to handle that conflict. | ||
|
||
Managing Xcodeproj manually is also an old and not efficient way to manage projects: even Apple realized that and started developing Swift Package Manager (SwiftPM) to replace the project for developing libraries. | ||
|
||
Modern approaches rely on a declarative syntax to describe how the project should look like and they rely on tools that can generate a valid Xcodeproj starting from that description. For example, [XCodeGen](https://github.com/yonaskolb/XcodeGen) uses YAML to describe the project, while [Tuist.io](https://tuist.io) uses directly swift to achieve the same result. | ||
|
||
The proposed solution is, indeed, to use [Tuist.io](https://tuist.io). It is an OSS tool, with a vibrant community and backed and supported by several companies. Some of its maintainers are also React Native core contributors. | ||
|
||
## Detailed design | ||
|
||
To adopt Tuist in React Native, we need to follow some steps: | ||
|
||
1. Land https://github.com/facebook/react-native/pull/37952. This PR already contains a functioning project which passed all the iOS tests in CI. | ||
2. Update the CLI to install Tuist in the user machine. Tuist comes directly with an additional executable called `tuistenv`, which handles the environment and version for the user. | ||
3. Update the CLI and instruct it to swap the `HelloWorld` strings in the `template/ios/Package.swift` to the AppName chosen by the user. | ||
4. Update the CLI to run `tuist generate` to create the project | ||
5. Update the CLI to run `tuist generate` on `yarn ios` or `npm run ios` in case the `Project.swift` has changed or there is no `Xcodeproj` file. | ||
6. Update doctor to check that the user have Tuist installed | ||
7. Remove the old Xcodeproj file and set the right `.gitignore` settings. | ||
|
||
## Drawbacks | ||
|
||
- Prioritization: I think that the only reason NOT to do this is for prioritization and time. Implementing this system will take some time which we can devote to other, maybe more impactful, activities. | ||
- Impact: This work could simplify updates, but recently we have started pushing all the changes to the Xcodeproj into the Cocoapods scripts. This means that the users don't have to touch the project file at all, and Cocoapods takes care of modifying the project when needed. It is still useful to have a laid-out description of the project, especially for brownfield projects that have to mimic the same configurations of a template app. | ||
- Workflow changes: there is an extra step that user has to run when modifying the project: after every change in the `Project.swift`, users have to run `tuist generate`. This is a minor issue as we do not expect for the user to manually update the `Project.swift` file at all, and we can bake most of the Tuist invocations in the CLI. | ||
|
||
## Alternatives | ||
|
||
### [XCodeGen](https://github.com/yonaskolb/XcodeGen) | ||
|
||
This tool allows to describe the Xcodeproj using a YAML file. | ||
|
||
If we go for this approach, the drawbacks are: | ||
|
||
- a new language to teach to our iOS users | ||
- more verbose project description | ||
- no code completion. | ||
- Xcodegen is less flexible than Tuist as it is not executable code and it is not easily extensible. | ||
|
||
### [Xcake](https://github.com/igor-makarov/xcake/) | ||
|
||
This tool allows to describe a project in Ruby. | ||
|
||
If we go for this approach, the drawbacks are: | ||
|
||
- a new language to teach to our users | ||
- no type checking due to the dynamic nature of Ruby | ||
- one of the oldest tool: it has been unmaintained for a few years before some other OSS contributor took ownership of it. It could go unmaintained again. | ||
|
||
## Adoption strategy | ||
|
||
- Implement all the changes before 0.73. | ||
- Communicate with a BlogPost the change, explaining the implications for new apps and updates. | ||
|
||
## How we teach this | ||
|
||
- Add the requirement to the website | ||
- Blogposts | ||
- Automating the workflow as much as possible. |
This file was deleted.
Oops, something went wrong.