Handling Windows C library Matrix

Hi,

Windows has an interesting (different) model for handling the C library.
There are *four* different libraries and you select the library you want
across two axis. Traditionally the driver controls the selected library
via flags (and options exposed to the developer via the IDE). Im not sure
what is the best way to handle that with swift.

This table explains how the library selection works:

                           Debug | Release

···

+----------------------+--------------------+
statically linked | libcmtd.lib (/MTd) | libcmt.lib (/MT)
dyamically linked | msvcrtdl.lib (MDd) | msvcrt.lib (/MD)

Now, there are certain advantages to both linkage models. The static
linkage means that you don't have any dependency on the VC runtime
redistributable at the cost of small binary. The dynamic linkage means
that you have a dependency on the VC runtime redistributable, but you have
a smaller binary and future updates can update libc.

The library selection unfortunately goes further than just linkage. The
flags control other flags which matter for the C library interfaces (DLL
storage).

The crux of the issue is, how to model this behavior in the swift driver,
since the only places where this matters will be the ClangImporter and the
standard library build, but the latter can be addressed much more easily as
it would be internal to the build and not exposed to the users.

If we are looking for precedent, the clang driver introduced a
`--dependent-lib` CC1 option (mapping /MTd, /MT, /MDd, /MD to it
appropriately).

Note that I am *NOT* advocating a second driver interface, because I think
that will just cause unnecessary work and confusion. As long as we have
options or some means t control the interface, I think having a single
unified driver interface is a significantly better approach.

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

For anyone watching this thread, Saleem broke it down a little further for me in https://github.com/apple/swift/pull/3326\. For now we decided to just add an autolink flag to the frontend (not the driver) to make sure we don't get the "wrong" C library by accident. We'll need to discuss further how this actually affects Swift, and what form this choice should be presented to the user.

I found Potential Errors Passing CRT Objects Across DLL Boundaries | Microsoft Learn which talks about the costs of mixing C libraries, and I'm a little concerned about allowing this at all. While swiftCore doesn't (currently) vend any pointers into the C runtime, it seems like any other library very well might (including a hypothetical Libc module).

Jordan

···

On Jun 29, 2016, at 7:44, Saleem Abdulrasool <compnerd@compnerd.org> wrote:

Hi,

Windows has an interesting (different) model for handling the C library. There are *four* different libraries and you select the library you want across two axis. Traditionally the driver controls the selected library via flags (and options exposed to the developer via the IDE). Im not sure what is the best way to handle that with swift.

This table explains how the library selection works:

                           Debug | Release
                  +----------------------+--------------------+
statically linked | libcmtd.lib (/MTd) | libcmt.lib (/MT)
dyamically linked | msvcrtdl.lib (MDd) | msvcrt.lib (/MD)

Now, there are certain advantages to both linkage models. The static linkage means that you don't have any dependency on the VC runtime redistributable at the cost of small binary. The dynamic linkage means that you have a dependency on the VC runtime redistributable, but you have a smaller binary and future updates can update libc.

The library selection unfortunately goes further than just linkage. The flags control other flags which matter for the C library interfaces (DLL storage).

The crux of the issue is, how to model this behavior in the swift driver, since the only places where this matters will be the ClangImporter and the standard library build, but the latter can be addressed much more easily as it would be internal to the build and not exposed to the users.

If we are looking for precedent, the clang driver introduced a `--dependent-lib` CC1 option (mapping /MTd, /MT, /MDd, /MD to it appropriately).

Note that I am *NOT* advocating a second driver interface, because I think that will just cause unnecessary work and confusion. As long as we have options or some means t control the interface, I think having a single unified driver interface is a significantly better approach.

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