<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">In the near future it's likely that this project will need to have types that use C based functionality for representing sockets or other low-layer functionality. This has typically been implemented using a conditional include based on whether the code is on Linux or not to import Darwin or Glibc:<div class=""><br class=""></div><div class="">&nbsp; #if os(Linux)</div><div class="">&nbsp; import Glibc</div><div class="">&nbsp; #else</div><div class="">&nbsp; import Darwin</div><div class="">&nbsp; #endif</div><div class=""><br class=""></div><div class="">This pattern exists in a number of different open source projects already, and it's a problem as new operating systems are added.</div><div class=""><br class=""></div><div class="">To that end, I've drafted a proposal that I intend to post to swift-evolution this weekend. If anyone would like to comment on this before I do, or add their names to the proposal as well, please let me know. I would like to send the draft off on Saturday, to give time for people to look over it before SwiftSummit convenes on Monday.</div><div class=""><br class=""></div><div class="">Arguably this is out of scope for Swift 3 phase 1, but I think it would be of benefit to this community to have a module that performs this functionality and we may be able to drive the requirements to include it in Swift 3 phase 2.</div><div class=""><br class=""></div><div class="">Comments welcome.</div><div class=""><br class=""></div><div class="">--- 8&lt; ---</div><div class=""><br class=""></div><div class=""><div class=""># Libc module for Swift</div><div class=""><br class=""></div><div class="">* Proposal: [SE-NNNN](NNNN-filename.md)</div><div class="">* Authors: [Alex Blewitt](<a href="https://github.com/alblue" class="">https://github.com/alblue</a>)</div><div class="">* Review Manager: TBD</div><div class="">* Status: **Under discussion**</div><div class=""><br class=""></div><div class="">## Introduction</div><div class=""><br class=""></div><div class="">When running on Darwin, the base module is called `Darwin`. When running</div><div class="">on Linux or other operating systems, it's called `GlibC`.&nbsp;</div><div class=""><br class=""></div><div class="">This repeatedly leads to code such as:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; ````</div><div class="">&nbsp; &nbsp; #if os(Linux)</div><div class="">&nbsp; &nbsp; &nbsp; import Glibc</div><div class="">&nbsp; &nbsp; #else</div><div class="">&nbsp; &nbsp; &nbsp; import Darwin</div><div class="">&nbsp; &nbsp; #endif</div><div class="">&nbsp; &nbsp; ```</div><div class=""><br class=""></div><div class="">As the set of operating systems evolve, one of these conditional imports</div><div class="">needs to be updated. Instead of repeating this, make it available via a</div><div class="">standard `Libc` module in the base Swift library.</div><div class=""><br class=""></div><div class="">Swift-evolution thread: [Discussion thread topic for that proposal](<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161003/027621.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161003/027621.html</a>)</div><div class=""><br class=""></div><div class="">## Motivation</div><div class=""><br class=""></div><div class="">The [set of platforms](<a href="https://github.com/apple/swift/blob/fdf6ee20e4ca1fd32482f4b7b88a97ebdda52cd2/lib/Basic/LangOptions.cpp#L26-L36" class="">https://github.com/apple/swift/blob/fdf6ee20e4ca1fd32482f4b7b88a97ebdda52cd2/lib/Basic/LangOptions.cpp#L26-L36</a>)</div><div class="">that Swift currently runs on can be divided into two; Darwin and XNU based systems</div><div class="">(macOS, iOS, watchOS, tvOS), Windows, and Unix based systems</div><div class="">(Linux, FreeBSD, Android, PS4).&nbsp;</div><div class=""><br class=""></div><div class="">The base module on Darwin is called `Darwin`, while on Linux and</div><div class="">other Unix systems the base module is called `Glibc`. The base</div><div class="">module is typically conditionally included when working at a lower layer</div><div class="">than Foundation (which has the same detail involved in importing the</div><div class="">base module).</div><div class=""><br class=""></div><div class="">As a result, conditionally importing the right version typically uses</div><div class="">a conditional test based on the operating system, and the same code is</div><div class="">seen in a number of different modules, both internal to Swift and external:</div><div class=""><br class=""></div><div class="">* [Test for mmap in stdlib](<a href="https://github.com/apple/swift/blob/07b196d2f9a5facc490b35e3649e18937796239b/test/stdlib/mmap.swift#L4-L9" class="">https://github.com/apple/swift/blob/07b196d2f9a5facc490b35e3649e18937796239b/test/stdlib/mmap.swift#L4-L9</a>)</div><div class="">* [Validation test for PassIfChildCrashedDuringTestExecution](<a href="https://github.com/apple/swift/blob/c3b7709a7c4789f1ad7249d357f69509fb8be731/validation-test/StdlibUnittest/ChildProcessShutdown/PassIfChildCrashedDuringTestExecution.swift#L4-L9" class="">https://github.com/apple/swift/blob/c3b7709a7c4789f1ad7249d357f69509fb8be731/validation-test/StdlibUnittest/ChildProcessShutdown/PassIfChildCrashedDuringTestExecution.swift#L4-L9</a>)</div><div class="">* [Kitura's Socket definitions](<a href="https://github.com/IBM-Swift/BlueSocket/blob/49c5af8b6953cecc8674a7fcf746fa27a72c056a/Sources/Socket.swift#L21-L25" class="">https://github.com/IBM-Swift/BlueSocket/blob/49c5af8b6953cecc8674a7fcf746fa27a72c056a/Sources/Socket.swift#L21-L25</a>)</div><div class="">* [Vapor's HTTP Server](<font color="#0069d9" class=""><u class=""><a href="https://github.com/vapor/engine/blob/1f95094ee470408309e98dd56b2251210d6a2a3d/Sources/HTTP/Models/Server/HTTP+Server.swift#L1-L5" class="">https://github.com/vapor/engine/blob/1f95094ee470408309e98dd56b2251210d6a2a3d/Sources/HTTP/Models/Server/HTTP%2BServer.swift#L1-L5</a>)</u></font></div><div class=""><br class=""></div><div class="">Some have already created a `Libc` module that effectively does what this</div><div class="">proposal suggests, such as [Vapor's Core Libc](<a href="https://github.com/vapor/core/blob/master/Sources/libc/libc.swift" class="">https://github.com/vapor/core/blob/master/Sources/libc/libc.swift</a>)</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; ```</div><div class="">&nbsp; &nbsp; #if os(Linux)</div><div class="">&nbsp; &nbsp; &nbsp; @_exported import Glibc</div><div class="">&nbsp; &nbsp; #else</div><div class="">&nbsp; &nbsp; &nbsp; @_exported import Darwin.C</div><div class="">&nbsp; &nbsp; #endif</div><div class="">&nbsp; &nbsp; ```</div><div class=""><br class=""></div><div class="">Each of these examples has subtly different behaviour; for example,</div><div class="">whether or not the os tests only include Linux (and then fail over to</div><div class="">Darwin), or whether they contain other Unices such as FreeBSD and Android.</div><div class=""><br class=""></div><div class="">## Proposed solution</div><div class=""><br class=""></div><div class="">The solution is to formalise these patterns in the base Swift library</div><div class="">and present a `Libc` module that conditionally imports `Glibc` or `Darwin`</div><div class="">based on the correct platform. Additional operating systems can be added</div><div class="">and kept up to date with the list of supported operating system conditionals</div><div class="">and including a failure message when an unknown operating system is detected.</div><div class=""><br class=""></div><div class="">## Detailed design</div><div class=""><br class=""></div><div class="">This will add a `Libc` module for the standard library that re-exports</div><div class="">the correct import depending on the operating system:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; ```</div><div class="">&nbsp; &nbsp; #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)</div><div class="">&nbsp; &nbsp; &nbsp; @_exported import Darwin</div><div class="">&nbsp; &nbsp; #elseif os(Linux) || os(FreeBSD) || os(Android) || os(PS4)</div><div class="">&nbsp; &nbsp; &nbsp; @_exported import Glibc</div><div class="">&nbsp; &nbsp; #else</div><div class="">&nbsp; &nbsp; &nbsp; fatalError("Libc not supported on operating system")</div><div class="">&nbsp; &nbsp; #endif</div><div class="">&nbsp; &nbsp; ```</div><div class=""><br class=""></div><div class="">As new operating systems are added or become supported (such as Windows)</div><div class="">the standard imports can be added appropriately to this module.</div><div class=""><br class=""></div><div class="">## Source compatibility</div><div class=""><br class=""></div><div class="">There is no impact to source compatibility, since this proposal is additive.</div><div class="">Existing source code will work regardless of if this module is used or not.</div><div class="">However it improves source compatibility going forwards, since as new</div><div class="">operating systems are added this file will be updated, instead of the change</div><div class="">having to be made in multiple open-source projects.</div><div class=""><br class=""></div><div class="">## Effect on ABI stability</div><div class=""><br class=""></div><div class="">There is no impact to ABI compatibility, since this proposal is additive.</div><div class="">Existing source code will work regardless of if this module is used or not.</div><div class=""><br class=""></div><div class="">## Effect on API resilience</div><div class=""><br class=""></div><div class="">There is no impact to ABI resilience, since this proposal is additive.</div><div class="">Existing source code will work regardless of if this module is used or not.</div><div class=""><br class=""></div><div class="">## Alternatives considered</div><div class=""><br class=""></div><div class="">The first alternative is to do nothing. Existing Swift projects already</div><div class="">conditionally import these modules, or import a higher-level module (such</div><div class="">as `Foundation`) that performs the conditional import.</div><div class=""><br class=""></div><div class="">The second alternative is to export sub-modules of the modules. Clang</div><div class="">permits imports of sub-modules, so it could be possible to import only</div><div class="">`Darwin.POSIX` and `GlibC.POSIX`. However, in Swift, importing a sub-module</div><div class="">makes the whole module available anyway, so the difference between importing</div><div class="">a whole module versus a submodule is irrelevant.</div><div class=""><br class=""></div><div class=""><div class="">The third alternative is to explore creating standard functions (in Swift)</div><div class="">corresponding to POSIX functionality, but where the format of the return</div><div class="">results are known. This would require a per-operating system binding to</div><div class="">expose operating-system details such as the byte ordering of structures</div><div class="">as used in the various `getaddrinfo` calls. These may evolve out of future</div><div class="">evolution proposals and this does not conflict with those goals at this</div><div class="">stage. There are additional clean-ups that this could address, such as the</div><div class="">use of the (thread-local) `errno` which may not be reliably read from within</div><div class="">Swift. However, the (swift-evolution thread)[<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161003/027602.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161003/027602.html</a>]</div><div class="">calls this "the perfect being the enemy of the good". Instead of trying to</div><div class="">solve all of these problems, they should be handled by subsequent</div><div class="">proposals (such as (Johannes' proposal)[<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161031/028627.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161031/028627.html</a>]</div><div class="">regarding errno handling sent to swift-evolution previously).</div></div></div></body></html>