Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excluding files in Swift Packages

To exclude entire sections of a file, I can use macros to target platforms such as #if os(iOS) || os(watchOS).

Is there a way to do this in Package.swift, or another way to target a few files for specific platforms in Swift Package Manager?

like image 911
TruMan1 Avatar asked Aug 23 '19 02:08

TruMan1


1 Answers

Is there a way to do this in Package.swift ... ?

Swifty stuff also works in Package.swift since the package declaration file is itself a .swift file.

Here are some examples which use Swift 5.3 Package Manager Conditional Target Dependencies SE-0273 condition and when.

// swift-tools-version:5.3
import PackageDescription

// ...
    targets: [
        .target(
            name: "BKSecurity",
            dependencies: [
                .product(name: "Crypto", condition: .when(platforms: [.linux])),
                "BKFoundation"
        ]),
// swift-tools-version:5.3
import PackageDescription

// ...
    targets: [
      .target(
        name: "CombineShim",
        dependencies: [
          .product(name: "OpenCombine", 
                   package: "OpenCombine",
                   condition: .when(platforms: [.wasi, .linux])
        )]
      ),
      .target(
        name: "TokamakShim",
        dependencies: [
          .target(name: "TokamakDOM", condition: .when(platforms: [.wasi])),
          "SomeCommonDependency"
        ]
      ),
// swift-tools-version:5.3
import PackageDescription

let supportsCoreAudio: BuildSettingCondition = 
        .when(platforms: [.iOS, .macOS, .tvOS, .watchOS])
let supportsALSA: BuildSettingCondition = 
        .when(platforms: [.linux])

let package = Package(
    name: "portaudio",
// ...
  targets: [
    .target(
      name: "libportaudio",
      dependencies: [],
      cSettings: [
        .define("PA_USE_COREAUDIO", supportsCoreAudio),
        .define("PA_USE_ALSA", supportsALSA)
      ],
      linkerSettings: [
        .linkedLibrary("asound", supportsALSA),
        .linkedFramework("CoreAudio", supportsCoreAudio),
        .linkedFramework("CoreServices", supportsCoreAudio),
        .linkedFramework("CoreFoundation", supportsCoreAudio),
        .linkedFramework("AudioUnit", supportsCoreAudio),
        .linkedFramework("AudioToolbox", supportsCoreAudio)
    ]),
  ]
//...
)

Note that #if os(…) can be used in Package.swift. However, Package.swift is evaluated, built and executed in the context of the build platform. So, #if os(…) is useful in the context when the target platform is the same as the build platform e.g. macOS, Linux or Windows.

Package.swift

import PackageDescription

let package = Package(
    // ...
    targets: {
        var targets: [Target] = [
            .testTarget(
                name: "QuickTests",
                dependencies: [ "Quick", "Nimble" ],
                exclude: ["SomeFile.ext"]
            ),
        ]
#if os(macOS)
        // macOS build platform
        targets.append(contentsOf: [
            .target(name: "QuickSpecBase", dependencies: []),
            .target(name: "Quick", dependencies: [ "QuickSpecBase" ]),
        ])
#else
        // not macOS build platform, e.g. linux
        targets.append(contentsOf: [
            .target(name: "Quick", dependencies: []),
        ])
#endif
        return targets
    }(),
)

See Also

  • The Swift Programming Language: Statements > Conditional Compilation Block
  • GitHub/Apple/swift: lib/Basic/LangOptions.cpp
    • Currently supported compilation OSs: macOS, tvOS, watchOS, iOS, Linux, FreeBSD,OpenBSD, Windows, Android, PS4, Cygwin, Haiku, WASI
  • GitHub/Apple/swift-evolution: SE-0273 Package Manager Conditional Target Dependencies
like image 193
l --marc l Avatar answered Sep 28 '22 07:09

l --marc l