Support for rewriting package urls?

I am working for government and we cannot use GitHub. In order to use SPM I wrote a script that mirrors git repositories from GitHub into our internal bitbucket server. There, I can only use a single space "Vendors" so I have to change the name from i.e. "apple/swift-syntax" to "Vendor/apple.swift-syntax".

While this works for a single package, it won't work for dependencies. I found no way to add some kind of rewrite mechanism to SPM so the next best thing was for me to rewrite the git repositories (EXT -> rewrite -> INT-READONLY). While this works it is very cumbersome and I have to constantly update my binary project that does the rewriting. At least I found a reasonable approach by appending some swift code to the end of each Package*.swift file in each commit in each branch of a repository.

The question I have is:

  • Am I missing something here? Is there a way to use Xcode, or swift package on a development machine that has no access to the internet?

  • If not, what is the best way to suggest a feature request and to whom should I send it?

Andreas Pardeike
Swedish Police IT Department

1 Like

I haven’t used it personally, but I believe SPM’s dependency mirroring will accomplish what you’re looking for.

It is my understanding that this works on the package level only. How would I tell our app developers to use a common package (like pointfreeco/swift-composable-architecture) in their Xcode projects?

Again, without having ever actually used the feature, I believe the workflow looks like:

  1. You mirror to, say, https://internal-bitbucket-server/pointfreeco-swift-composable-architecture
  2. Your developer runs the following command on their workstation (probably as part of a setup script for the app):
swift package config set-mirror \
    --package-url \
    --mirror-url https://internal-bitbucket-server/pointfreeco-swift-composable-architecture
  1. Your developers add to their Package.swift like normal
  2. When they build their app, Xcode/SPM instead reach out to https://internal-bitbucket-server/pointfreeco-swift-composable-architecture

Note that you'll also have to repeat steps 1 and 2 for every single dependency for, but the mirroring configuration is on the top level for the app they're building and should apply to all parts of the builds kicked off from that context.

As I said earlier, this only works if you use SPM. When running swift package config set-mirror it will tell you:

error: Could not find Package.swift in this directory or any of its parent directories

which is to be expected since a normal Xcode project does not have a Package.swift.

This is difficult, as Xcode doesn't support mirroring. You'll need to break all of your app's dependencies into a separate Package.swift and then use that file as a package in your app. You'd do all the mirroring in that file.

This is trivial in VSCode.

It does, but not in a very user friendly way.

If you place a mirror config in xcshareddata/swiftpm/configuration of the project/workspace in use, it'll be picked up and applied by libSwiftPM. This should work in pretty much any Xcode version for any dependency declared by a package, so any transitive dependencies.

There was an issue applying them to dependencies declared in Xcode projects specifically which has been fixed a few months ago in, but I am not 100% sure if that has made it into any Xcode releases, yet.

1 Like

This here is the information I was looking for. Thank you, I will try to write some helper binary/script that makes it easier is necessary.

I’ll see if this way actually works.

Btw this stackoverflow topic adds some more information to the details: xcode - Check in xcworkspace for swiftpm to git? - Stack Overflow

Hi again,
I now had time to test this but I cannot get it to work. Here is what I tried so far: created a new spm package and added the mirror there, in this case using GitHub - apple/swift-argument-parser: Straightforward, type-safe argument parsing for Swift

I then created a new app project in Xcode and copied mirrors.json from the spm package over, resulting in this file structure:

β”œβ”€β”€ test
β”‚   β”œβ”€β”€ Assets.xcassets
β”‚   β”‚   └── Contents.json
β”‚   β”œβ”€β”€ ContentView.swift
β”‚   β”œβ”€β”€ Preview Content
β”‚   β”‚   └── Preview Assets.xcassets
β”‚   β”‚       └── Contents.json
β”‚   └── testApp.swift
└── test.xcodeproj
    β”œβ”€β”€ project.pbxproj
    β”œβ”€β”€ project.xcworkspace
    β”‚   β”œβ”€β”€ contents.xcworkspacedata
    β”‚   β”œβ”€β”€ xcshareddata
    β”‚   β”‚   β”œβ”€β”€ IDEWorkspaceChecks.plist
    β”‚   β”‚   └── swiftpm
    β”‚   β”‚       └── configuration
    β”‚   β”‚           └── mirrors.json
    β”‚   └── xcuserdata
    β”‚       └── u0035718.xcuserdatad
    β”‚           └── UserInterfaceState.xcuserstate
    └── xcuserdata
        └── u0035718.xcuserdatad
            └── xcschemes
                └── xcschememanagement.plist

I then opened the Xcode project and used File > Add Package Dependencies... to add but Xcode just asks me to log into GitHub (which via a proxy will fail). So it looks like the mirror is not used.

In contrast, if I go into Package.swift in the spm package project and add the dependency to then it will successfully use our internal mirror from the command line:

> swift package update
Fetching ssh:// from cache

but not if I use Xcode to edit Package.swift:

Conclusion: To me this still looks like Xcode does its very own thing and I cannot use mirroring to solve my proxy problem.

1 Like

Note the second part of the answer: