(Apologies in advance if the chosen category is unfit, please move if needed )
While investigating the possibilities of scripting in swift (specifically to run scripts on Xcode Cloud) I encountered the usual problems of reusing code. While there are solutions like clutch, this seemed overkill to me and my use case.
Specifically on Xcode Cloud, anything that requires installing more dependencies defeats the purpose of having relatively simple helper functions (e.g. to invoke the usual scripting commands) available in the named "top" scripts (like ci_post_clone.sh
).
Like described in the linked thread, I wanted to simply have some helper code in a common source file, yet @jrose advised against trying to import a source file directly via a command line parameter of swift
.
So I came up with a way to compile my ScriptHelper.swift
common file into a module and import that. After tinkering around a bit, I came to the conclusion to keep it as simple as possible, i.e. no wrapping Package.swift
or anything around it, just pure old swiftc
and some, scripted, moving around of files.
I posted the result as a gist and would very much appreciate any feedback! Perhaps it can also help somebody else (so I will link this in the other thread as well in a second).
A rough explanation is provided in the comments of the gist files, but here some
additional thoughts
I decided against compiling the helper file on the CI as that would have required triggering this inside the various ci_*.sh
scripts on Xcode Cloud, then call yet another script to handle the actual logic I want to implement in my CI scripts. Since I don't expect the helper code to be changed that frequently and it's not "production code" in the sense that it becomes part of my app I simply build the module locally and check the result into my repo. I'd say that's the same as checking in a bunch of dependencies in JavaScript based projects or so (though I am mostly not a fan of this).
So far I ran the rebuildBinaries.swift
script manually on a terminal, I did not include this in my project's build phases or the like to avoid accidentally inflating any commits. I haven't checked whether unchanged source may still lead to slightly different binaries "in git's eyes", though, so maybe that can also be done.
Also, while I usually edit the scripts in Xcode, it seems the way the module is imported (via the shebang) doesn't work well with autocompletion, i.e. Xcode does not properly "see" the methods from the module. Surprisingly, it does not show errors or warnings in the editor either (though it does understand that it is Swift code). I'd be interested in potential solutions.
As explained in the gist, the module is a universal binary, so it should run on Intel and Apple Silicon machines. I have read somewhere that Xcode Cloud seems to run (also?) on Intel, but I haven't checked whether that's (still?) true. As I didn't have a test machine ready, I'm not 100 % sure it does work on x86_64, so I would be extra thankful if somebody can verify that... . I am 99% sure, though...