SE-0271: Package Manager Resources

It’s just a tool update, so theoretically, it wouldn’t need to coincide with any OS update.

It’s up to Apple if they feel it’s worth releasing another interim XCode update. Perhaps if the community demand is strong, they might be persuaded to do it :man_shrugging:

Sure, but we're literally run out of time for that to happen before WWDC. And as history showed us, there was no new Xcode with a different Swift version released in between WWDC and the fall.

2 Likes

Then again, there might not be a WWDC this year...

I doubt that Apple won‘t even make everything virtual and prepare video sessions.

That release will be Swift 5.3. A release process blog post with branching schedule will be going up shortly.

32 Likes

Awesome news. This is the only thing preventing my company from moving to SPM.

1 Like

Is this usable now via Xcode importing a 5.3 Developer Snapshot? My mild experimentation says, "No" but greater minds than mine are abundant here!

As far as I can tell it is not. In my past experience, Xcode has never used the installed toolchain in the "Resolve Swift Packages" step, which is a little annoying. I filed FB7691693 suggesting that it would be good to have Xcode use the chosen toolchain to resolve swift packages.

To get resources working, I used Docker and the latest nightly Swift 5.3 image. If you have Docker installed and running, you can run swift test using the following script in your package directory:

docker run \
    --rm \
    --volume "$PWD:/package" \
    --workdir "/package" \
    swiftlang/swift:nightly-5.3 \
    /bin/bash \
    -c "swift test --build-path ./.build/linux"

(Hat tip to @samdeane for the original script.)

2 Likes

This is correct, the toolchain is only used to find the used compiler, linker, etc -- but we are not loading libSwiftPM from there. Only the built-in one is being used.

I'm trying it with Xcode 12 on mac and with swift 5.3 dev snapshot on linux. I'm using proposal itself as a documentation.

it works, tho i was very much confused on the usage. root directory for lookup is Sources/ProductName (if configured with default sources location). and from what I see in my tests you can not place any resource outside that directory - switpm just ignores that configuration

1 Like

That's correct, resources work very much like sources in that regard.

Is the Bundle.module implemented as of Xcode 12 beta 1 ?

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.