iOS Dev Tools
Generating xcodeproj’s with Xcodegen
Get rid of unreadable xcodeproj files and say hello to readable project configuration files
Have you ever created pull requests(PR)/merge requests(MR) with changes to the xcodeproj
file of your iOS app project?
It is likely that a team of 2 more iOS devs to make changes to the xcodeproj
files simultaneously.
For example, both may create new files. In such a case, you may create conflicting changes as both of you modify the same file. Additionally, xcodeproj files are not readable. Reviewing PRs with changes in the xcodeproj files is hard to follow and understand.
Is there any way we can get rid of xcodeproj
files? Unfortunately, there is no easy way to get rid of these xcodeproj
files for iOS app development.
However, we can easily generate xcodeproj files from more readable configuration files using Xcodegen.
Xcodegen allows you to store your project configuration in a YAML formatted file. Xcodegen then generates the xcodeproj
files based from the YAML file.
In this post, I will show you how to adopt a simple sample project to use Xcodegen. Then I will show how to add Swift Packages using Xcodegen. Finally, I’ll cover how to change build settings for your targets.
I have used Swift 5.5.2 and Xcode 13.2.1 for this article.
How to convert an iOS app project to use Xcodegen
In this section, we’ll start by installing Xcodegen.
We’ll then download an already existing app.
Finally, create an Xcodegen project configuration file, remove the existing xcodeproj file and generate the xcodeproj file using Xcodegen.
Here are the steps we are going to take:
Let’s get started!
1. Install Xcodegen
There are multiple ways to install Xcodegen. However, in this tutorial, we’ll be using Homebrew to install Xcodegen. Homebrew is a software package management system. It is a very popular tool for macOS. If you haven’t already installed it then go ahead and do so. Follow the installation instruction for Homebrew in its website brew.sh.
Once Homebrew is installed let’s install Xcodegen. Run the following command in the terminal:
brew install xcodegen
2. Download the starter pack
Let’s download an already existing iOS app project. Open a terminal and run the following commands:
cd $HOME
git clone https://github.com/anuragajwani/SaladMaker
cd SaladMaker
open -a Xcode SaladMaker.xcodeproj
3. Converting the project to use Xcodegen
Before we create the YAML file for Xcodegen let’s first analyse the project structure in the xcodeproj files.
First, we have a project named SaladMaker
which contains a single target. The single target is an app for the iOS platform named also SaladMaker
. The source files and assets for the project is under a directory also named SaladMaker
. The minimum deployment target for this app is iOS 14.
Let’s create the YAML file for Xcodegen. In terminal run the following command with <YOUR_NAMESPACE>
replaced:
cat > project.yml <<-EOF
name: SaladMaker
options:
bundleIdPrefix: com.<YOUR_NAMESPACE>
targets:
SaladMaker:
type: application
platform: iOS
deploymentTarget: "14.0"
sources:
- SaladMaker
EOF
Next, let’s delete SaladMaker.xcodeproj
and run Xcodegen at the root of the project. Run the following command:
rm -rf SaladMaker.xcodeproj && xcodegen && open SaladMaker.xcodeproj
Xcodegen will read the project.yml
file and generate an xcodeproj
based on the contents of the project.yml
.
Let’s breakdown the contents of the project.yml
. The name
property is the project name. The options
property applies configuration setting across the whole project. In this case, all targets identifier will be prefixed with com.<YOUR_NAMESPACE>
(you can change here to own identifier). By default, Xcodegen will generate the Bundle Identifier to bundle prefix + target name (i.e. com.anuragajwani.SaladMaker
).
Next, we have the targets
property. This should be self explanatory. All targets will be specified under this property. We have our SaladMaker
target which of type
application
for the iOS
platform
. We set the minimum deployment target to 14.0
and set the source files and assets by specifying the sources
property.
Xcodegen allows for lots of customisation and configuration. Check out the full specification for the YML file.
That’s it! We’ve gone from a complicated xcodeproj
file of over 350 lines of code over multiple files to 10 lines of code.
Remember to tell git to ignore the xcodeproj files once you ready to use Xcodegen. I won’t be covering how to do that as git is out of scope for this article.
Additionally, all members should remember to run xcodegen
command when changing branches.
How to add Swift Packages using Xcodegen
Most applications use open source libraries to aid or speed development. There are multiple ways of importing open source libraries. One of the most popular methods is to use a dependency manager. One of the most popular dependencies managers used in iOS development is Swift Package Manager.
In this section, I will show you how to import a popular open-source library used in iOS development: Alamofire.
Open project.yml
at the top level after options:
section add the following:
packages:
Alamofire:
url: https://github.com/Alamofire/Alamofire
majorVersion: 5.5.0
Above we added the package at a project level. However, we haven’t linked Alamofire to our SaladMaker app target. Let’s do that next. Under the SaladMaker
target add the following:
dependencies:
- package: Alamofire
Your project.yml
should look like the following:
name: SaladMaker
options:
bundleIdPrefix: com.anuragajwani
packages:
Alamofire:
url: https://github.com/Alamofire/Alamofire
majorVersion: 5.5.0
targets:
SaladMaker:
type: application
platform: iOS
deploymentTarget: "14.0"
sources:
- SaladMaker
dependencies:
- package: Alamofire
Next, run xcodegen and then open SaladMaker.xcodeproj
in Xcode. In terminal run the following commands:
xcodegen && open SaladMaker.xcodeproj
That’s it, we’re ready to use Alamofire in SaladMaker.
How to change build settings
By default, Xcodegen will set the xcodeproj default build settings or not specify it at all and allow Xcode to set the default.
However, in some cases, we might want to tweak build settings based on our app-specific needs. Xcodegen allows us to specify any build settings that you want to set for a target. Let’s say we want to disable bitcode for our SaladMaker app. Open project.yml
and under the SaladMaker target add the following:
settings:
ENABLE_BITCODE: NO
Your project.yml
should now look like the following:
name: SaladMaker
options:
bundleIdPrefix: com.anuragajwani
packages:
Alamofire:
url: https://github.com/Alamofire/Alamofire
majorVersion: 5.5.0
targets:
SaladMaker:
settings:
ENABLE_BITCODE: NO
type: application
platform: iOS
deploymentTarget: "14.0"
sources:
- SaladMaker
dependencies:
- package: Alamofire
Once again run xcodegen command to generate a new xcodeproj:
xcodegen && open SaladMaker.xcodeproj
See the changes in action:
Summary
- Xcodegen simplifies complicated to read xcodeproj files in project configuration YAML files.
- Pull Requests/Merge Request are easier to read and follow
- Conflicts in the
project.yml
are easier to resolve
There is a lot you can configure of the project with Xcodegen. Make sure to checkout the specs.
Final Thoughts
Xcodeproj files have been around for a long while now. They haven’t got better over time. I don’t know whether Apple is working on replacing these for iOS apps and other application targets.
However, there are positive signs from Apple. For example, for Swift Packages, Apple ditched xcodeproj files in favour of a more readable Package.swift
file. Xcode can read these files as project configuration files for packages.
For now, the tools like Xcodegen allows stepping away from xcodeproj
files to a certain degree. Xcodegen is not the only tool out there. I will be covering other tools and comparing these in the future.
Want to Connect?For more on iOS development follow me on Twitter.