[Draft] Unify "import Darwin/Glibc" to simply "Libc"


(Brian Gesiak) #1

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in
libc (`fputs`, `stderr`, etc.) must all write the same five lines of
boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print
"Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols
`fputs` and `stderr`. Five lines may not be much, but these come with
significant drawbacks:

- They must be written in each source file that relies on libc, which is
tedious.
- It is subject to frequent change. As Swift is ported to more platforms,
that initial check must change to `#if os(Linux) || os(FreeBSD) ||
os(Windows) || os(Android)`, and so on. End users of Swift may not be
actively involved in its development, and so may be surprised when the
latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write
cross-platform code--as opposed to simply writing Swift and have it work on
other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for
the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the following:

    import Libc

This would import whichever libc implementation Swift was compiled with.
For Ubuntu Linux releases, this would be Glibc. For OS X releases, this
would be Darwin. For Android (coming soon in
https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates them
from the rapid expansion of platforms on which Swift is able to be executed.

This idea is not novel: the Swift package manager already defines a "libc"
package that is essentially the boilerplate `os()` check above:
https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift
.

However, rather than determining which libc implementation to use at
runtime (like SwiftPM does above), I propose we allow the Swift stdlib to
be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in
the Swift build scripts and CMake modules. Similar to how those scripts
export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this
proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that
could automatically convert conditional imports of Darwin/Glibc to the new
`import Libc`.

We must also devise a strategy for the transient rollout period, when Swift
defines a Libc module, but we don't have an OS X SDK that uses that name in
the bundled module.map. We can add a compiler hack for that, to
transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons
stated in "Motivation". To reiterate: the current system forces users to go
out of their way to write cross-platform Swift code, as opposed to writing
code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and the
C standard library. We could export *two* modules. However I believe this
introduces additional overhead for users, with only the marginal benefit of
clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would
automatically get preprocessed to the five lines of boilerplate shown
above. This has several downsides, most notably the added complexity to
Swift syntax.

On point #2 (what to name it), I have spoken with people that raised
concerns over the name "Libc":

Another concern is about compatibility with the C++ modules proposal. If

we want this module name to mean something, it should agree with the C++
spec.

I don't know which name was chosen in the C++ spec. I've been searching
WG21 papers with no luck--any advice on how to find out would be
appreciated!

Aside from the above point, some concrete alternatives for point #2 (what
to name it) include:

