Creating an SPM build pluginPosted Friday, September 8, 2023.
As seen when creating a CLI in an artifact bundle, we made a CLI and packaged it into an artifact bundle.
In this post we are going to explore using this cli in a SPM build plugin to generate code/resources for us in another target. That target will then be vended as a library with the generated content.
The finished file structure of this package will look like:
We are choosing to store our
input.jsonin this package though that is not required
We will use
MyCLI.artifactbundle that we created previously as a binary target. Our
Package.swift will contain the following:
The binary target could be hosted and referenced by URL, but we are choosing to co-locate them for simplicity
Build Tool Plugin
In our build tool plugin, we will call our previously created CLI tool which will handle generating and writing content to the plugin working directory. This will create "read only" code and resources in any target that utilizes this plugin (in our case - the
On clean builds or if the contents of
info.json have changed, this build tool will run. Otherwise the contents generated from the previous run will be cached in DerivedData.
The arguments that we choose in
.buildCommand(...) are the arguments that our CLI requires (ie they match 1:1).
I would have thought that including only
[generatedPath, resourcesPath]for output files would have been good enough, but it did not work unless explicitly specifying the path of each created resource (
x.txt). Hence, we load the info data just to read which txt files will be written by the cli.
As specified in the CLI's command code, the generated swift code is namespaced under
Lets create a file in the
MyCoolLib target named
MyCoolType.swift with the following contents:
Because of the dependency of this target to the build plugin, whenever this target is built, we will have access to the generated code. So if the
info.json had the following contents:
We would expect the following:
MyCoolTypeshould have 2 static members
- Two txt files should have been written
hello.txtwith the contents
this is a greeting message
goodbye.txtwith the contents
this is a parting message
- the static members will read the message from the appropriate text file
Now we can do the following:
In a future post, we will explore how to use this for localization generation in an iOS application