Code Generating Shell Script Package Plugin

I'm trying to generate Swift Code via a shell script, and then use that as a build plugin for a Swift Package.

A proof of concept could be something as simple as...

# generate.sh
echo "struct Foo { static let bar = 42 }" > MyPackage/Sources/Foo.swift

Are there any examples of how could I include this as a Swift plugin for package MyPackage? I'd like to automatically run it prior to each build, and then have the resulting file be usable inside MyPackage.

// main.swift
print("The generated number was: \(Foo.bar)!")

Appreciate any pointers in advance!

I was able to get it up and running with the help of this guide however I can't figure out how to write the generated code to the actual package directory.

If I change the output of the generator to the package directory (instead of DerivedData), it throws the error:

you don't have permissions to save the file <file.swift> in the folder MyPackage/Sources.

How can I give the plugin permissions to allow me to generate Swift code inside the actual package?

For context - the generation is an expensive operation (generate Swift code from thousands of graphql files) and I'd like to cache the generated code so it doesn't regenerate all the code each time. The script keeps track of only re-generating code for the files that have changed.

I appreciate any pointers anyone could provide :pray:

You can't write directly to the Sources directory. Instead, you take the context passed to your plugin's createBuildCommands(context:target:) function, and pass a location within context.pluginWorkDirectory to write your generated source(s) to. The outputFiles of the .buildCommand that you return will need to include (the absolute path of) all the files that your script generated (that you want the Swift compiler to use).

1 Like

Thanks @rhx!

So there is literally no way for a plugin to write anywhere except that specific working directory?

I understand why this would be the default setting, but I'm a bit surprised there isn't a flag or something to bypass this.