As I wrote previously, I finally adopted XcodeGen across my projects. One of the mistakes I sometimes make is forgetting to run xcodegen after I update project.yml. Most of the time, this is obvious, like if I’m testing or tweaking some project settings. But I find that I might miss it if I’m updating the build or version number.

This was easy to solve. I took inspiration from CocoaPods (it checks if Podfile.lock has been modified).

There are 3 parts:

Copy project.yml when running xcodegen

I use just as my command runner, but this can easily replicated with make or a shell script. In my justfile:

xcodegen:
    xcodegen
    cp project.yml .project-last.yml

So instead of running xcodegen, I run just xcodegen instead.

Add a build phase script to check if the copied file is the same as project.yml

Add this to the target in project.yml:

    preBuildScripts:
      - name: "[xcodegen] Check project.yml in-sync"
        script: |
                diff project.yml ".project-last.yml" > /dev/null
                if [ $? != 0 ] ; then
                    # print error to STDERR
                    echo "error: project.yml has been modified. Run 'just xcodegen'." >&2
                    exit 1
                fi
        basedOnDependencyAnalysis: false
        showEnvVars: false

Add .project-last.yml to .gitignore

In .gitignore, add:

## track last generated project.yml so we can check if Xcode project is in sync when building
.project-last.yml

That’s it!

Just run just xcodegen whenever you want to regenerate the Xcode project and then build with Xcode as normal. If you have edited project.yml and forget to run just xcodegen and ran xcodegen instead, or forgot both and build in Xcode, it’ll complain.