<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I agree that trying to completely unify low-level platforms is usually a mess. That said, I also don’t think accessing platform specific behaviour needs to involve completely throwing away the nice abstractions in Foundation. Wherever possible, we should provide platform-specific extensions to the types in Foundation. For instance, we could expose methods/inits that operate in terms of file descriptors on unix-y systems, and handle_t on windows.</div><div class=""><br class=""></div><div class="">But I also think there should be <i class="">some</i> opt-in to doing this, so that Foundation users can be confident they’re writing portable software by default. I don’t think imports should be the mechanism for this because this necessarily forces awkward divisions. I’m cautiously optimistic the feature flag system we need to build out for language evolution purposes will provide a good fit here. Opting into platform-specific behaviour is fairly similar to opting into experimental APIs.&nbsp;</div><div class=""><br class=""></div><div class="">(Note: I haven’t actually used Foundation much, so this may be inconsistent with its overarching design)</div><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 10, 2016, at 10:48 PM, Drew Crawford via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">


<title class=""></title>

<div class=""><div class="">&nbsp; &nbsp; grep -R "import Glibc" ~/Code --include "*.swift" | wc -l<br class=""></div>
<div class="">&nbsp; &nbsp; 297</div>
<div class=""><br class=""></div>
<div class="">As someone who might be characterized as suffering from the problem this proposal purports to solve, I am not convinced.<br class=""></div>
<div class=""><br class=""></div>
<div class="">The primary problem here is that "libc" is a misnomer. &nbsp;Did you mean musl, dietlibc, or glibc? &nbsp;Did you mean "whatever libc my distro likes?" &nbsp;Swift in practice only supports one per platform, but that is a bug not a feature, and that bug should not be standardized. &nbsp;We could try to invent some syntax to specify one but now we are back with the current system again.<br class=""></div>
<div class=""><br class=""></div>
<div class="">The other problem is that in all my usages, "import Glibc" is not a real problem I face. &nbsp;The real problems are that "the libcs <i class="">plural</i>" are *just different*. &nbsp;Darwin has timeval64, glibc does not, and you'd better check your arch and pick the right one, only on one platform. &nbsp;SO_REUSEADDR has one type in Brand X and another type in Brand Y. &nbsp;Don't even get me *started* on poll, EREs, or half a dozen other behavioral variations. &nbsp;<br class=""></div>
<div class=""><br class=""></div>
<div class="">Taking two different libraries and pretending they are the same is not the solution, it's the disease. &nbsp;The way out of this swamp for most developers is to use a real Swift library, the same damn Swift library, on all platforms (sadly, Foundation today does not meet this requirement). &nbsp;The way out of this swamp for crazy people like me who must write to the metal is to actually write to the metal, to the particular libc being targeted, not to a hypothetical platonic ideal libc which does not exist. &nbsp;<br class=""></div>
<div class=""><br class=""></div>
<div class="">I realize that four lines at the top of my files is a *visible* annoyance, but fixing it just promotes it to an invisible one.&nbsp;<br class=""></div>
<div class=""><br class=""></div>
<div class="">Drew</div>
<div class=""><br class=""></div>
<div id="sig56767961" class=""><div class="signature">--<br class=""></div>
<div class="signature">&nbsp; Drew Crawford<br class=""></div>
<div class="signature">&nbsp; <a href="mailto:drew@sealedabstract.com" class="">drew@sealedabstract.com</a><br class=""></div>
<div class="signature"><br class=""></div>
</div>
<div class=""><br class=""></div>
<div class=""><br class=""></div>
<div class="">On Wed, Nov 9, 2016, at 12:58 PM, Alex Blewitt via swift-evolution wrote:<br class=""></div>
<blockquote type="cite" class=""><div class="">Although out of scope for phase 1, something that keeps cropping up in a variety of Linux/Darwin Swift scripts is the conditional inclusion of Darwin or GlibC per platform. The last point was an observation that creating a 'nice' wrapper for LibC or a cleaned up POSIX API is a non-goal:<br class=""></div>
<div class=""><br class=""></div>
<div class=""><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><br class=""></div>
<div class=""><br class=""></div>
<div class=""><blockquote type="cite" class=""><pre style="white-space:pre-wrap;background-color:rgb(255, 255, 255);" class="">I think it makes sense to have a cross platform “libc” which is an alias for darwin, glibc, or whatever, and just leave it at that.

Other proposals for a “POSIX” module have gotten bogged down because inevitably the idea comes up to make the resultant API nicer in various ways: rename creat, handle errno more nicely, make use of multiple return values, … etc.  The problem with this approach is that we don’t *want* people using these layer of APIs, we want higher level Foundation-like APIs to be used.

