
When working on a large project with multiple developers, we often find ourselves in contention with the Xcode project.pbxproj
file. Conflicts here are not easy to solve manually, and if you make a mistake Xcode won’t load the project at all, requiring you to fix it manually.
There are some solutions to mitigate these problems and one of them is to treat the Xcode project as a generated artifact instead of the source of truth.
Doing so changes a bit of your workflow, but the benefits are pretty obvious once you get used to it.
In this episode we’ll migrate our Wurdle project from a past series to use Xcodegen.
If you want to follow along, make sure to download the source for that episode first. The completed project.yml
file will be provided in this episode's git repository.
We can install Xcodegen with Homebrew.
$ brew install xcodegen
Once installed, you will run xcodegen
any time you want to regenerate a project. But in order to do that, we first need a project.yml
file.
The project.yml
file contains all of the information needed to create your Xcode project. At first it may seem a little overwhelming, however it contains lots of sensible default behavior and you start to get used to the structure over time.
Be prepared to reference the Project Spec documentation regularly as you build it out.
Our project.yml
contains some top-level information:
name: Wurdle
options:
bundleIdPrefix: com.nsscreencast.wurdle
To specify which packages we may want to install, we add a packages
section to the top level as well:
packages:
Yams:
url: https://github.com/jpsim/Yams
from: 2.0.0
Note: We don’t actually need this package, but I wanted to show how this is done.
Your project is made up of targets. In this example, we’ll create two targets:
We’ll put our model code and any other code we may want to share or test separately in the framework. All of the iOS UI code will go in the application target.
targets:
Wurdle:
type: application
platform: iOS
deploymentTarget: "16.0"
sources: [Sources/Wurdle]
info:
path: Sources/Wurdle/Info.plist
properties:
CFBundleDisplayName: WURDLE!
UISupportedInterfaceOrientations: [UIInterfaceOrientationPortrait]
UILaunchStoryboardName: LaunchScreen
dependencies:
- target: WurdleKit
WurdleKit:
type: framework
platform: iOS
sources: [Sources/WurdleKit]
dependencies:
- package: Yams
info:
path: Sources/WurdleKit/Info.plist
properties:
In this example, we have indicated that we want an Info.plist
file generated with the specified properties. You can also reference an existing Info.plist
file if you have one already and don't want to migrate to a generated one.
At this point all source files that exist in the folder structure you specified will be picked up automatically.
Now run xcodegen
to generate your project. You will run this often:
Since we are continually generating this project file, it’s a good idea now to ignore it from the git repository entirely:
$ git rm -r --cached Wurdle.xcodeproj
(deletes the file from the git index)
$ echo "Wurdle.xcodeproj" >> .gitignore
$ git add . && git commit -m "Ignore xcode project"
This episode uses Xcode 14.0, Xcodegen 2.32.0.