OpenVMS isn't in the supported list of Swift packages, so comparing it to that is pointless.
https://github.com/apple/swift/blob/c3b7709a7c4789f1ad7249d357f69509fb8be731/lib/Basic/LangOptions.cpp#L26-L36 static const StringRef SupportedConditionalCompilationOSs[] = { "OSX", "tvOS", "watchOS", "iOS", "Linux", "FreeBSD", "Windows", "Android", "PS4", }; Look, this code is already battle tested in Swift. It's even used in the test case for the interpreter: https://github.com/apple/swift/blob/c3b7709a7c4789f1ad7249d357f69509fb8be731/test/Interpreter/SDK/libc.swift#L10-L14 <https://github.com/apple/swift/blob/c3b7709a7c4789f1ad7249d357f69509fb8be731/test/Interpreter/SDK/libc.swift#L10-L14> #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) import Darwin #elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) import Glibc #endif Alex > On 15 Nov 2016, at 19:51, Drew Crawford <[email protected]> wrote: > > Thanks for using specific examples, as they are illustrative. > >> Or, as used in >> https://github.com/drewcrawford/Caroline/blob/edd8aefef44717ecfa03c629100baf095fab983a/caroline-static-tool/main.swift >> >> <https://github.com/drewcrawford/Caroline/blob/edd8aefef44717ecfa03c629100baf095fab983a/caroline-static-tool/main.swift> >> to just get access to the exit() function, which is the same across all >> platforms. > > > exit is an interesting case. Believe it or not, it is *not* portable, as > used here. The C standard defines two constants for its parameter: > EXIT_SUCCESS (defined to be zero) and EXIT_FAILURE (undefined). You can pass > other values (trivia time: only values less than 0377, because the high bits > of this integer are reserved on some platforms), but the "fail-iarity" or > "successiness" of values other than the defined two are not specified and may > take on different meanings on different platforms. C programmers commonly > pick a nonzero value to indicate failure (as I did here) – sometimes multiple > distinct values to indicate different kinds of failure – but this is actually > non-portable. > > The reason I am being pedantic here is because it demonstrates a broader > point: people do not actually write portable code; they target either their > current platform or some vague amalgamation of 2-3 platforms in their > immediate vicinity. All the platforms I cared about do something sane with > exit(1) so it's "portable enough". But "portable enough" isn't portable. > >> In any case, the four lines at the top of your files are almost certainly >> inconsistent on other platforms; for example, do you test for freebsd? Or >> ps4? > > This is a feature, not a bug. We *like* compiler errors because they give us > early warning we got something wrong. > > I *want* the compiler to stop me when compiling this for OpenVMS. When I > wrote this code, I had only Darwin/Glibc in mind, and on that basis, I used > exit(1). The working assumption is now violated, and the compiler is correct > to remind me about it. I don't know, and would need to go find out, what > kind of exit is sensible for VMS. Or to move to EXIT_FAILURE like a language > lawyer. > > But the compile error itself is not a silly annoyance that I would like to > "solve" by blindly putting more libcs in the list etc. This is a guard rail > where I indicated the platforms I had in mind when writing this code, and > when I wake up one morning in a drunken stupor and try to do something else, > we fire a warning shot. > > It's a safety feature, like force-unwrap. If you're sure it won't blow up, > you can put an exclamation mark in there and shut up the compiler. If you're > sure it's portable to bsd, add bsd to the list and shut up the compiler. But > the resolution to this compile error is not to import more libcs. The > resolution is to *consider carefully if that is a good idea*. > > The assumption embedded in the proposal is that of course we want the program > to compile, and the question is merely to calculate the set of import > statements that will achieve compilation, for which the proposal offers an > algorithm. My argument is that actually we do not want the program to > compile unless we are reasonably sure it will work as intended, and the > question is what syntax allows the author to reasonably encode their > assumptions so that when they are violated we provide a moment of quiet > reflection to consider e.g. if exit(1) is sensible on VMS. > > The existing system is imperfect (and very ugly) but does a surprisingly good > job in this dimension. > >> It also doesn't seem to support some of the other platforms that might be >> desirable in a test framework, such as iOS, watchOS or tvOS. > > I do support iOS (not in this component – it's a command-line tool, so the > omission of iOS in this file is deliberate, and the compatibility issues go > far beyond exit). I don't yet support watchOS or tvOS because I don't have > CI for those platforms yet and in my view supporting a platform is more than > adjusting an import statement and wondering if it will compile. > > So in summary: > > 1. I would not use this feature in the cited examples > > 2. I would prefer it if others did not use this feature. When I see "import > Glibc" at the top of a file I know what I am signing up for. When I see > "import libc" for all I know the developer used Windows. > > Finally, this is more of a detail, but I still do not understand how this > would be implemented for a Linux platform without Glibc, such as Arch. The > current proposal has > > > >> #if os(Linux) >> >> @_exported import Glibc >> > > which is obviously not going to compile on Arch. So if the goal is to have > syntax that is portable the current proposal does not do it. > > I do believe there is some room for a more moderate reform on the libc > problem. For example instead of the traditional ifdefs, we could have > >> import? Glibc >> >> import? Darwin >> > > Where the "import?" keyword imports the module if available or otherwise has > no effect. > > This preserves the majority of desireable properties discussed above (clearly > indicates the intended libcs, provides guard rails similar to the present > regime) while being significantly shorter than the present regime. It also > contemplates problems that the current proposal does not, such as Arch (we > can continue to list libcs until we find one, and Swift already has rules for > resolving multiple imports), and it is more broadly applicable to other kinds > of import problems than libc imports narrowly. > > One problem with the import? idea is that it glosses e.g. watchOS/tvOS/macOS > as "Darwin" when that is not strictly true (posix_spawn for example) but it's > at least a far more sensible unification than VMS/Darwin. We do have a clear > path to check Darwin portability in the compiler (e.g. require > @availability(macOS) for posix_spawn) while no similar path exists to check > Darwin/VMS portability. So I think doing something moderate is at least > plausible. > > Still, it may be a solution in search of a problem. If you are writing > against something as badly fractured as POSIX, it should feel like it, and > even a small unification may be a step too far. > > Of course, the real solution to writing portable code is to target a portable > standard, such as Foundation or some alternative high-level library. > On November 15, 2016 at 10:27:14 AM, Alex Blewitt ([email protected] > <mailto:[email protected]>) wrote: > >> >>> On 11 Nov 2016, at 03:48, Drew Crawford <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> grep -R "import Glibc" ~/Code --include "*.swift" | wc -l >>> 297 >>> >>> As someone who might be characterized as suffering from the problem this >>> proposal purports to solve, I am not convinced. >>> >>> The primary problem here is that "libc" is a misnomer. Did you mean musl, >>> dietlibc, or glibc? Did you mean "whatever libc my distro likes?" Swift >>> in practice only supports one per platform, but that is a bug not a >>> feature, and that bug should not be standardized. We could try to invent >>> some syntax to specify one but now we are back with the current system >>> again. >> >> We're at the current system to start off with, though. When you do "import >> Darwin" or "import GlibC" you're getting whatever the platform has, >> regardless of what you call it. You could call it something else, like >> "Platform" or "Base" but it doesn't change the suggestion itself. >> >>> The other problem is that in all my usages, "import Glibc" is not a real >>> problem I face. The real problems are that "the libcs plural" are *just >>> different*. Darwin has timeval64, glibc does not, and you'd better check >>> your arch and pick the right one, only on one platform. SO_REUSEADDR has >>> one type in Brand X and another type in Brand Y. Don't even get me >>> *started* on poll, EREs, or half a dozen other behavioral variations. >> >> Yes, these are issues. Some of them will be worked out with the swift server >> workgroup, or at least standardising Socket as a type which abstracts the >> platform away. But we're at that position at the moment, whether or not >> there's a standard module to represent Darwin/Glibc. >> >>> Taking two different libraries and pretending they are the same is not the >>> solution, it's the disease. 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). 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. >>> >>> 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. >> >> Not necessarily, it can be a starting point to fix some of the other >> problems. In any case, the four lines at the top of your files are almost >> certainly inconsistent on other platforms; for example, do you test for >> freebsd? Or ps4? >> >> https://github.com/drewcrawford/Caroline/blob/26cd0d71e57a62fac6258e4e13dfd6849a1945c6/caroline-static-tool/FileUtils.swift >> >> <https://github.com/drewcrawford/Caroline/blob/26cd0d71e57a62fac6258e4e13dfd6849a1945c6/caroline-static-tool/FileUtils.swift> >> >> >> >> >> #if >> os(OSX) >> >> import >> Darwin >> >> #elseif >> os(Linux) >> >> import >> Glibc >> >> #endif >> >> So your test framework doesn't work on FreeBSD by default. Yet they've still >> got the same 'write' method. It also doesn't seem to support some of the >> other platforms that might be desirable in a test framework, such as iOS, >> watchOS or tvOS. You'll just get silent errors on those when it's used on >> those platforms. And as new platforms get added, your code will slowly drift >> further away from supporting everything to supporting a few known values. >> >> Now granted, some of these may have yet more incompatible versions for >> 'write' which needs handling specifically. That's bad, and it should be >> something that can be worked on. But most of the other functions (like >> 'close') don't need handling specifically. Or, as used in >> https://github.com/drewcrawford/Caroline/blob/edd8aefef44717ecfa03c629100baf095fab983a/caroline-static-tool/main.swift >> >> <https://github.com/drewcrawford/Caroline/blob/edd8aefef44717ecfa03c629100baf095fab983a/caroline-static-tool/main.swift> >> to just get access to the exit() function, which is the same across all >> platforms. >> >> Other proposals - such as Johannes' treatment of how to handle errno - will >> help work around these problems. Perhaps we end up with a generic write >> function that wraps the platform specific one to abstract that away as well, >> which reduces these issues one by one. >> >> Alex
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