...<i class="">
</i>
I think we should formally decide that a “nice” wrapper for libc is a non-goal.  There is too much that doesn’t make sense to wrap at this level - the only Swift code that should be using this is the implementation of higher level API, and such extremely narrow cases that we can live with them having to handle the problems of dealing with the raw APIs directly.

-Chris<br class=""></pre></blockquote><div class=""><br class=""></div>
</div>
<div class="">I have created a draft for a proposal to create such a module. Comments are welcome.<br class=""></div>
<div class=""><br class=""></div>
<div class="">Alex<br class=""></div>
<div class=""><br class=""></div>
<div class="">---<br class=""></div>
<div class=""><br class=""></div>
<div class=""># Libc module for Swift<br class=""></div>
<div class=""><br class=""></div>
<div class="">* Proposal: [SE-NNNN](NNNN-filename.md)<br class=""></div>
<div class="">* Authors: [Alex Blewitt](<a href="https://github.com/alblue" class="">https://github.com/alblue</a>)<br class=""></div>
<div class="">* Review Manager: TBD<br class=""></div>
<div class="">* Status: **Under discussion**<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Introduction<br class=""></div>
<div class=""><br class=""></div>
<div class="">When running on Darwin, the base module is called `Darwin`. When running<br class=""></div>
<div class="">on Linux or other operating systems, it's called `GlibC`.&nbsp;<br class=""></div>
<div class=""><br class=""></div>
<div class="">This repeatedly leads to code such as:<br class=""></div>
<div class=""><br class=""></div>
<div class="">&nbsp; &nbsp; ````<br class=""></div>
<div class="">&nbsp; &nbsp; #if os(Linux)<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; import Glibc<br class=""></div>
<div class="">&nbsp; &nbsp; #else<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; import Darwin<br class=""></div>
<div class="">&nbsp; &nbsp; #endif<br class=""></div>
<div class="">&nbsp; &nbsp; ```<br class=""></div>
<div class=""><br class=""></div>
<div class="">As the set of operating systems evolve, one of these conditional imports<br class=""></div>
<div class="">needs to be updated. Instead of repeating this, make it available via a<br class=""></div>
<div class="">standard `Libc` module in the base Swift library.<br class=""></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>)<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Motivation<br class=""></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>)<br class=""></div>
<div class="">that Swift currently runs on can be divided into two; Darwin and XNU based systems<br class=""></div>
<div class="">(macOS, iOS, watchOS, tvOS), Windows, and Unix based systems<br class=""></div>
<div class="">(Linux, FreeBSD, Android, PS4).&nbsp;<br class=""></div>
<div class=""><br class=""></div>
<div class="">The base module on Darwin is called `Darwin`, while on Linux and<br class=""></div>
<div class="">other Unix systems the base module is called `Glibc`. The base<br class=""></div>
<div class="">module is typically conditionally included when working at a lower layer<br class=""></div>
<div class="">than Foundation (which has the same detail involved in importing the<br class=""></div>
<div class="">base module).<br class=""></div>
<div class=""><br class=""></div>
<div class="">As a result, conditionally importing the right version typically uses<br class=""></div>
<div class="">a conditional test based on the operating system, and the same code is<br class=""></div>
<div class="">seen in a number of different modules, both internal to Swift and external:<br class=""></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>)<br class=""></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>)<br class=""></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>)<br class=""></div>
<div class="">* [Vapor's HTTP Server](<a href="https://github.com/vapor/engine/blob/1f95094ee470408309e98dd56b2251210d6a2a3d/Sources/HTTP/Models/Server/HTTP%2BServer.swift#L1-L5" class="">https://github.com/vapor/engine/blob/1f95094ee470408309e98dd56b2251210d6a2a3d/Sources/HTTP/Models/Server/HTTP%2BServer.swift#L1-L5</a>)<br class=""></div>
<div class=""><br class=""></div>
<div class="">Some have already created a `Libc` module that effectively does what this<br class=""></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>)<br class=""></div>
<div class=""><br class=""></div>
<div class="">&nbsp; &nbsp; ```<br class=""></div>
<div class="">&nbsp; &nbsp; #if os(Linux)<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; @_exported import Glibc<br class=""></div>
<div class="">&nbsp; &nbsp; #else<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; @_exported import Darwin.C<br class=""></div>
<div class="">&nbsp; &nbsp; #endif<br class=""></div>
<div class="">&nbsp; &nbsp; ```<br class=""></div>
<div class=""><br class=""></div>
<div class="">Each of these examples has subtly different behaviour; for example,<br class=""></div>
<div class="">whether or not the os tests only include Linux (and then fail over to<br class=""></div>
<div class="">Darwin), or whether they contain other Unices such as FreeBSD and Android.<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Proposed solution<br class=""></div>
<div class=""><br class=""></div>
<div class="">The solution is to formalise these patterns in the base Swift library<br class=""></div>
<div class="">and present a `Libc` module that conditionally imports `Glibc` or `Darwin`<br class=""></div>
<div class="">based on the correct platform. Additional operating systems can be added<br class=""></div>
<div class="">and kept up to date with the list of supported operating system conditionals<br class=""></div>
<div class="">and including a failure message when an unknown operating system is detected.<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Detailed design<br class=""></div>
<div class=""><br class=""></div>
<div class="">This will add a `Libc` module for the standard library that re-exports<br class=""></div>
<div class="">the correct import depending on the operating system:<br class=""></div>
<div class=""><br class=""></div>
<div class="">&nbsp; &nbsp; ```<br class=""></div>
<div class="">&nbsp; &nbsp; #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; @_exported import Darwin<br class=""></div>
<div class="">&nbsp; &nbsp; #elseif os(Linux) || os(FreeBSD) || os(Android) || os(PS4)<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; @_exported import Glibc<br class=""></div>
<div class="">&nbsp; &nbsp; #else<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; fatalError("Libc not supported on operating system")<br class=""></div>
<div class="">&nbsp; &nbsp; #endif<br class=""></div>
<div class="">&nbsp; &nbsp; ```<br class=""></div>
<div class=""><br class=""></div>
<div class="">As new operating systems are added or become supported (such as Windows)<br class=""></div>
<div class="">the standard imports can be added appropriately to this module.<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Source compatibility<br class=""></div>
<div class=""><br class=""></div>
<div class="">There is no impact to source compatibility, since this proposal is additive.<br class=""></div>
<div class="">Existing source code will work regardless of if this module is used or not.<br class=""></div>
<div class="">However it improves source compatibility going forwards, since as new<br class=""></div>
<div class="">operating systems are added this file will be updated, instead of the change<br class=""></div>
<div class="">having to be made in multiple open-source projects.<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Effect on ABI stability<br class=""></div>
<div class=""><br class=""></div>
<div class="">There is no impact to ABI compatibility, since this proposal is additive.<br class=""></div>
<div class="">Existing source code will work regardless of if this module is used or not.<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Effect on API resilience<br class=""></div>
<div class=""><br class=""></div>
<div class="">There is no impact to ABI resilience, since this proposal is additive.<br class=""></div>
<div class="">Existing source code will work regardless of if this module is used or not.<br class=""></div>
<div class=""><br class=""></div>
<div class="">## Alternatives considered<br class=""></div>
<div class=""><br class=""></div>
<div class="">The first alternative is to do nothing. Existing Swift projects already<br class=""></div>
<div class="">conditionally import these modules, or import a higher-level module (such<br class=""></div>
<div class="">as `Foundation`) that performs the conditional import.<br class=""></div>
<div class=""><br class=""></div>
<div class="">The second alternative is to export sub-modules of the modules. Clang<br class=""></div>
<div class="">permits imports of sub-modules, so it could be possible to import only<br class=""></div>
<div class="">`Darwin.POSIX` and `GlibC.POSIX`. However, in Swift, importing a sub-module<br class=""></div>
<div class="">makes the whole module available anyway, so the difference between importing<br class=""></div>
<div class="">a whole module versus a submodule is irrelevant.<br class=""></div>
<div class=""><br class=""></div>
<div class="">The third alternative is to explore creating standard functions (in Swift)<br class=""></div>
<div class="">corresponding to POSIX functionality, but where the format of the return<br class=""></div>
<div class="">results are known. This would require a per-operating system binding to<br class=""></div>
<div class="">expose operating-system details such as the byte ordering of structures<br class=""></div>
<div class="">as used in the various `getaddrinfo` calls. These may evolve out of future<br class=""></div>
<div class="">evolution proposals and this does not conflict with those goals at this<br class=""></div>
<div class="">stage. There are additional clean-ups that this could address, such as the<br class=""></div>
<div class="">use of the (thread-local) `errno` which may not be reliably read from within<br class=""></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>]<br class=""></div>
<div class="">calls this "the perfect being the enemy of the good". Instead of trying to<br class=""></div>
<div class="">solve all of these problems, they should be handled by subsequent<br class=""></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>]<br class=""></div>
<div class="">regarding errno handling sent to swift-evolution previously).<br class=""></div>
<div class=""><u class="">_______________________________________________</u><br class=""></div>
<div class="">swift-evolution mailing list<br class=""></div>
<div class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""></div>
<div class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div>
</blockquote><div class=""><br class=""></div>
</div>

_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>