Lachtan
Lachtan

Reputation: 5172

Swift Package Manager Dependency Mirroring

I have a project and:

That being said, if I want to install any dependency, I have to ask their dev ops to mirror the target repository and only then I can use it.

The problem arises when I want to implement Crashlytics which has a lot of dependencies. When I import the Firebase, it's fetched from the mirrored repo correctly, but it's dependencies are still being fetched from the original URLs (which makes perfect sense).

The question is - How do I tell Swift Package Manager to swap each URL with mirrors? I have all the dependencies mirrored. I only need to tell SPM to use it.

I have found this proposal which was implemented in Swift 5, but when I go to root of my project and run:

$ swift package config set-mirror --package-url <original URL> --mirror-url <mirror URL>

I get this error:

error: root manifest not found

Any ideas how to do this correctly? Thank you

EDIT:

As Florian correctly pointed out, the proposal works from the package's repository, not my projects! So:

  1. I do clone mirrored repo in my project's root
  2. I run set of commands to set mirror url for each dependency:
swift package config set-mirror \
    --original-url https://github.com/google/GoogleAppMeasurement.git \
    --mirror-url <company's url>/mirrors/githubcom-google-GoogleAppMeasurement
  1. I go back to projects root and run:
xcodebuild -resolvePackageDependencies -project MyProject.xcodeproj -scheme MyAppScheme

But it's still fetching from original urls, not the mirrors!

Upvotes: 3

Views: 1692

Answers (3)

Rakuyo
Rakuyo

Reputation: 630

Try this:

  1. Build a package using Package.swift in your project root directory.
  2. Add the dependencies required by your application to the Package.swift in step 1.
  3. Prepare the mirror files (mirrors.json) and add them to the following two paths respectively:
    • [appName].xcodeproj/project.workspace/xcshareddata/swiftpm/configuration
    • root/.swiftpm/configuration
  4. Add this package as a local dependency in your project.

Step 3 requires setting up mirroring in two places. Now I have set up both, but I suspect that one of them may not be necessary.

Also, please check your .gitignore file. The data under xcshareddata will most likely not be submitted to git.

Upvotes: 1

dirtydanee
dirtydanee

Reputation: 6151

SPM mirroring only works for packages, not applications.
I faced withthe requirement to use on the CI the packages from an internal repository, while building on my workstations we are required to build from a public Github repo.

The solution i went with is to "patch" the project.pbxproj file using a shell script.
In the project.pbxproj the URL for the repository is set to be the public and is just a plain string.
On the CI we use xcodebuild to build the application, and prior to the build / archive actions i run a shell script using sed to override the URL to the internal.

#!/usr/bin/env bash

set -e

if [[ ! "${RUNNING_ON_CI}" ]]; then
    echo "Build is not running on the CI, skipping SPM URL update."
    exit 0
fi

PROJECT_FILE_PATH="${REPO_ROOT}/${PROJECT_NAME}.xcodeproj/project.pbxproj"
sed -ie "s/[email protected]:Alamofire\/Alamofire.git/[email protected]:Alamofire\/Alamofire.git/g" "${PROJECT_FILE_PATH}"

SED_BACKUP_FILE="${REPO_ROOT}/${PROJECT_NAME}.xcodeproj/project.pbxproje"
if [ -f "${SED_BACKUP_FILE}" ]; then
    rm -rf "${SED_BACKUP_FILE}"
fi

It is not mirroring, since we always build from the internal repository on the CI, but it works.

Upvotes: 0

Florian Friedrich
Florian Friedrich

Reputation: 841

Having an Xcode project makes this task basically impossible (at the time of writing). Xcode's integration with SPM works fine for most things, but is not (yet?) at par with what SPM can do in pure SPM packages.

The problem is, that swift package config is always only local to the package and does not have any effect on projects / packages that depend on the package. And with Xcode currently having no counterpart to swift package config, it's not possible to do this at the moment.

What you could do, however, is to clone all your dependencies locally and then reference them as local packages from Xcode (simply dragging the package folder into the open Xcode project will do so). Xcode will be smart enough to take the dependencies from the local local checkout (or at least it was smart enough last time I tried this).

Let's hope for a future Xcode version with full SPM support!

Upvotes: 1

Related Questions