Skip to content

Combine Compatible Package

ddddxxx edited this page Oct 17, 2019 · 17 revisions

A combine compatible package let you choose underlying Combine implementation, without modifying any code / package description.

Why

It's common to use open souces Combine implementaion as a Combine polyfill on lower version macOS, iOS, and Linux.

For cross platform applications, You need lots of compilation conditions, like this:

Boilerplate Code
// in Package.swift
#if canImport(Combine)
let packageDependencies: [Package.Dependency] = []
let targetDependencies: [Target.Dependency] = []
#else
let packageDependencies = [Package.Dependency.package(url: "https://github.com/cx-org/CombineX", ...]
let targetDependencies: [Target.Dependency] = ["CombineX"]
#endif
// config package accordingly

// in code
#if canImport(Combine)
import Combine
#else
import CombineX
#endif

It's not that simple for libraries. Once you choose Apple's Combine, there's no way you can use open souces Combine implementaion as polyfill for lower OS version. In contrast, once you choose open souces Combine implementaion to support lower version OS, you have to bundle the whole third party Combine, even your user targets on new OS version.

Further more, no matter which Combine implementaion you choose for whatever platform, you are forcing you user to do the same choice. Even worse, If two libraries make different choice, they are inherently incompatiable!

Solution

Introducing CXShim. It dynamically choose appropriate Combine implementation at build time according to env variable. You only need one single dependency, no more compilation conditions.

Example
// in Package.swift
let package = Package(
    name: "MyAwesomePackage",
    ...
    dependencies: [
        .package(url: "https://github.com/cx-org/CombineX", ...),
    ],
    targets: [
        .target(name: "MyAwesomePackage", dependencies: ["CXShim"]),
    ]
}

// in code
import CXShim // Thats all!

Usage

You can specify underlying Combine implementation via env variable.

  • Set SWIFT_PACKAGE_USE_COMBINEX to use CombineX.
  • Set SWIFT_PACKAGE_USE_COMBINE to use Apple's Combine.
$ export SWIFT_PACKAGE_USE_COMBINEX="true"

# for CLI tools, execute with env variable
$ swift ...
$ xcodebuild ...

# for Xcode GUI, reopen Xcode with env variable
$ killall Xcode
$ open Package.swift

If no env variable is set, CXShim automatically select appropriate Combine implementation.

Especially, on Apple platforms, Combine is preferred, so you won't accidentally introduce third party dependency, unless you explicitly specified.

Other Combine Implementation

Note: These project are not part of CombineX. They may have different consistent level with Apple's Combine than we promised, and may not pass our test suit. We do not make any warranty of any kind for them.

Library Env Variable
OpenCombine SWIFT_PACKAGE_USE_OPEN_COMBINE
Clone this wiki locally