The idea is basically just adding one #if os directive but all inclusive for Darwin platforms. Currently, to check for Darwin platforms, you have to type out a lengthy statement:
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
// Darwin code
// Non Darwin code
You will see stuff like that very frequently in Apple's own Swift code, the issue is that this is not future-proof for any future Darwin platforms, and quite lengthy to type out & read, which is why I believe this would be better:
// Darwin code
// Non Darwin code
I've also considered a @available support, however, honestly, that's not realistic as most developers don't know the Darwin version number for specific iOS/macOS/tvOS/watchOS releases.
As mentioned above in this post, I've made a working implementation of this, and have tested successfully with CI and locally.
That's one of the reasons I made that impl, I've seen people do stuff such as
Which, I don't believe it would be good practice to distinguish Apple platforms from non-Apple platforms using those methods, hopefully #if os(Darwin) changes that if it does pass.
I think proper #if support would be nicer, but I am a bit torn with this platform specific conditionals that seem to be in vogue - I was raised with conditionals on features ('have pthreads', 'have kqueue', 'have epoll' etc) - that might be different for the same platform depending on version, but that is a different aspect...)
We’ve generally tried to make sure that #if os(osName) options are mutually exclusive—that is, that there’s only one osName that will be true at a time—to avoid the confusing tangle of target defines that we see in Objective-C, where for instance TARGET_OS_MAC is true on iOS. I’m not sure if we’ve actually held the line on that, though.
Having said that, I think it’d be wonderful to have this functionality—just perhaps not in os(…).
Hmm, I'm torn on this. On the one hand, this makes sense for the Darwin based platforms, and also would fix up the os(Android) || os(Linux) cases. On the other hand, what about baremetal platforms (i.e. no kernel) and platforms such as cygwin? Would it make sense to return "NT" as the kernel even though the user may expect Linux? Another thing to consider is something like personalities.
As a crappy compromise, something like #if vendor(Apple) could work to group together the Apple OSes perhaps?
If this is a tangible goal which is really that important, we could instead do #if platform and provide options to check for Darwin, Unix, or BSD in general from there, though that may confuse people due to the wording being similar to #if os.
I think that this could work, but I do worry about the complexity. I may want to build the code for BSD to run on Linux with the BSD personality. That is to say, I expect most users would not expect the following behavior:
#if os(Linux) && kernel(BSD)
// this is valid
I think that platform works better than kernel (cygwin and MinGW are more platforms than kernels or OSes, it also covers WASI well IMO). I'm not sure I understand the "Unix" category. Would that be SCO Unix? SystemV Unix? All the Unix derivates?
That’d be up for discussion if such an idea does get far. With that being said, I’m still against not using #if os for Darwin, I do get a goal was to keep #if os options mutually exclusive however #if os is already familiar to most Swift programmers, especially ones writing cross platform code.
I actually think this is correct. If you're trying to guard import Darwin and uses of the Darwin module, then isn't canImport(Darwin) expressing precisely the thing you want?
What exactly is the API surface of the os(Darwin) SDK? Can I assume only that it includes the Darwin module? If so, is it not a synonym for canImport(Darwin)?
Or does os(Darwin) also imply the availability of other Apple frameworks, such as SwiftUI? What about frameworks that are not available on every Apple platform, such as AppKit and UIKit, or the recently-announced ClockKit?
Correct me if I'm wrong, but I don't believe Apple has ever defined a set of frameworks that all Darwin-family platforms will support. Pretty much the only thing that seems reasonable to assume is that import Darwin will work on a Darwin platform (kind of, by definition). IMO, it's up to Apple's platform team whether or not they want to introduce an expanded concept of a "Darwin OS" which includes more than just that one module, and which other modules os(Darwin) should include.
On a related note, hopefully one day we'll add some kind of CStdlib module, which will cut down the boilerplate for cross-platform code. So you could just import CStdlib, and handle the platform differences as and where they occur.
Is it possible that is just a style choice? That it isn't due to a functionality gap in canImport?
If canImport really is deficient in some way, it would be nice to know more about that. At least for me, I write plenty of cross-platform code, and canImport(Darwin) seems to be working fine.
I'd be interested to know which limitations developers are encountering. I'm not sure how we can judge whether os(Darwin) would be better, without learning more about why developers aren't using the existing solution. Currently it seems we're just guessing at why developers happened to write a thing in a certain way.