- `import System`: This is better suited to the idea that the module
contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (
https://www.youtube.com/watch?v=PEgk2v6KntY)

···

---

Thanks for taking the time to read this proposal draft! Feedback (on its
contents or on how to proceed with the evolution proposal process) is
greatly appreciated.

- Brian Gesiak


(Joe Groff) #2

How much would `Libc` include? The standard C library? POSIX? Does it provide any abstraction over platform-specific differences? In my mind, the common 'Libc' and/or 'POSIX' module would provide a reasonably consistent interface to libc or POSIX, and you'd still have library-specific modules for library-specific APIs.

-Joe

···

On Mar 8, 2016, at 11:13 AM, Brian Gesiak via swift-evolution <swift-evolution@swift.org> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in libc (`fputs`, `stderr`, etc.) must all write the same five lines of boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print "Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols `fputs` and `stderr`. Five lines may not be much, but these come with significant drawbacks:

- They must be written in each source file that relies on libc, which is tedious.
- It is subject to frequent change. As Swift is ported to more platforms, that initial check must change to `#if os(Linux) || os(FreeBSD) || os(Windows) || os(Android)`, and so on. End users of Swift may not be actively involved in its development, and so may be surprised when the latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write cross-platform code--as opposed to simply writing Swift and have it work on other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the following:

    import Libc

This would import whichever libc implementation Swift was compiled with. For Ubuntu Linux releases, this would be Glibc. For OS X releases, this would be Darwin. For Android (coming soon in https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates them from the rapid expansion of platforms on which Swift is able to be executed.

This idea is not novel: the Swift package manager already defines a "libc" package that is essentially the boilerplate `os()` check above: https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift.

However, rather than determining which libc implementation to use at runtime (like SwiftPM does above), I propose we allow the Swift stdlib to be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in the Swift build scripts and CMake modules. Similar to how those scripts export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that could automatically convert conditional imports of Darwin/Glibc to the new `import Libc`.

We must also devise a strategy for the transient rollout period, when Swift defines a Libc module, but we don't have an OS X SDK that uses that name in the bundled module.map. We can add a compiler hack for that, to transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons stated in "Motivation". To reiterate: the current system forces users to go out of their way to write cross-platform Swift code, as opposed to writing code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and the C standard library. We could export *two* modules. However I believe this introduces additional overhead for users, with only the marginal benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would automatically get preprocessed to the five lines of boilerplate shown above. This has several downsides, most notably the added complexity to Swift syntax.

On point #2 (what to name it), I have spoken with people that raised concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal. If we want this module name to mean something, it should agree with the C++ spec.

I don't know which name was chosen in the C++ spec. I've been searching WG21 papers with no luck--any advice on how to find out would be appreciated!

Aside from the above point, some concrete alternatives for point #2 (what to name it) include:

- `import System`: This is better suited to the idea that the module contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (https://www.youtube.com/watch?v=PEgk2v6KntY <https://www.youtube.com/watch?v=PEgk2v6KntY>)

---

Thanks for taking the time to read this proposal draft! Feedback (on its contents or on how to proceed with the evolution proposal process) is greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(William Dillon) #3

That would make sense to me, too. I’m not sure where Brian would draw the line, but as a user, I would expect Libc to include things like stdlib, stdio, and stdint.

- Will

···

On Mar 8, 2016, at 11:21 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

How much would `Libc` include? The standard C library? POSIX? Does it provide any abstraction over platform-specific differences? In my mind, the common 'Libc' and/or 'POSIX' module would provide a reasonably consistent interface to libc or POSIX, and you'd still have library-specific modules for library-specific APIs.


(Joe Groff) #4

This would be problematic for non-POSIX platforms, like Windows. (iOS and Android are also limited in POSIX-ness in various ways.)

-Joe

···

On Mar 8, 2016, at 11:33 AM, Brian Pratt via swift-evolution <swift-evolution@swift.org> wrote:

I'm definitely a big +1 on this -- and pretty much any other suggestion that makes Swift code more portable and sets up a simple interface so that other platforms can be supported without the addition of more code.

A few thoughts to add:
- there are differences (minor, but still) between Glibc and Darwin. Those should be either unified (if possible) or re-arranged so that the unified library shares unified functionality and then each separate one can have its own set of caveats.

- I like `import System` myself, for the reasons you mentioned (conveys LibC+POSIX combo)


#5

I'm definitely a big +1 on this -- and pretty much any other suggestion
that makes Swift code more portable and sets up a simple interface so that
other platforms can be supported without the addition of more code.

A few thoughts to add:
- there are differences (minor, but still) between Glibc and Darwin. Those
should be either unified (if possible) or re-arranged so that the unified
library shares unified functionality and then each separate one can have
its own set of caveats.

- I like `import System` myself, for the reasons you mentioned (conveys
LibC+POSIX combo)

- down the line, what are thoughts on getting a more Swift-friendly libC
API? (I know Foundation plays this role already, but it'd be nice to have a
nice API for system calls without having to worry about maintaining
interface with the more-proprietary CoreFoundation)

···

On Tue, Mar 8, 2016 at 1:13 PM, Brian Gesiak via swift-evolution < swift-evolution@swift.org> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in
libc (`fputs`, `stderr`, etc.) must all write the same five lines of
boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print
"Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols
`fputs` and `stderr`. Five lines may not be much, but these come with
significant drawbacks:

- They must be written in each source file that relies on libc, which is
tedious.
- It is subject to frequent change. As Swift is ported to more platforms,
that initial check must change to `#if os(Linux) || os(FreeBSD) ||
os(Windows) || os(Android)`, and so on. End users of Swift may not be
actively involved in its development, and so may be surprised when the
latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write
cross-platform code--as opposed to simply writing Swift and have it work on
other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for
the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the
following:

    import Libc

This would import whichever libc implementation Swift was compiled with.
For Ubuntu Linux releases, this would be Glibc. For OS X releases, this
would be Darwin. For Android (coming soon in
https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates
them from the rapid expansion of platforms on which Swift is able to be
executed.

This idea is not novel: the Swift package manager already defines a "libc"
package that is essentially the boilerplate `os()` check above:
https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift
.

However, rather than determining which libc implementation to use at
runtime (like SwiftPM does above), I propose we allow the Swift stdlib to
be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in
the Swift build scripts and CMake modules. Similar to how those scripts
export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this
proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that
could automatically convert conditional imports of Darwin/Glibc to the new
`import Libc`.

We must also devise a strategy for the transient rollout period, when
Swift defines a Libc module, but we don't have an OS X SDK that uses that
name in the bundled module.map. We can add a compiler hack for that, to
transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons
stated in "Motivation". To reiterate: the current system forces users to go
out of their way to write cross-platform Swift code, as opposed to writing
code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and
the C standard library. We could export *two* modules. However I believe
this introduces additional overhead for users, with only the marginal
benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would
automatically get preprocessed to the five lines of boilerplate shown
above. This has several downsides, most notably the added complexity to
Swift syntax.

On point #2 (what to name it), I have spoken with people that raised
concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal. If
we want this module name to mean something, it should agree with the C++
spec.

I don't know which name was chosen in the C++ spec. I've been searching
WG21 papers with no luck--any advice on how to find out would be
appreciated!

Aside from the above point, some concrete alternatives for point #2 (what
to name it) include:

- `import System`: This is better suited to the idea that the module
contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (
https://www.youtube.com/watch?v=PEgk2v6KntY)

---

Thanks for taking the time to read this proposal draft! Feedback (on its
contents or on how to proceed with the evolution proposal process) is
greatly appreciated.

- Brian Gesiak

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


#6

This would be problematic for non-POSIX platforms, like Windows. (iOS and

Android are also limited in POSIX-ness in various ways.)

Definitely -- that's part of the reason I asked about the idea of creating
some sort of abstraction at a higher-level than libc (and a lower one than
Foundation), because it seems like it would enable a bit more flexibility
on the back-end.

···

On Tue, Mar 8, 2016 at 1:35 PM, Joe Groff <jgroff@apple.com> wrote:

> On Mar 8, 2016, at 11:33 AM, Brian Pratt via swift-evolution < > swift-evolution@swift.org> wrote:
>
> I'm definitely a big +1 on this -- and pretty much any other suggestion
that makes Swift code more portable and sets up a simple interface so that
other platforms can be supported without the addition of more code.
>
> A few thoughts to add:
> - there are differences (minor, but still) between Glibc and Darwin.
Those should be either unified (if possible) or re-arranged so that the
unified library shares unified functionality and then each separate one can
have its own set of caveats.
>
> - I like `import System` myself, for the reasons you mentioned (conveys
LibC+POSIX combo)

This would be problematic for non-POSIX platforms, like Windows. (iOS and
Android are also limited in POSIX-ness in various ways.)

-Joe


(Jordan Rose) #7

One of the reasons we haven't picked this particular name is if the C or C++ committees ever adopted modules. Given that they just got punted from C++17, though, maybe that shouldn't hold us back.

Jordan

···

On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution <swift-evolution@swift.org> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in libc (`fputs`, `stderr`, etc.) must all write the same five lines of boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print "Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols `fputs` and `stderr`. Five lines may not be much, but these come with significant drawbacks:

- They must be written in each source file that relies on libc, which is tedious.
- It is subject to frequent change. As Swift is ported to more platforms, that initial check must change to `#if os(Linux) || os(FreeBSD) || os(Windows) || os(Android)`, and so on. End users of Swift may not be actively involved in its development, and so may be surprised when the latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write cross-platform code--as opposed to simply writing Swift and have it work on other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the following:

    import Libc

This would import whichever libc implementation Swift was compiled with. For Ubuntu Linux releases, this would be Glibc. For OS X releases, this would be Darwin. For Android (coming soon in https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates them from the rapid expansion of platforms on which Swift is able to be executed.

This idea is not novel: the Swift package manager already defines a "libc" package that is essentially the boilerplate `os()` check above: https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift.

However, rather than determining which libc implementation to use at runtime (like SwiftPM does above), I propose we allow the Swift stdlib to be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in the Swift build scripts and CMake modules. Similar to how those scripts export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that could automatically convert conditional imports of Darwin/Glibc to the new `import Libc`.

We must also devise a strategy for the transient rollout period, when Swift defines a Libc module, but we don't have an OS X SDK that uses that name in the bundled module.map. We can add a compiler hack for that, to transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons stated in "Motivation". To reiterate: the current system forces users to go out of their way to write cross-platform Swift code, as opposed to writing code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and the C standard library. We could export *two* modules. However I believe this introduces additional overhead for users, with only the marginal benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would automatically get preprocessed to the five lines of boilerplate shown above. This has several downsides, most notably the added complexity to Swift syntax.

On point #2 (what to name it), I have spoken with people that raised concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal. If we want this module name to mean something, it should agree with the C++ spec.

I don't know which name was chosen in the C++ spec. I've been searching WG21 papers with no luck--any advice on how to find out would be appreciated!

Aside from the above point, some concrete alternatives for point #2 (what to name it) include:

- `import System`: This is better suited to the idea that the module contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (https://www.youtube.com/watch?v=PEgk2v6KntY <https://www.youtube.com/watch?v=PEgk2v6KntY>)

---

Thanks for taking the time to read this proposal draft! Feedback (on its contents or on how to proceed with the evolution proposal process) is greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Honza Dvorsky) #8

A huge +1 on the proposal, I even have a code snippet to import the
platform-appropriate C library. I try to write every new Swift library
cross-platform-by-default now and this would definitely remove some
friction. Not to mention it would future-proof many libraries which won't
need to be updated when a new Swift platform is added.

Personally, I like "import C", but at the end of the day I'm happy to call
it whatever as long as it solves the problem. I agree with Brian that with
Swift scaling up to 4 or so platforms soon-ish, it's preferable to not put
any extra burden on Swift users if there is an almost-uniform C API which
can be used everywhere.

···

On Wed, Mar 9, 2016 at 2:03 AM Jordan Rose via swift-evolution < swift-evolution@swift.org> wrote:

One of the reasons we haven't picked this *particular* name is if the C
or C++ committees ever adopted modules. Given that they just got punted
from C++17, though, maybe that shouldn't hold us back.

Jordan

On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution < > swift-evolution@swift.org> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in
libc (`fputs`, `stderr`, etc.) must all write the same five lines of
boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print
"Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols
`fputs` and `stderr`. Five lines may not be much, but these come with
significant drawbacks:

- They must be written in each source file that relies on libc, which is
tedious.
- It is subject to frequent change. As Swift is ported to more platforms,
that initial check must change to `#if os(Linux) || os(FreeBSD) ||
os(Windows) || os(Android)`, and so on. End users of Swift may not be
actively involved in its development, and so may be surprised when the
latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write
cross-platform code--as opposed to simply writing Swift and have it work on
other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for
the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the
following:

    import Libc

This would import whichever libc implementation Swift was compiled with.
For Ubuntu Linux releases, this would be Glibc. For OS X releases, this
would be Darwin. For Android (coming soon in
https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates
them from the rapid expansion of platforms on which Swift is able to be
executed.

This idea is not novel: the Swift package manager already defines a "libc"
package that is essentially the boilerplate `os()` check above:
https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift
.

However, rather than determining which libc implementation to use at
runtime (like SwiftPM does above), I propose we allow the Swift stdlib to
be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in
the Swift build scripts and CMake modules. Similar to how those scripts
export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this
proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that
could automatically convert conditional imports of Darwin/Glibc to the new
`import Libc`.

We must also devise a strategy for the transient rollout period, when
Swift defines a Libc module, but we don't have an OS X SDK that uses that
name in the bundled module.map. We can add a compiler hack for that, to
transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons
stated in "Motivation". To reiterate: the current system forces users to go
out of their way to write cross-platform Swift code, as opposed to writing
code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and
the C standard library. We could export *two* modules. However I believe
this introduces additional overhead for users, with only the marginal
benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would
automatically get preprocessed to the five lines of boilerplate shown
above. This has several downsides, most notably the added complexity to
Swift syntax.

On point #2 (what to name it), I have spoken with people that raised
concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal. If
we want this module name to mean something, it should agree with the C++
spec.

I don't know which name was chosen in the C++ spec. I've been searching
WG21 papers with no luck--any advice on how to find out would be
appreciated!

Aside from the above point, some concrete alternatives for point #2 (what
to name it) include:

- `import System`: This is better suited to the idea that the module
contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (
https://www.youtube.com/watch?v=PEgk2v6KntY)

---

Thanks for taking the time to read this proposal draft! Feedback (on its
contents or on how to proceed with the evolution proposal process) is
greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brian Gesiak) #9

Sorry to resurrect such an old thread! I understand getting this in Swift
3.0 might not be realistic anymore, but this is still something I’d love to
see added to Swift. Could someone advise on whether it still makes sense to
spend time on this proposal? Or is this part of Swift too solidified to
change at this point?

How much would Libc include? The standard C library? POSIX?

Yes, I had originally anticipated this as including module C
<https://github.com/apple/swift/blob/7b1a8dcf7fbcfd66f029cc5473edef5a08f86602/stdlib/public/Platform/glibc.modulemap.gyb#L29>
and module POSIX
<https://github.com/apple/swift/blob/7b1a8dcf7fbcfd66f029cc5473edef5a08f86602/stdlib/public/Platform/glibc.modulemap.gyb#L141>.
I see that module CUUID was recently added as well
<https://github.com/apple/swift/pull/3107>, but I don’t think that should
be included.

there are differences (minor, but still) between Glibc and Darwin. Those
should be either unified (if possible) or re-arranged so that the unified
library shares unified functionality and then each separate one can have
its own set of caveats.

I don’t think the unified import C module should do anything besides
obviate the need to write the following:

#if os(Linux) || os(FreeBSD)
    import Glibc
#else
    import Darwin
#endif

If people feel strongly about unifying the overlay, perhaps we should
discuss that in future swift-evolution proposals.

Personally, I like “import C”, but at the end of the day I’m happy to call
it whatever as long as it solves the problem.

I couldn’t have said it better myself!

/cc Saleem, since he may have Windows opinions.

- Brian Gesiak

···

On Wed, Mar 9, 2016 at 6:35 AM, Honza Dvorsky <czechboy0@gmail.com> wrote:

A huge +1 on the proposal, I even have a code snippet to import the
platform-appropriate C library. I try to write every new Swift library
cross-platform-by-default now and this would definitely remove some
friction. Not to mention it would future-proof many libraries which won't
need to be updated when a new Swift platform is added.

Personally, I like "import C", but at the end of the day I'm happy to call
it whatever as long as it solves the problem. I agree with Brian that with
Swift scaling up to 4 or so platforms soon-ish, it's preferable to not put
any extra burden on Swift users if there is an almost-uniform C API which
can be used everywhere.

On Wed, Mar 9, 2016 at 2:03 AM Jordan Rose via swift-evolution < > swift-evolution@swift.org> wrote:

One of the reasons we haven't picked this *particular* name is if the C
or C++ committees ever adopted modules. Given that they just got punted
from C++17, though, maybe that shouldn't hold us back.

Jordan

On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution < >> swift-evolution@swift.org> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in
libc (`fputs`, `stderr`, etc.) must all write the same five lines of
boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print
"Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols
`fputs` and `stderr`. Five lines may not be much, but these come with
significant drawbacks:

- They must be written in each source file that relies on libc, which is
tedious.
- It is subject to frequent change. As Swift is ported to more platforms,
that initial check must change to `#if os(Linux) || os(FreeBSD) ||
os(Windows) || os(Android)`, and so on. End users of Swift may not be
actively involved in its development, and so may be surprised when the
latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write
cross-platform code--as opposed to simply writing Swift and have it work on
other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for
the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the
following:

    import Libc

This would import whichever libc implementation Swift was compiled with.
For Ubuntu Linux releases, this would be Glibc. For OS X releases, this
would be Darwin. For Android (coming soon in
https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates
them from the rapid expansion of platforms on which Swift is able to be
executed.

This idea is not novel: the Swift package manager already defines a
"libc" package that is essentially the boilerplate `os()` check above:
https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift
.

However, rather than determining which libc implementation to use at
runtime (like SwiftPM does above), I propose we allow the Swift stdlib to
be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place
in the Swift build scripts and CMake modules. Similar to how those scripts
export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this
proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that
could automatically convert conditional imports of Darwin/Glibc to the new
`import Libc`.

We must also devise a strategy for the transient rollout period, when
Swift defines a Libc module, but we don't have an OS X SDK that uses that
name in the bundled module.map. We can add a compiler hack for that, to
transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons
stated in "Motivation". To reiterate: the current system forces users to go
out of their way to write cross-platform Swift code, as opposed to writing
code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and
the C standard library. We could export *two* modules. However I believe
this introduces additional overhead for users, with only the marginal
benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would
automatically get preprocessed to the five lines of boilerplate shown
above. This has several downsides, most notably the added complexity to
Swift syntax.

On point #2 (what to name it), I have spoken with people that raised
concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal.
If we want this module name to mean something, it should agree with the C++
spec.

I don't know which name was chosen in the C++ spec. I've been searching
WG21 papers with no luck--any advice on how to find out would be
appreciated!

Aside from the above point, some concrete alternatives for point #2 (what
to name it) include:

- `import System`: This is better suited to the idea that the module
contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (
https://www.youtube.com/watch?v=PEgk2v6KntY)

---

Thanks for taking the time to read this proposal draft! Feedback (on its
contents or on how to proceed with the evolution proposal process) is
greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #10

Sorry to resurrect such an old thread! I understand getting this in Swift 3.0 might not be realistic anymore, but this is still something I’d love to see added to Swift. Could someone advise on whether it still makes sense to spend time on this proposal? Or is this part of Swift too solidified to change at this point?

It is definitely beyond Swift 3.0, but I’d love to see this happen at some point, we really need someone to drive the (surely to be contentious) design process.

-Chris

···

On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution <swift-evolution@swift.org> wrote:

How much would Libc include? The standard C library? POSIX?

Yes, I had originally anticipated this as including module C <https://github.com/apple/swift/blob/7b1a8dcf7fbcfd66f029cc5473edef5a08f86602/stdlib/public/Platform/glibc.modulemap.gyb#L29> and module POSIX <https://github.com/apple/swift/blob/7b1a8dcf7fbcfd66f029cc5473edef5a08f86602/stdlib/public/Platform/glibc.modulemap.gyb#L141>. I see that module CUUID was recently added as well <https://github.com/apple/swift/pull/3107>, but I don’t think that should be included.

there are differences (minor, but still) between Glibc and Darwin. Those should be either unified (if possible) or re-arranged so that the unified library shares unified functionality and then each separate one can have its own set of caveats.

I don’t think the unified import C module should do anything besides obviate the need to write the following:

#if os(Linux) || os(FreeBSD)
    import Glibc
#else
    import Darwin
#endif
If people feel strongly about unifying the overlay, perhaps we should discuss that in future swift-evolution proposals.

Personally, I like “import C”, but at the end of the day I’m happy to call it whatever as long as it solves the problem.

I couldn’t have said it better myself!

/cc Saleem, since he may have Windows opinions.

- Brian Gesiak

On Wed, Mar 9, 2016 at 6:35 AM, Honza Dvorsky <czechboy0@gmail.com <mailto:czechboy0@gmail.com>> wrote:
A huge +1 on the proposal, I even have a code snippet to import the platform-appropriate C library. I try to write every new Swift library cross-platform-by-default now and this would definitely remove some friction. Not to mention it would future-proof many libraries which won't need to be updated when a new Swift platform is added.

Personally, I like "import C", but at the end of the day I'm happy to call it whatever as long as it solves the problem. I agree with Brian that with Swift scaling up to 4 or so platforms soon-ish, it's preferable to not put any extra burden on Swift users if there is an almost-uniform C API which can be used everywhere.

On Wed, Mar 9, 2016 at 2:03 AM Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
One of the reasons we haven't picked this particular name is if the C or C++ committees ever adopted modules. Given that they just got punted from C++17, though, maybe that shouldn't hold us back.

Jordan

On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in libc (`fputs`, `stderr`, etc.) must all write the same five lines of boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print "Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols `fputs` and `stderr`. Five lines may not be much, but these come with significant drawbacks:

- They must be written in each source file that relies on libc, which is tedious.
- It is subject to frequent change. As Swift is ported to more platforms, that initial check must change to `#if os(Linux) || os(FreeBSD) || os(Windows) || os(Android)`, and so on. End users of Swift may not be actively involved in its development, and so may be surprised when the latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write cross-platform code--as opposed to simply writing Swift and have it work on other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the following:

    import Libc

This would import whichever libc implementation Swift was compiled with. For Ubuntu Linux releases, this would be Glibc. For OS X releases, this would be Darwin. For Android (coming soon in https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates them from the rapid expansion of platforms on which Swift is able to be executed.

This idea is not novel: the Swift package manager already defines a "libc" package that is essentially the boilerplate `os()` check above: https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift.

However, rather than determining which libc implementation to use at runtime (like SwiftPM does above), I propose we allow the Swift stdlib to be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in the Swift build scripts and CMake modules. Similar to how those scripts export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that could automatically convert conditional imports of Darwin/Glibc to the new `import Libc`.

We must also devise a strategy for the transient rollout period, when Swift defines a Libc module, but we don't have an OS X SDK that uses that name in the bundled module.map. We can add a compiler hack for that, to transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons stated in "Motivation". To reiterate: the current system forces users to go out of their way to write cross-platform Swift code, as opposed to writing code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and the C standard library. We could export *two* modules. However I believe this introduces additional overhead for users, with only the marginal benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would automatically get preprocessed to the five lines of boilerplate shown above. This has several downsides, most notably the added complexity to Swift syntax.

On point #2 (what to name it), I have spoken with people that raised concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal. If we want this module name to mean something, it should agree with the C++ spec.

I don't know which name was chosen in the C++ spec. I've been searching WG21 papers with no luck--any advice on how to find out would be appreciated!

Aside from the above point, some concrete alternatives for point #2 (what to name it) include:

- `import System`: This is better suited to the idea that the module contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (https://www.youtube.com/watch?v=PEgk2v6KntY <https://www.youtube.com/watch?v=PEgk2v6KntY>)

---

Thanks for taking the time to read this proposal draft! Feedback (on its contents or on how to proceed with the evolution proposal process) is greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Saleem Abdulrasool) #11

Sorry to resurrect such an old thread! I understand getting this in Swift
3.0 might not be realistic anymore, but this is still something I’d love to
see added to Swift. Could someone advise on whether it still makes sense to
spend time on this proposal? Or is this part of Swift too solidified to
change at this point?

It is definitely beyond Swift 3.0, but I’d love to see this happen at some
point, we really need someone to drive the (surely to be contentious)
design process.

I'm probably going to regret this, but given that I had originally proposed
this to Brian and would really like to see this happen, what does this
entail?

-Chris

How much would Libc include? The standard C library? POSIX?

Yes, I had originally anticipated this as including module C
<https://github.com/apple/swift/blob/7b1a8dcf7fbcfd66f029cc5473edef5a08f86602/stdlib/public/Platform/glibc.modulemap.gyb#L29>
and module POSIX
<https://github.com/apple/swift/blob/7b1a8dcf7fbcfd66f029cc5473edef5a08f86602/stdlib/public/Platform/glibc.modulemap.gyb#L141>.
I see that module CUUID was recently added as well
<https://github.com/apple/swift/pull/3107>, but I don’t think that should
be included.

there are differences (minor, but still) between Glibc and Darwin. Those
should be either unified (if possible) or re-arranged so that the unified
library shares unified functionality and then each separate one can have
its own set of caveats.

I don’t think the unified import C module should do anything besides
obviate the need to write the following:

#if os(Linux) || os(FreeBSD)
    import Glibc
#else
    import Darwin
#endif

This is about to me made worse with me trying to get Windows support. How

does this look?

#if os(Linux) || os(FreeBSD) || os(PS4)
   import Glibc
#elseif os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
  import Darwin
#elseif os(Windows) && (_environment(msvc) || _environment(gnu))
  import msvc
#else
  import glibc
#endif

···

On Tuesday, July 5, 2016, Chris Lattner <clattner@apple.com> wrote:

On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

If people feel strongly about unifying the overlay, perhaps we should
discuss that in future swift-evolution proposals.

I would be interested in that as well.

Personally, I like “import C”, but at the end of the day I’m happy to call
it whatever as long as it solves the problem.

I couldn’t have said it better myself!

/cc Saleem, since he may have Windows opinions.

- Brian Gesiak

On Wed, Mar 9, 2016 at 6:35 AM, Honza Dvorsky <czechboy0@gmail.com > <javascript:_e(%7B%7D,'cvml','czechboy0@gmail.com');>> wrote:

A huge +1 on the proposal, I even have a code snippet to import the
platform-appropriate C library. I try to write every new Swift library
cross-platform-by-default now and this would definitely remove some
friction. Not to mention it would future-proof many libraries which won't
need to be updated when a new Swift platform is added.

Personally, I like "import C", but at the end of the day I'm happy to
call it whatever as long as it solves the problem. I agree with Brian that
with Swift scaling up to 4 or so platforms soon-ish, it's preferable to not
put any extra burden on Swift users if there is an almost-uniform C API
which can be used everywhere.

On Wed, Mar 9, 2016 at 2:03 AM Jordan Rose via swift-evolution < >> swift-evolution@swift.org >> <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

One of the reasons we haven't picked this *particular* name is if the C
or C++ committees ever adopted modules. Given that they just got punted
from C++17, though, maybe that shouldn't hold us back.

Jordan

On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution < >>> swift-evolution@swift.org >>> <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in
libc (`fputs`, `stderr`, etc.) must all write the same five lines of
boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would
print "Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols
`fputs` and `stderr`. Five lines may not be much, but these come with
significant drawbacks:

- They must be written in each source file that relies on libc, which is
tedious.
- It is subject to frequent change. As Swift is ported to more
platforms, that initial check must change to `#if os(Linux) || os(FreeBSD)
>> os(Windows) || os(Android)`, and so on. End users of Swift may not be
actively involved in its development, and so may be surprised when the
latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write
cross-platform code--as opposed to simply writing Swift and have it work on
other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for
the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the
following:

    import Libc

This would import whichever libc implementation Swift was compiled with.
For Ubuntu Linux releases, this would be Glibc. For OS X releases, this
would be Darwin. For Android (coming soon in
https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates
them from the rapid expansion of platforms on which Swift is able to be
executed.

This idea is not novel: the Swift package manager already defines a
"libc" package that is essentially the boilerplate `os()` check above:
https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift
.

However, rather than determining which libc implementation to use at
runtime (like SwiftPM does above), I propose we allow the Swift stdlib to
be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place
in the Swift build scripts and CMake modules. Similar to how those scripts
export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this
proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that
could automatically convert conditional imports of Darwin/Glibc to the new
`import Libc`.

We must also devise a strategy for the transient rollout period, when
Swift defines a Libc module, but we don't have an OS X SDK that uses that
name in the bundled module.map. We can add a compiler hack for that, to
transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons
stated in "Motivation". To reiterate: the current system forces users to go
out of their way to write cross-platform Swift code, as opposed to writing
code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and
the C standard library. We could export *two* modules. However I believe
this introduces additional overhead for users, with only the marginal
benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would
automatically get preprocessed to the five lines of boilerplate shown
above. This has several downsides, most notably the added complexity to
Swift syntax.

On point #2 (what to name it), I have spoken with people that raised
concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal.
If we want this module name to mean something, it should agree with the C++
spec.

I don't know which name was chosen in the C++ spec. I've been searching
WG21 papers with no luck--any advice on how to find out would be
appreciated!

Aside from the above point, some concrete alternatives for point #2
(what to name it) include:

- `import System`: This is better suited to the idea that the module
contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (
https://www.youtube.com/watch?v=PEgk2v6KntY)

---

Thanks for taking the time to read this proposal draft! Feedback (on its
contents or on how to proceed with the evolution proposal process) is
greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org


(Chris Lattner) #12

1) get some consensus on list for an overall approach
2) formalize a proposal and submit a PR to swift-evolution
3) iterate

#1 is the hardest I think. I don’t think a truly minimal wrapper of the POSIX APIs is interesting, I think we should at least make a Swifty POSIX API, which is portable and low-abstraction overhead. However, it should fix the mistakes of errno and “creat” among other things.

-Chris

···

On Jul 5, 2016, at 5:28 PM, Saleem Abdulrasool <compnerd@compnerd.org> wrote:

On Tuesday, July 5, 2016, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution <swift-evolution@swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Sorry to resurrect such an old thread! I understand getting this in Swift 3.0 might not be realistic anymore, but this is still something I’d love to see added to Swift. Could someone advise on whether it still makes sense to spend time on this proposal? Or is this part of Swift too solidified to change at this point?

It is definitely beyond Swift 3.0, but I’d love to see this happen at some point, we really need someone to drive the (surely to be contentious) design process.

I'm probably going to regret this, but given that I had originally proposed this to Brian and would really like to see this happen, what does this entail?


(Saleem Abdulrasool) #13

Sorry to resurrect such an old thread! I understand getting this in Swift
3.0 might not be realistic anymore, but this is still something I’d love to
see added to Swift. Could someone advise on whether it still makes sense to
spend time on this proposal? Or is this part of Swift too solidified to
change at this point?

It is definitely beyond Swift 3.0, but I’d love to see this happen at
some point, we really need someone to drive the (surely to be contentious)
design process.

I'm probably going to regret this, but given that I had originally
proposed this to Brian and would really like to see this happen, what does
this entail?

1) get some consensus on list for an overall approach
2) formalize a proposal and submit a PR to swift-evolution
3) iterate

#1 is the hardest I think. I don’t think a truly minimal wrapper of the
POSIX APIs is interesting, I think we should at least make a Swifty POSIX
API, which is portable and low-abstraction overhead. However, it should
fix the mistakes of errno and “creat” among other things.

That sounds pretty reasonable. Especially if we do this earlier, breaking
from expectations in terms of mapping for things like "creat" would be less
intrusive.

Not sure what you had in mind for errno. It seems like if we have an SDK
overlay for posix, we could hide errno, handling it similar to NSError.
However, I think that violates the low overhead.

···

On Tuesday, July 5, 2016, Chris Lattner <clattner@apple.com> wrote:

On Jul 5, 2016, at 5:28 PM, Saleem Abdulrasool <compnerd@compnerd.org > <javascript:_e(%7B%7D,'cvml','compnerd@compnerd.org');>> wrote:
On Tuesday, July 5, 2016, Chris Lattner <clattner@apple.com > <javascript:_e(%7B%7D,'cvml','clattner@apple.com');>> wrote:

On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution < >> swift-evolution@swift.org> wrote:

-Chris

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org


(Chris Lattner) #14

It seems that we should either go down the “typed result type” route, or implement support for typed throws (my personal preference), allowing us to say “func f() throws POSIXError {}”.

-Chris

···

On Jul 5, 2016, at 5:41 PM, Saleem Abdulrasool <compnerd@compnerd.org> wrote:

On Tuesday, July 5, 2016, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Jul 5, 2016, at 5:28 PM, Saleem Abdulrasool <compnerd@compnerd.org <javascript:_e(%7B%7D,'cvml','compnerd@compnerd.org');>> wrote:

On Tuesday, July 5, 2016, Chris Lattner <clattner@apple.com <javascript:_e(%7B%7D,'cvml','clattner@apple.com');>> wrote:

On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution <swift-evolution@swift.org <>> wrote:

Sorry to resurrect such an old thread! I understand getting this in Swift 3.0 might not be realistic anymore, but this is still something I’d love to see added to Swift. Could someone advise on whether it still makes sense to spend time on this proposal? Or is this part of Swift too solidified to change at this point?

It is definitely beyond Swift 3.0, but I’d love to see this happen at some point, we really need someone to drive the (surely to be contentious) design process.

I'm probably going to regret this, but given that I had originally proposed this to Brian and would really like to see this happen, what does this entail?

1) get some consensus on list for an overall approach
2) formalize a proposal and submit a PR to swift-evolution
3) iterate

#1 is the hardest I think. I don’t think a truly minimal wrapper of the POSIX APIs is interesting, I think we should at least make a Swifty POSIX API, which is portable and low-abstraction overhead. However, it should fix the mistakes of errno and “creat” among other things.

That sounds pretty reasonable. Especially if we do this earlier, breaking from expectations in terms of mapping for things like "creat" would be less intrusive.

Not sure what you had in mind for errno. It seems like if we have an SDK overlay for posix, we could hide errno, handling it similar to NSError. However, I think that violates the low overhead.


(David Waite) #15

I see two possible approaches:

1. A “import Libc” imports the platform libraries, whatever they may be, on the OS platform you are on.

2. The OS platform libraries are divided up, virtually if necessary, to expose the underlying standard interfaces without platform-specific extensions. I imagine that would look similar to https://gist.github.com/dwaite/c7125680def834e93ba1fae8873ce1f8:

                                                        ┌─────────────┐
                               ┌────────────────────────│ Foundation ├┐
                               │ Platform-specific └┬────────────┘├┐
                               │ ┌──────────────┐ └┬────┬───────┘│
                               │ │ Linux │ └────┼────────┘
                               │ │ ┌────────┐ │ │
                               ├──────┼──│ GLibc │ │ │
                               │ │ └────────┘ │ │
                               │ │ │ │
             C Standard │ ├──────────────┤ │
               Library ▼ │ Apple OSes │ │
