Target environment platform condition
- Proposal: SE-0190
- Authors: Erica Sadun, Graydon Hoare
- Review Manager: Ted Kremenek
- Status: Implemented (Swift 4.1)
- Swift Evolution Review Thread
- Implementation: apple/swift#12964
- Decision Notes: Rationale
This proposal introduces a platform condition to differentiate device and simulator builds. This condition subsumes a common pattern of conditional compilation for Metal, Keychain, and AVFoundation Camera code.
- Expanding Build Configuration Tests for Simulator and Device targets
- Target environment platform condition
A common developer requirement is to conditionally compile code based on whether the current compilation target is a simulator or a real device. The current technique for accomplishing this involves testing for particular combinations of presumed mismatch between architecture and operating system. This is fragile and non-obvious, and requires reasoning about complex nested conditions that obscure the user's purpose.
For example, code often looks like this:
// Test for a simulator destination #if (arch(i386) || arch(x86_64)) && (!os(macOS)) print("Simulator") #else print("Device") #endif // More restrictive test for iOS simulator // Adjust the os test for watchOS, tvOS #if (arch(i386) || arch(x86_64)) && os(iOS) // iOS simulator code #endif
This proposal adds a new platform condition
targetEnvironment with a single valid
In other words, the proposal is to enable conditional compilation of the form
When the compiler is targeting simulator environments, the
condition will evaluate to
true. Otherwise it will evaluate as
In the future, other target environments may be indicated using different arguments to
targetEnvironment condition. It is a general extension point for disambiguating
otherwise-similar target environments.
The name of the condition is motivated by the fact that an unambiguous indication of target environment can be made using the 4th (seldom used, but valid) environment field of the target triple provided to the compiler.
In other words, if the compiler's target triple is specified with an environment
field such as
will be set.
As a transitionary measure: until users have migrated to consistent use of target triples
with an explicit
simulator value in the environment field, the Swift compiler
will infer it from the remaining components of the target triple, without requiring the
user to approximate the condition through combinations of
In other words, while a given target triple may be missing the environment field,
targetEnvironment(simulator) condition may still be
true, if it is inferred
that the current target triple denotes a simulator environment.
This is an additive proposal, existing code will continue to work.
A warning and fixit may be provided for migrating recognizable cases in existing code, but this will necessarily be best-effort, as existing conditions may be arbitrarily complex.
Effect on ABI stability
Effect on API resilience
Swift currently supports the following platform conditions:
os()function that tests for
macOS, iOS, watchOS, tvOS, Linux, Windows, FreeBSD, Android, PS4, Cygwin and Haiku
arch()function that tests for
x86_64, arm, arm64, i386, powerpc64, powerpc64le and s390x
swift()function that tests for specific Swift language releases, e.g.
Comparison with other languages
- Rust's conditional compilation system
target_envconfiguration option, which similarly presents the environment field of the target triple.
- In Clang, several environment-based preprocessor symbols can be used to achieve similar
__ANDROID__, etc.) though the mapping is quite ad-hoc and the 4th field of the target triple is officially documented as representing the target ABI. In the implementation, however, the 4th field is treated as environment (subsuming ABI) and a 5th field for object format is supported.
- Clang also supports various flags such as
-mtvos-simulator-version-minwhich define a simulator-specific preprocessor symbol
Some possible alternatives were considered:
- As in the first round of this proposal,
target(simulator). This has the advantage of brevity, but the disadvantage of using a relatively overloaded term, and contradicts the existing design of using a separate condition per-component of the target triple (
- A similarly brief
environment(simulator)condition, which has the disadvantage that users may mistake it for a means of accessing environment variables of the compiler process.
- An additional state for the
archconditions, such as
os(simulator). This would complicate both the definition and implementation of platform conditions, while blurring the notion of an operating system.
- Avoidance of the target triple altogether, and use of a dedicated
simulator()platform condition. This is the simplest option, but is less-similar to existing conditions and may introduce more meaningless combinations of flags as the set of target environments grows (rather than mutually exclusive arguments to