SE-0271: Package Manager Resources

Yes. It's implemented.

you mean in Xcode 12.1 beta? it's not public yet, right? The Bundle.module API does not exist in Xcode 12 beta toolchain

UPD. so it's available only if you open project via Package.swift file in Xcode and not if you generate Xcode project

I find that swift package generate-xcodeproj doesn't seem to include resources, build resource bundles or include the Bundle.module API. Is that a bug you know about?

swift package generate-xcodeproj doesn't support resources as it is kind of a legacy command that existed prior to Xcode supporting SwiftPM projects out of the box. Going forward, I would expect all features to work first and foremost by opening the SwiftPM project in Xcode, and not necessarily with generate-xcodeproj.

2 Likes

Just a note that Xcode CI “bots” still don’t support SwiftPM projects out of the box, and swift package generate-xcodeproj is currently IMO the easiest work-around.

Just a note that Xcode CI “bots” still don’t support SwiftPM projects out of the box, and swift package generate-xcodeproj is currently IMO the easiest work-around.

you can use standard xcodebuild commands targeting swift packages. You dont actually need and Xcode project to do it.

here's a standard GitHub actions workflow I used for building one of my packages.

Build:
    runs-on: macos-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2.3.4
      - name: List available Xcode versions
        run: ls /Applications | grep Xcode
      - name: Select Xcode
        run: sudo xcode-select -switch /Applications/Xcode_12.2.app
      - name: Build and Test
        run: xcodebuild test -scheme MyPackage -destination 'platform=iOS Simulator,OS=14.2,name=iPhone 12'

Yes, GitHub actions are very useful when your projects are hosted on GitHub. Unfortunately you can’t configure an Xcode CI bot with arbitrary commands* for building and testing so there’s no way to use xcodebuild directly in that situation.

*unless you set up an Xcode project that defines an external build system, but then we’re back to needing a project file.

@NeoNacho in fact you don't need a Run script phase, it is both easier and more complicated than that.

  1. SPM + XCode handle .metal files properly, by adding them as .process("MyFile.metal") in resources. So you know, it merges all the compiled metal symbols into a single default.library. Xcode do just the same and it's fine to use a bit of metal along with SPM.

  2. When using a Metal file to define CoreImage functions, it is required that you set MTL_COMPILER_FLAGS to -fcikernel and MTLLINKER_FLAGS to -cikernel.
    This is the first issue : there is currently no metalSettings that I am aware of. We would need both compiler flags and linker flags.

  3. Rarely you want to have both metal functions and CoreImage kernel functions in an app (I am currently encountering the need). It turns out when adding the flag described above, your non-CoreImage metal functions won't be compiled. The workaround with Xcode isn't that simple : You need to define a Custom Build Rule for CoreImage metal files with a custom extension, let say .cikernel.
    The Custom Build Rule will copy .cikernel back to .metal extension in order to execute two command, xcrun metal and xcrun metallib. The first command builds an intermediate .air file, taking a file that needs .metal extension as input. And the second command builds the final .metallib with the .air as input. It may seem weird to rename some of the .metal files to .cikernel but they need to be excluded from Xcode's regular build system, for which we ommit the custom build settings so that regular non-CoreImage metal files can be built properly. As I said, this is a bit more complicated... and counter-intuitive.

... I tried to get a script to copy, and build custom metal files from the Package.swift but it seems writing from there is not permitted. A solution would be something like that :

resources: [
   .processMetal("MyFile.metal"), // implying output: `default.metallib`
   .processMetal("MyCoreImageFunction1.metal", "MyCoreImageFunction2.metal",
        compilerFlags: ["-fcikernel"],
        linkerFlags: ["-cikernel"],
        output: "MyCoreImageFunctions.metallib")
]

I wonder if the SPM community will take this subject seriously in consideration soon. Or if an alternative such as being allowed to run scripts is coming soon. Building metal library manually is not really sustainable.

1 Like