How to switch package dependencies in Xcode after deprecation of 'generate-xcodeproj'?

Xcode can now directly open "Package.swift" to edit sources, run tests, and so on.
As a result, 'generate-xcodeproj' will be deprecated.

Imagine the world where you cannot use 'generate-xcodeproj'.
And the following "Package.swift" is given.

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
import Foundation

let dependencies: [Package.Dependency]
if ProcessInfo.processInfo.environment["USE_ANOTHER_DEP"] != nil {
  dependencies = [.package(path: "/my/another/package")]
} else {
  dependencies = [.package(path: "/my/default/package")]
}

let package = Package(
  name: "SwitchDep",
  products: [
    .library(name: "SwitchDep", targets: ["SwitchDep"]),
  ],
  dependencies: dependencies,
  targets: [
    .target(name: "SwitchDep", dependencies: []),
    .testTarget(name: "SwitchDepTests", dependencies: ["SwitchDep"]),
  ]
)

You can run % USE_ANOTHER_DEP=1 swift build when you want to use "/my/another/package" to build the package.
However, you can't use "/my/another/package" in Xcode when you just doubleclick "Package.swift".
% USE_ANOTHER_DEP=1 swift package generate-xcodeproj was available, but now has been disabled.

Q. How do we switch package dependencies in Xcode after deprecation of 'generate-xcodeproj'?

You can open Xcode with environment variable.

$ killall Xcode
$ USE_ANOTHER_DEP=1 open Package.swift

I don’t know if this is documented or not, but it’s heavily used in my project.

3 Likes

And for things that use the command line anyway, xcodebuild is affected by the environment just the same as SwiftPM.

@ddddxxx
Thank you for the answer. That's a good idea.

In my understanding, all packages opened by Xcode at the same time are affected by the environment variable in that way, aren't they?

Is it impossible to "let SwitchDep1 use /my/default/package and let SwitchDep2 use /my/another/package" simultaneously? :thinking:

@SDGGiesbrecht
Thank you for the response.
xcodebuild requires .xcodeproj, doesn't it?

I don’t think it’s possible. What if /my/default/package and /my/another/package depends on a third package with different configuration? Like a graphic package that you can switch between single precision and double precision?

Not necessarily. I happen to use this technique in my project as well.

As @ddddxxx mentioned, it does not. If the current working directory contains a package manifest, xcodebuild will operate directly on the package. (But the Xcode project wins if both a package manifest and a project are present.)

If I remember correctly the scheme naming is slightly different between a raw package and its equivalent generated project. Use xcodebuild -list to find out what schemes Xcode decided to derive.

1 Like

Thank you for clarifying.
Anyway, your answers have gotten rid of my worry.


@ddddxxx
@SDGGiesbrecht

Thank you for also instructing me about xcodebuild.
I have rarely used xcodebuild so far. I will get help from xcodebuild if the opportunity arises.

One problem with USE_ANOTHER_DEP=1 open Package.swift:
Xcode ignores "~/Library/Developer/Xcode/Templates/File Templates" when the package is opened by the command above. :disappointed_relieved: