OS/Environment check in Swift

Hi,

We all know that we are lacking an environment check in Swift. It shouldn't be a important feature if we were only targeting Apple(macOS, iOS...) and Linux or if we are targeting only one Windows ABI. But our community are working hard to port swift to Windows targeting various ABIs. There are currently three main variants of Windows ABIs: MSVC, Cygwin and MinGW. Of course, their ABI's varies too. So when porting Swift to windows with targeting these ABIs and when writing swift code on windows, we need an environment check .

By using the `environment check` term we are talking about the mechanism that will provide us the information about the ABI that the swift compiler is targeting.

When porting stdlib and Foundation to windows, community members are using the method 'ad hoc -D flag'. But to me and to the community this method is not sufficient or a long term solution. Saleem Abdulrasool and Han Sangjin have pointed out this in following threads:

1. [swift-dev] [RFC] Finer grained OS checks

2. [swift-evolution] #if os(Windows) and MSVC/Cygwin Compatibility

But unfortunately the core team haven't succeeded to make or choose a solution. But as we are expecting a swift release, we should make a solution.

As Saleem pointed out that there are ABI problems in Linux also:

> This is not a problem strictly limited to Windows. It also appears in
> other OSes. As a concrete example, Linux has traditionally had the "gnu"
> environment (libc). However, there is also "uclibc" which is pretty
> common, and these days, "musl" as different targets.

So we have multiple environment(ABI?) in Linux also.

I have seen some core members want to know how other languages handles this issue like Chris Lattner wanted to know:

> I am not a windows guru (and haven’t used it for over a decade) but my understanding is that Cygwin is a different target (as in different target triple, different ABI, different environment) from MSVC and MinGW. If that is the case, it should be its own “arch” or “os”. MSVC and MinGW (again, AFAIK) use the same C ABI, and thus could be treated as the same target.

> I think it would be defensible to treat MSVC/MinGW as an os(Windows) but treat Cygwin as os(Cygwin).
>
> How do other languages handle this? What does dlang do, for example?
>
> -Chris

So I want to put some information how other languages handles this issue.

## D lang

On D, anyone can handle this by using `version()` block.


version(Cygwin)
{
     // Environment is Windows Cygwin

} else {

     // Not a Windows Cygwin environment

}

## Rust

On windows Rust supports two ABI's: MSVC and Mingw(gnu). On rust we can check the environment by:


#[cfg(target_env = "msvc")]

// MSVC environment

#[cfg(target_env = "gnu")]

// Mingw environment

## Environment check & Swift

Here I want to propose some conditionals:


environment(MSVC)

environment(CYGWIN)

environment(MUSL)

// or

target(MSVC)

target(MUSL)

// or

os(Windows, target: MSVC)

os(Linux, target: MUSL)

// or

os(Windows, environment: MSVC)

os(Linux, environment: MUSL)

We can discuss about this topic and submit a proposal when everyone is agreed to a decision. So lets start!

Thanks

Mominul