┌────────┐ ┌────────┐ ┌────────┐ │ ┌────────┐ │ │
│ Swift │◀──│ Libc │◀──│ Posix │◀─┼──│ Darwin │◀─┼─────────┤
└────────┘ └────────┘ └────────┘ │ └────────┘ │ │
                  ▲ │ │ │
                  │ ├──────────────┤ │
                  │ │ Windows │ │
                  │ │ ┌────────┐ │ │
                  └───────────────────┼──│ Win32 │◀─┼─────────┘
                                      │ └────────┘ │
                                      │ │
                                      └──────────────┘

My feeling is that while dealing with imported code, it is understandable you will have API that differs per platform. Once you start adding object or protocol-oriented design on top, it is expected that the additional layer will abstract those differences away.

-DW

···

On Jul 5, 2016, at 6:28 PM, Saleem Abdulrasool via swift-evolution <swift-evolution@swift.org> wrote:

On Tuesday, July 5, 2016, Chris Lattner <clattner@apple.com> wrote:

On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution <swift-evolution@swift.org> wrote:

Sorry to resurrect such an old thread! I understand getting this in Swift 3.0 might not be realistic anymore, but this is still something I’d love to see added to Swift. Could someone advise on whether it still makes sense to spend time on this proposal? Or is this part of Swift too solidified to change at this point?

It is definitely beyond Swift 3.0, but I’d love to see this happen at some point, we really need someone to drive the (surely to be contentious) design process.

I'm probably going to regret this, but given that I had originally proposed this to Brian and would really like to see this happen, what does this entail?

-Chris

How much would Libc include? The standard C library? POSIX?

Yes, I had originally anticipated this as including module C and module POSIX. I see that module CUUID was recently added as well, but I don’t think that should be included.

there are differences (minor, but still) between Glibc and Darwin. Those should be either unified (if possible) or re-arranged so that the unified library shares unified functionality and then each separate one can have its own set of caveats.

I don’t think the unified import C module should do anything besides obviate the need to write the following:

#if os(Linux) || os(FreeBSD
)
    
import Glibc

#
else

import Darwin

#endif

This is about to me made worse with me trying to get Windows support. How does this look?

#if os(Linux) || os(FreeBSD) || os(PS4)
   import Glibc
#elseif os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
  import Darwin
#elseif os(Windows) && (_environment(msvc) || _environment(gnu))
  import msvc
#else
  import glibc
#endif

If people feel strongly about unifying the overlay, perhaps we should discuss that in future swift-evolution proposals.

I would be interested in that as well.

Personally, I like “import C”, but at the end of the day I’m happy to call it whatever as long as it solves the problem.

I couldn’t have said it better myself!

/cc Saleem, since he may have Windows opinions.

- Brian Gesiak

On Wed, Mar 9, 2016 at 6:35 AM, Honza Dvorsky <czechboy0@gmail.com> wrote:
A huge +1 on the proposal, I even have a code snippet to import the platform-appropriate C library. I try to write every new Swift library cross-platform-by-default now and this would definitely remove some friction. Not to mention it would future-proof many libraries which won't need to be updated when a new Swift platform is added.

Personally, I like "import C", but at the end of the day I'm happy to call it whatever as long as it solves the problem. I agree with Brian that with Swift scaling up to 4 or so platforms soon-ish, it's preferable to not put any extra burden on Swift users if there is an almost-uniform C API which can be used everywhere.

On Wed, Mar 9, 2016 at 2:03 AM Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:
One of the reasons we haven't picked this particular name is if the C or C++ committees ever adopted modules. Given that they just got punted from C++17, though, maybe that shouldn't hold us back.

Jordan

On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution <swift-evolution@swift.org> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in libc (`fputs`, `stderr`, etc.) must all write the same five lines of boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print "Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols `fputs` and `stderr`. Five lines may not be much, but these come with significant drawbacks:

- They must be written in each source file that relies on libc, which is tedious.
- It is subject to frequent change. As Swift is ported to more platforms, that initial check must change to `#if os(Linux) || os(FreeBSD) || os(Windows) || os(Android)`, and so on. End users of Swift may not be actively involved in its development, and so may be surprised when the latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write cross-platform code--as opposed to simply writing Swift and have it work on other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the following:

    import Libc

This would import whichever libc implementation Swift was compiled with. For Ubuntu Linux releases, this would be Glibc. For OS X releases, this would be Darwin. For Android (coming soon in https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates them from the rapid expansion of platforms on which Swift is able to be executed.

This idea is not novel: the Swift package manager already defines a "libc" package that is essentially the boilerplate `os()` check above: https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift.

However, rather than determining which libc implementation to use at runtime (like SwiftPM does above), I propose we allow the Swift stdlib to be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in the Swift build scripts and CMake modules. Similar to how those scripts export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that could automatically convert conditional imports of Darwin/Glibc to the new `import Libc`.

We must also devise a strategy for the transient rollout period, when Swift defines a Libc module, but we don't have an OS X SDK that uses that name in the bundled module.map. We can add a compiler hack for that, to transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons stated in "Motivation". To reiterate: the current system forces users to go out of their way to write cross-platform Swift code, as opposed to writing code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and the C standard library. We could export *two* modules. However I believe this introduces additional overhead for users, with only the marginal benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would automatically get preprocessed to the five lines of boilerplate shown above. This has several downsides, most notably the added complexity to Swift syntax.

On point #2 (what to name it), I have spoken with people that raised concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal. If we want this module name to mean something, it should agree with the C++ spec.

I don't know which name was chosen in the C++ spec. I've been searching WG21 papers with no luck--any advice on how to find out would be appreciated!

Aside from the above point, some concrete alternatives for point #2 (what to name it) include:

- `import System`: This is better suited to the idea that the module contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (https://www.youtube.com/watch?v=PEgk2v6KntY)

---

Thanks for taking the time to read this proposal draft! Feedback (on its contents or on how to proceed with the evolution proposal process) is greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(L Mihalkovic) #16

It looks like there are 2 views being discussed

Import System : just masks the difference in platform specific names
Import Libc : a true attempt at a swift specific view of credible c runtime equivalent

The first one would be easy to do now and would alleviate all the mindless #if...#endif we have today.

Regards
LM
(From mobile)

···

On Jul 6, 2016, at 1:13 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution <swift-evolution@swift.org> wrote:

Sorry to resurrect such an old thread! I understand getting this in Swift 3.0 might not be realistic anymore, but this is still something I’d love to see added to Swift. Could someone advise on whether it still makes sense to spend time on this proposal? Or is this part of Swift too solidified to change at this point?

It is definitely beyond Swift 3.0, but I’d love to see this happen at some point, we really need someone to drive the (surely to be contentious) design process.

-Chris

How much would Libc include? The standard C library? POSIX?

Yes, I had originally anticipated this as including module C and module POSIX. I see that module CUUID was recently added as well, but I don’t think that should be included.

there are differences (minor, but still) between Glibc and Darwin. Those should be either unified (if possible) or re-arranged so that the unified library shares unified functionality and then each separate one can have its own set of caveats.

I don’t think the unified import C module should do anything besides obviate the need to write the following:

#if os(Linux) || os(FreeBSD)
    import Glibc
#else
    import Darwin
#endif
If people feel strongly about unifying the overlay, perhaps we should discuss that in future swift-evolution proposals.

Personally, I like “import C”, but at the end of the day I’m happy to call it whatever as long as it solves the problem.

I couldn’t have said it better myself!

/cc Saleem, since he may have Windows opinions.

- Brian Gesiak

On Wed, Mar 9, 2016 at 6:35 AM, Honza Dvorsky <czechboy0@gmail.com> wrote:
A huge +1 on the proposal, I even have a code snippet to import the platform-appropriate C library. I try to write every new Swift library cross-platform-by-default now and this would definitely remove some friction. Not to mention it would future-proof many libraries which won't need to be updated when a new Swift platform is added.

Personally, I like "import C", but at the end of the day I'm happy to call it whatever as long as it solves the problem. I agree with Brian that with Swift scaling up to 4 or so platforms soon-ish, it's preferable to not put any extra burden on Swift users if there is an almost-uniform C API which can be used everywhere.

On Wed, Mar 9, 2016 at 2:03 AM Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:

One of the reasons we haven't picked this particular name is if the C or C++ committees ever adopted modules. Given that they just got punted from C++17, though, maybe that shouldn't hold us back.

Jordan

On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution <swift-evolution@swift.org> wrote:

# Introduction

Currently, cross-platform Swift programs that rely on symbols defined in libc (`fputs`, `stderr`, etc.) must all write the same five lines of boilerplate code:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

Instead, I propose the following, which will work on all platforms:

    import Libc

# Motivation

Let's say we wanted to write a program that, on any platform, would print "Hello world!" to stderr. We'd probably come up with this:

    #if os(Linux) || os(FreeBSD)
        import Glibc
    #else
        import Darwin
    #endif

    fputs("Hello world!", stderr)

The first five lines of this program are necessary to import the symbols `fputs` and `stderr`. Five lines may not be much, but these come with significant drawbacks:

- They must be written in each source file that relies on libc, which is tedious.
- It is subject to frequent change. As Swift is ported to more platforms, that initial check must change to `#if os(Linux) || os(FreeBSD) || os(Windows) || os(Android)`, and so on. End users of Swift may not be actively involved in its development, and so may be surprised when the latest release suddenly necessitates more `os()` conditions.
- These combined force users to make a conscious decision to write cross-platform code--as opposed to simply writing Swift and have it work on other platforms seamlessly.

It would be preferable if people writing Swift did not need to check for the current `os()` in order to write code that works across platforms.

# Proposed solution

Instead of conditionally importing Darwin or Glibc, I propose the following:

    import Libc

This would import whichever libc implementation Swift was compiled with. For Ubuntu Linux releases, this would be Glibc. For OS X releases, this would be Darwin. For Android (coming soon in https://github.com/apple/swift/pull/1442), this would be Bionic.

This saves the end user from writing boilerplate code, and it isolates them from the rapid expansion of platforms on which Swift is able to be executed.

This idea is not novel: the Swift package manager already defines a "libc" package that is essentially the boilerplate `os()` check above: https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift.

However, rather than determining which libc implementation to use at runtime (like SwiftPM does above), I propose we allow the Swift stdlib to be compiled with any arbitrary implementation of libc.

# Detailed design

It's my understanding that the majority of this change would take place in the Swift build scripts and CMake modules. Similar to how those scripts export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this proposal could be implementing by exporting a "Libc" on all platforms.

This would also be accompanied by a change to the Swift 3 migrator that could automatically convert conditional imports of Darwin/Glibc to the new `import Libc`.

We must also devise a strategy for the transient rollout period, when Swift defines a Libc module, but we don't have an OS X SDK that uses that name in the bundled module.map. We can add a compiler hack for that, to transparently translate the name.

# Alternatives considered

I believe there are two contentious points to this proposal:

1. Whether to unify the module name across platforms.
2. What to name the module.

Alternatives considered on point #1 (whether to unify) include:

1a. The status quo: I consider this to be undesirable for the reasons stated in "Motivation". To reiterate: the current system forces users to go out of their way to write cross-platform Swift code, as opposed to writing code that "just works" everywhere.
1b. The current Darwin and Glibc modules are a combination of POSIX and the C standard library. We could export *two* modules. However I believe this introduces additional overhead for users, with only the marginal benefit of clean separation between libc and POSIX.
1c. A special import statement, defined in the Swift stdlib, that would automatically get preprocessed to the five lines of boilerplate shown above. This has several downsides, most notably the added complexity to Swift syntax.

On point #2 (what to name it), I have spoken with people that raised concerns over the name "Libc":

> Another concern is about compatibility with the C++ modules proposal. If we want this module name to mean something, it should agree with the C++ spec.

I don't know which name was chosen in the C++ spec. I've been searching WG21 papers with no luck--any advice on how to find out would be appreciated!

Aside from the above point, some concrete alternatives for point #2 (what to name it) include:

- `import System`: This is better suited to the idea that the module contains both POSIX and libc.
- `import C`: Drop the "Lib"--just "C". It's cleaner. (https://www.youtube.com/watch?v=PEgk2v6KntY)

---

Thanks for taking the time to read this proposal draft! Feedback (on its contents or on how to proceed with the evolution proposal process) is greatly appreciated.

- Brian Gesiak
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #17

I think that it is also important to ask what the real goal here is. Foundation is our cross platform compatibility layer, are there specific deficiencies in the Foundation API that cause a problem here, or is it just that not all of corelibs Foundation is “done” yet?

-Chris

···

On Jul 6, 2016, at 4:35 PM, David Waite <david@alkaline-solutions.com> wrote:

I see two possible approaches:

1. A “import Libc” imports the platform libraries, whatever they may be, on the OS platform you are on.

2. The OS platform libraries are divided up, virtually if necessary, to expose the underlying standard interfaces without platform-specific extensions. I imagine that would look similar to https://gist.github.com/dwaite/c7125680def834e93ba1fae8873ce1f8: <https://gist.github.com/dwaite/c7125680def834e93ba1fae8873ce1f8:>


(Sean Alling) #18

Hey guys and girls and everything in between,

I was discussing this on Twitter.

Perhaps the first step to easing this import system is to allow import conditional operators:

&&

would be the two of most use (mostly ||). We could perform the Darwin or Glibc import based on order of operations. Should the first import library fail than try the second, third, etc. elements until one has either been found or none. This avoids creating a whole pure swift library, although that may be a longer term goal to create a ecosystem of architecture independent libraries for pure swift use cross platform. Import statements for Darwin/Glibc would end up looking like this:

import Darwin || Glibc

I feel this would be well within line with Swift syntax.

- Sean

···

-----------------
Sean Alling
Nuclear Engineer

> It looks like there are 2 views being discussed
>
> Import System : just masks the difference in platform specific names
> Import Libc : a true attempt at a swift specific view of credible c runtime equivalent
>
> The first one would be easy to do now and would alleviate all the mindless #if...#endif we have today.
>
> Regards
> LM
> (From mobile)
>
> > On Jul 6, 2016, at 1:13 AM, Chris Lattner via swift-evolution<swift-evolution at swift.org>wrote:
> >
> >
> > > On Jul 5, 2016, at 2:59 PM, Brian Gesiak via swift-evolution<swift-evolution at swift.org>wrote:
> > >
> > > Sorry to resurrect such an old thread! I understand getting this in Swift 3.0 might not be realistic anymore, but this is still something I’d love to see added to Swift. Could someone advise on whether it still makes sense to spend time on this proposal? Or is this part of Swift too solidified to change at this point?
> > It is definitely beyond Swift 3.0, but I’d love to see this happen at some point, we really need someone to drive the (surely to be contentious) design process.
> >
> > -Chris
> >
> >
> > > How much would Libc include? The standard C library? POSIX?
> > >
> > > Yes, I had originally anticipated this as including module C and module POSIX. I see that module CUUID was recently added as well, but I don’t think that should be included.
> > >
> > > there are differences (minor, but still) between Glibc and Darwin. Those should be either unified (if possible) or re-arranged so that the unified library shares unified functionality and then each separate one can have its own set of caveats.
> > >
> > > I don’t think the unified import C module should do anything besides obviate the need to write the following:
> > >
> > > #if os(Linux) || os(FreeBSD)
> > > import Glibc
> > > #else
> > > import Darwin
> > > #endif
> > > If people feel strongly about unifying the overlay, perhaps we should discuss that in future swift-evolution proposals.
> > >
> > > Personally, I like “import C”, but at the end of the day I’m happy to call it whatever as long as it solves the problem.
> > >
> > > I couldn’t have said it better myself!
> > >
> > > /cc Saleem, since he may have Windows opinions.
> > >
> > > - Brian Gesiak
> > >
> > >
> > > > On Wed, Mar 9, 2016 at 6:35 AM, Honza Dvorsky<czechboy0 at gmail.com>wrote:
> > > > A huge +1 on the proposal, I even have a code snippet to import the platform-appropriate C library. I try to write every new Swift library cross-platform-by-default now and this would definitely remove some friction. Not to mention it would future-proof many libraries which won't need to be updated when a new Swift platform is added.
> > > >
> > > > Personally, I like "import C", but at the end of the day I'm happy to call it whatever as long as it solves the problem. I agree with Brian that with Swift scaling up to 4 or so platforms soon-ish, it's preferable to not put any extra burden on Swift users if there is an almost-uniform C API which can be used everywhere.
> > > >
> > > > On Wed, Mar 9, 2016 at 2:03 AM Jordan Rose via swift-evolution<swift-evolution at swift.org>wrote:
> > > > > One of the reasons we haven't picked this particular name is if the C or C++ committees ever adopted modules. Given that they just got punted from C++17, though, maybe that shouldn't hold us back.
> > > > >
> > > > > Jordan
> > > > >
> > > > >
> > > > > > On Mar 8, 2016, at 11:13, Brian Gesiak via swift-evolution<swift-evolution at swift.org>wrote:
> > > > > >
> > > > > > # Introduction
> > > > > >
> > > > > > Currently, cross-platform Swift programs that rely on symbols defined in libc (`fputs`, `stderr`, etc.) must all write the same five lines of boilerplate code:
> > > > > >
> > > > > > #if os(Linux) || os(FreeBSD)
> > > > > > import Glibc
> > > > > > #else
> > > > > > import Darwin
> > > > > > #endif
> > > > > >
> > > > > > Instead, I propose the following, which will work on all platforms:
> > > > > >
> > > > > > import Libc
> > > > > >
> > > > > > # Motivation
> > > > > >
> > > > > > Let's say we wanted to write a program that, on any platform, would print "Hello world!" to stderr. We'd probably come up with this:
> > > > > >
> > > > > > #if os(Linux) || os(FreeBSD)
> > > > > > import Glibc
> > > > > > #else
> > > > > > import Darwin
> > > > > > #endif
> > > > > >
> > > > > > fputs("Hello world!", stderr)
> > > > > >
> > > > > > The first five lines of this program are necessary to import the symbols `fputs` and `stderr`. Five lines may not be much, but these come with significant drawbacks:
> > > > > >
> > > > > > - They must be written in each source file that relies on libc, which is tedious.
> > > > > > - It is subject to frequent change. As Swift is ported to more platforms, that initial check must change to `#if os(Linux) || os(FreeBSD) || os(Windows) || os(Android)`, and so on. End users of Swift may not be actively involved in its development, and so may be surprised when the latest release suddenly necessitates more `os()` conditions.
> > > > > > - These combined force users to make a conscious decision to write cross-platform code--as opposed to simply writing Swift and have it work on other platforms seamlessly.
> > > > > >
> > > > > > It would be preferable if people writing Swift did not need to check for the current `os()` in order to write code that works across platforms.
> > > > > >
> > > > > > # Proposed solution
> > > > > >
> > > > > > Instead of conditionally importing Darwin or Glibc, I propose the following:
> > > > > >
> > > > > > import Libc
> > > > > >
> > > > > > This would import whichever libc implementation Swift was compiled with. For Ubuntu Linux releases, this would be Glibc. For OS X releases, this would be Darwin. For Android (coming soon in https://github.com/apple/swift/pull/1442), this would be Bionic.
> > > > > >
> > > > > > This saves the end user from writing boilerplate code, and it isolates them from the rapid expansion of platforms on which Swift is able to be executed.
> > > > > >
> > > > > > This idea is not novel: the Swift package manager already defines a "libc" package that is essentially the boilerplate `os()` check above: https://github.com/apple/swift-package-manager/blob/master/Sources/libc/libc.swift.
> > > > > >
> > > > > > However, rather than determining which libc implementation to use at runtime (like SwiftPM does above), I propose we allow the Swift stdlib to be compiled with any arbitrary implementation of libc.
> > > > > >
> > > > > > # Detailed design
> > > > > >
> > > > > > It's my understanding that the majority of this change would take place in the Swift build scripts and CMake modules. Similar to how those scripts export a module named "Glibc" on Linux (see stdlib/public/core/Glibc), this proposal could be implementing by exporting a "Libc" on all platforms.
> > > > > >
> > > > > > This would also be accompanied by a change to the Swift 3 migrator that could automatically convert conditional imports of Darwin/Glibc to the new `import Libc`.
> > > > > >
> > > > > > We must also devise a strategy for the transient rollout period, when Swift defines a Libc module, but we don't have an OS X SDK that uses that name in the bundled module.map. We can add a compiler hack for that, to transparently translate the name.
> > > > > >
> > > > > > # Alternatives considered
> > > > > >
> > > > > > I believe there are two contentious points to this proposal:
> > > > > >
> > > > > > 1. Whether to unify the module name across platforms.
> > > > > > 2. What to name the module.
> > > > > >
> > > > > > Alternatives considered on point #1 (whether to unify) include:
> > > > > >
> > > > > > 1a. The status quo: I consider this to be undesirable for the reasons stated in "Motivation". To reiterate: the current system forces users to go out of their way to write cross-platform Swift code, as opposed to writing code that "just works" everywhere.
> > > > > > 1b. The current Darwin and Glibc modules are a combination of POSIX and the C standard library. We could export *two* modules. However I believe this introduces additional overhead for users, with only the marginal benefit of clean separation between libc and POSIX.
> > > > > > 1c. A special import statement, defined in the Swift stdlib, that would automatically get preprocessed to the five lines of boilerplate shown above. This has several downsides, most notably the added complexity to Swift syntax.
> > > > > >
> > > > > > On point #2 (what to name it), I have spoken with people that raised concerns over the name "Libc":
> > > > > >
> > > > > > > Another concern is about compatibility with the C++ modules proposal. If we want this module name to mean something, it should agree with the C++ spec.
> > > > > >
> > > > > > I don't know which name was chosen in the C++ spec. I've been searching WG21 papers with no luck--any advice on how to find out would be appreciated!
> > > > > >
> > > > > > Aside from the above point, some concrete alternatives for point #2 (what to name it) include:
> > > > > >
> > > > > > - `import System`: This is better suited to the idea that the module contains both POSIX and libc.
> > > > > > - `import C`: Drop the "Lib"--just "C". It's cleaner. (https://www.youtube.com/watch?v=PEgk2v6KntY)
> > > > > >
> > > > > > ---
> > > > > >
> > > > > > Thanks for taking the time to read this proposal draft! Feedback (on its contents or on how to proceed with the evolution proposal process) is greatly appreciated.
> > > > > >
> > > > > > - Brian Gesiak
> > > > > > _______________________________________________
> > > > > > swift-evolution mailing list
> > > > > > swift-evolution at swift.org
> > > > > > https://lists.swift.org/mailman/listinfo/swift-evolution
> > > > >
> > > > > _______________________________________________
> > > > > swift-evolution mailing list
> > > > > swift-evolution at swift.org
> > > > > https://lists.swift.org/mailman/listinfo/swift-evolution
> > >
> > > _______________________________________________
> > > swift-evolution mailing list
> > > swift-evolution at swift.org
> > > https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>


(Stuart Carnie) #19

I would like to add my vote for pushing Foundation as a cross-platform
compatibility layer, rather than exposing "Libc". Naturally there is
flexibility in designing the APIs to be appropriately Swifty. I would also
like to see higher level concepts available via Foundation, like protocols
for streams (Readers, Writers, etc) and implementations for files, sockets,
compression, encryption, etc. Protocols oriented design will shine. I think
the Go standard library would serve as inspiration for some of the design,
such as the io package.

Cheers,

Stu

*Stuart Carnie*

···

On Thu, Jul 7, 2016 at 3:38 PM, Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

On Jul 6, 2016, at 4:35 PM, David Waite <david@alkaline-solutions.com> > wrote:

I see two possible approaches:

1. A “import Libc” imports the platform libraries, whatever they may be,
on the OS platform you are on.

2. The OS platform libraries are divided up, virtually if necessary, to
expose the underlying standard interfaces without platform-specific
extensions. I imagine that would look similar to
https://gist.github.com/dwaite/c7125680def834e93ba1fae8873ce1f8:

I think that it is also important to ask what the real goal here is.
Foundation is our cross platform compatibility layer, are there specific
deficiencies in the Foundation API that cause a problem here, or is it just
that not all of corelibs Foundation is “done” yet?

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brian Gesiak) #20

Resurrecting this discussion since the question of "why does Android import
Glibc?" came up on this swift-corelibs-foundation pull request:
https://github.com/apple/swift-corelibs-foundation/pull/622#discussion_r77848100

I think that it is also important to ask what the real goal here is.

Foundation is our cross platform compatibility layer, are there specific
deficiencies in the Foundation API that cause a problem here, or is it just
that not all of corelibs Foundation is “done” yet?

When I first proposed the idea, I simply wanted to turn these five lines:

    #if os(Linux) || os(FreeBSD) || os(Android) || os(PS4)
        import Glibc
    #else
        import Darwin
    #endif

Into this one line:

    import WhateverNameWeDecideUpon

After all, writing five lines of code for the import is painful, and the
list of `#if os(...) || os(...) || ...` is always expanding.

I hadn't thought about a unified overlay for POSIX. I think the simplified
import alone has benefit to warrant its own evolution proposal. Would it be
possible to have a separate discussion for the POSIX overlay idea? Or is
there a reason that I'm missing that prevents the import from being viable
on its own? (Apologies in advance if there's an obvious answer to this
question!)

- Brian Gesiak