I can't understand what "BuildConfiguration" exactly is

Hello. I think I should explain my situation first.
Now I have a huge one xcodeproj, and i want to split it. so, I'm trying to make local packages. and combine them into the one project.
like, my.xcodeproj = [PackageA.swift, PackageB.swift, PackageC.swift...]
and some packages need conditions like, "is it DEBUG?" or "is it RELEASE?" until now. In fact, I have more build configurations so this contexts can be added. like "is it ad-hoc?" "is it QA?"
before making local packages, I made some custom configurations and flags. furthermore I made schemes like "app-ad-hoc", "app-dev", "app-qa". and I archive and distribute matching target one by one. below json is my abstraction.

{
  "app-ad-hoc" : {
    "add-hoc-configuration": ["DEBUG", "add-hoc"]
  },
  "app-ad-hoc-qa" : {
    "add-hoc-qa-configuration": ["DEBUG", "add-hoc", "QA"]
  },
  "app-dev": {
    "dev-configuration": ["DEBUG, "DEV"]
  },
  ...
  "app-release": {
    "release-configuration": ["RELEASE"]
  }
}

so, with swift packages, I want to solve this problem as swift's compiler control statements too. like,

// PacakageA
#if DEBUG
something.isDebuggable = true
#elseif QA
something.isQA = true
#endif

If i change this flow, like inject some flags with swift, I have to codes in local packages too. I don't want to do that.
so I've tried to make custom flags in Package.swift. like,

.target(
  name: "Package",
  swiftSettings: [
    .define("DEBUG", .when(configuration: .debug)),
    .define("RELEASE", .when(configuration: .release))
  ]
),

but there are only two option .debug and .release in PackageDescription.BuildConfiguration

and also, my custom configurations are all belong to .release. so I can't understand how PackageDescription.BuildConfiguration really match to project's configuration.

Maybe you think It's not appropriate idea for swift packages. like, 'package should be independent'
I want to solve this problem, but I also really expect other ideas.
Thank you for reading. I need your help

If you're building on the command line with swift build, would package traits resolve your problem?

1 Like

Hello. really thank you for your interest and idea. Indeed, I haven't knew about package traits until you mention it. and also I'm building with Xcode.

but from your comment, I checked the difference about Xcode and SPM, that Xcode uses xcodebuild, and SPM uses swift build. and I remember that SPM is in github

for me, It's too huge to understand in an instant. but It seems Xcode's BuildConfiguration is also PackageDescription.BuildConfiguration. I don't know how but I think some ways may be existed to inject this flag. I'll look for it and reply it if i find. Thank you

In this situation I resorted to a dynamic plist key check:

App plist file:

    <key>CONFIGURATION</key>
    <string>$(CONFIGURATION)</string>

usage from the package:

let configuration = Bundle.main.infoDictionary!["CONFIGURATION"] as! String
if configuration == "SpecialBuildForQA" { // †
    ...
} else {
    ....
}
// † the name doesn't have "Debug" or "Development" in it so treated as "release".

Another alternative is to do a static check in the app and pass that information to the package by some custom means:

app:

#if DEBUG
let configuration = "Debug"
#elseif RELEASE
let configuration = "Release"
#elseif SpecialBuildForQA
let configuration = "SpecialBuildForQA"
#endif

callPackage(configuration: configuration, ...)
1 Like

I can't understand how PackageDescription.BuildConfiguration really match to project's configuration

To my understanding, it seems that the compiler does string matching between "debug” / “release” and your configurations.
If your configuration name contains “debug” (case insensitive), the `.when(configuration: .debug)` will match. It can be “debug”, or “my_debug_conf”, or whatever with “debug” in it.

In my project I removed Debug and Release default build configurations, to set DEV & PROD instead . => none of these can trigger the `.when(configuration: .debug)`
So I renamed DEV with “DEV-debug”, and now the `.when` triggers correctly.

SwiftPM’s BuildConfigurations are defined in PackageModel.BuildConfiguration. There are only two at the moment, debug and release.

And don’t use Traits. Traits are package configuration things, not build configuration. They are evaluated at package resolution time and are not part of the package model after that, in particular at build time.