Skip to content

Instantly share code, notes, and snippets.

@amosavian
Last active December 12, 2017 21:27
Show Gist options
  • Save amosavian/c6c5db6453b0355362a574c3feac4d71 to your computer and use it in GitHub Desktop.
Save amosavian/c6c5db6453b0355362a574c3feac4d71 to your computer and use it in GitHub Desktop.
Target platform condition Proposal for Swift

Target platform condition

Introduction

This proposal intends to indroduce a unified way to check building and evironment conditions and allow to expand them in future. Another intnetion is to decrease os check as all Apple platforms can be checked by #if target(kernel: Darwin) rather than checking for 4 different OSes.

Motivation

A developer usually must check for environment to expose different behavior in different building situations. In Swift, this usually is done with #if precompiling directive.

A flow with current approach is we should check every OS separately, this can lead to confusion and increase maintanence cost for currnet codes as Swift is expanding to new environments and a code should be checked against 12 OSes and architectures.

Proposed Solution

This proposal deprecates existing #if arch() & #if os() grammer and introduces new way:

#if (type: condition)

The type can be arch, os, kernel, config and env. This design allows to replace:

#if os(macOS) || os(ios) || os(tvOS) || os(watchOS)

simply with a more meaningful:

#if target(kernel: Darwin)

If a new operating system would be introduced by Apple based on Darwin, new code will be compiled correctly without any modification.

Detailed Design

This will conditions available:

Architecture

For arch type, condition can be x86_64, arm, arm64, i386, powerpc64, powerpc64le and s390x

Operating system

For os type, condition can be macOS, iOS, watchOS, tvOS, GNU, Windows, FreeBSD, Android, PS4, Cygwin, Haiku, Fuchsia

Please note Linux is a kernel. GNU fits better as operating system.

Kernel

for kernel type, condition can be Darwin, Linux, Posix, Zircon.

Darwin will cover macOS, iOS, watchOS, tvOS.

Linux will cover GNU, Android, Cygwin.

BSD will cover FreeBSD, PS4.

Posix will cover all Darwin, BSD and Linux OSes.

This type simplifies importing in Foundation and StdLib to:

#if target(kernel: Darwin)
    import Darwin
#elseif target(kernel: Linux) || target(kernel: BSD)
// equal with `#elseif target(kernel: Posix)` as we checked Darwin already
    import Glibc
#endif

Environment

For env type, condition can be simulator, embedded, desktop.

Also we can define mobile, tablet, watch as environment, but these conditions should be handled runtime rather than compile time.

This section covers proposal 190.

Configuration

For config type, condition can be debug, release. This will be affected by Xcode build configuration.

Endianness

For endian type, condition can be little, big. This will be mapped to corresponding arch types.

Other considerations

We may add support for Metal version by this approach. e.g. #if target(metal: 2).

Technically, Linux is a kernel and Gnu is userland of operating system. In existing system it's a condition for os.

Cygwin is considered as operating system. We can define it as env with Windows as operating system. But this may add complexity.

Source compatibility

This is an additive proposal, existing code will continue to work but we can deprecate existing approach.

A warning and fixit may be provided for migrating recognizable cases in existing code, but this will not be necessarily.

Effect on ABI stability

None

Effect on API resilience

None

Alternatives Considered

Some possible alternatives can be considered:

  1. Keep current approach for architecture and os determination.
  2. Add #if config() and #if kernel() to existing directives.
  3. Using cpu as type instead of arch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment