-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gcc-12.2.0-r2: revbump to disable "stdlib=" support on Darwin. #28
Conversation
Historically, Darwin included two C++ libraries, an outdated GCC and its libstdc++, and a new libc++ (from clang). The old library was the default. Thus, when building a modern C++ program using clang, the flag "stdlib=libc++" must be supplied to clang. On the other hand, when an updated GCC is used, it links to an updated GCC libstdc++ by default, no flag is needed. In fact, since "stdlib=libc++" cannot be recognized by GCC, it should not be used. As a result, many build scripts and build systems on macOS check if the flag "stdlib=libc++" is supported. If it's the case, the flag is used. If it's not, no flag is added. Practically, it creates the de-facto behavior of: If the program is built with clang, it's linked to clang's libc++. If the program is built with GCC, it's linked to GCC's native libstdc++. So far so good. This is also the most reasonable behavior, as expected by most users. As time passes, it was realized that using GCC and clang on the same system may create tricky conflicts, it's useful to be able to link against clang's libc++ even if GCC is used (this is useful beyond Darwin, e.g. for FreeBSD). Therefore, GCC now supports "stdlib=libc++ as well. The first immediate (but trivial) problem is a path problem. GCC's Darwin fork (maintained by Ian) enables stdlib= support by default (unlike upstream GCC that only conditionally enables it when an include path "gcc_gxx_libcxx_include_dir" is passed to GCC during build time). However, the default include path is invalid. Building a program with "stdlib=libc++" would fail since GCC cannot find basic C++ headers, like <vector> or <algorithm>. For example: main.cpp:1:10: fatal error: algorithm: No such file or directory 1 | #include <algorithm> | ^~~~~~~~ compilation terminated. In principle, setting the correct clang libc++ path on macOS would fix this problem, but it's far from our only trouble here. Unfortunately, this consequences of this change can be far-reaching and unexpected. In the past, if a program is compiled on clang, it's always linked to libc++, if a program is compiled with gcc, it's always linked to GCC's native libstdc++. But now this assumption has been broken when GCC starts supporting "stdlib=libc++". It means that now programs compiled by GCC will sometimes be linked to libc++, and sometimes be linked to libstdc++, depending on two factors: 1. If a program's build system does not make any attempt to detect the existence of "stdlib=libc++" when it's built with GCC, it will be linked to GCC's native libstdc++. This situation happens if the program was not ported to macOS in the past, or if the program is designed for macOS 10.9.x and newer systems (in which libc++ became clang's default). 2. If a program's build system attempts to detect the existence of "stdlib=libc++", it's now linked to clang's libc++ when it's built by GCC - when previously it would link to GCC's native libstdc++. Thus, when GCC is used, some programs would be linked to libstdc++, but others may suddenly be linked to clang's libc++. depending on the build system of the program. This would create surprising and somewhat unpredictable situations. The solution requires careful thought. There are four possibilities: 1. Disable stdlib= support, so the existing behavior is maintained (more importantly, maintained without the need to patch the build system of countless programs). The disadvantage is that end-users would lose the ability to use stdlib=libc++ to build their own programs when they found it's necessary. 2. Enable stdlib= support. This allows users to enjoy the interoperability benefits of "stdlib=libc++" should it be necessary. But now some programs would suddenly be linked to clang's libc++ when GCC is used, while others would still use GCC. This is unexpected and would be surprising to end-users. And Since Gentoo Prefix currently assumes a consistent GCC environment, it may potentially create compatibility problems as well. To maintain the historical behavior (programs built by GCC always links to GCC's libstdc++), we need to patch the "stdlib=libc++" out of the build system of countless programs... On the other hand, perhaps it's still doable, since many programs are moving away from "stdlib=libc++" as modern macOS defaults to libc++. 3. Enable stdlib= support, and pass stdlib=libstdc++ in the global CXXFLAGS of Portage. 4. Enable stdlib= support, and pass stdlib=libc++ in the global CXXFLAGS of Portage. The last two options sound more reasonable, perhaps in the future, it can be Portage's responsibility to decide which libc++ is used, just like how it currently can decide when to use GCC or clang. Since in GCC, new compiler flags can override previous flag, we can force a "stdlib=" choice to allow well-defined, predictable selection of C++ libraries. Option 2 or 1 is also imaginable, depending on the circumstances. But we clearly need further considerations. For now, we choose the simplest solution, disable support for "stdlib=" to maintain the existing behavior, at least as a stop-gap solution. This may change in the future. Closes: https://bugs.gentoo.org/905152 Signed-off-by: Yifeng Li <tomli@tomli.me>
$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h | ||
|
||
else | ||
- case $target in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we can't pass --disable-stdlib-option
to configure instead?
It looks like (just looking at the diff context here, I might be missing something) when you don't pass it at all, it's automagic on Darwin, but it may still respect turning it off.
If so, that would let us avoid a conditional patch which is generally a pain to rebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we can't pass
--disable-stdlib-option
to configure instead?
I tried, it does not work, because the so-called "option" --disable-stdlib-option
does not actually exist. If you read the code, you would see that the original script defines the macro ENABLE_STDLIB_OPTION
based on whether gcc_gxx_libcxx_include_dir
is passed as a the command-line option, otherwise it disables it. And in GCC Darwin, it also checks whether we're targeting Darwin, if so, it also defines the macro ENABLE_STDLIB_OPTION
.
Unless I missed something, I believe there is no option to disable it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, it's much clearer with the full file context. You're right.
Historically, Darwin included two C++ libraries, an outdated GCC and its libstdc++, and a new libc++ (from clang). The old library was the default. Thus, when building a modern C++ program using clang, the flag "stdlib=libc++" must be supplied to clang. On the other hand, when an updated GCC is used, it links to an updated GCC libstdc++ by default, no flag is needed. In fact, since "stdlib=libc++" cannot be recognized by GCC, it should not be used.
As a result, many build scripts and build systems on macOS check if the flag "stdlib=libc++" is supported. If it's the case, the flag is used. If it's not, no flag is added. Practically, it creates the de-facto behavior of: If the program is built with clang, it's linked to clang's libc++. If the program is built with GCC, it's linked to GCC's native libstdc++. So far so good. This is also the most reasonable behavior, as expected by most users.
As time passes, it was realized that using GCC and clang on the same system may create tricky conflicts, it's useful to be able to link against clang's libc++ even if GCC is used (this is useful beyond Darwin, e.g. for FreeBSD). Therefore, GCC now supports "stdlib=libc++ as well.
The first immediate (but trivial) problem is a path problem. GCC's Darwin fork (maintained by Ian) enables stdlib= support by default (unlike upstream GCC that only conditionally enables it when an include path "gcc_gxx_libcxx_include_dir" is passed to GCC during build time). However, the default include path is invalid. Building a program with "stdlib=libc++" would fail since GCC cannot find basic C++ headers, like or . For example:
In principle, setting the correct clang libc++ path on macOS would fix this problem, but it's far from our only trouble here.
Unfortunately, this consequences of this change can be far-reaching and unexpected. In the past, if a program is compiled on clang, it's always linked to libc++, if a program is compiled with gcc, it's always linked to GCC's native libstdc++. But now this assumption has been broken when GCC starts supporting "stdlib=libc++". It means that now programs compiled by GCC will sometimes be linked to libc++, and sometimes be linked to libstdc++, depending on two factors:
If a program's build system does not make any attempt to detect the existence of "stdlib=libc++" when it's built with GCC, it will be linked to GCC's native libstdc++. This situation happens if the program was not ported to macOS in the past, or if the program is designed for macOS 10.9.x and newer systems (in which libc++ became clang's default).
If a program's build system attempts to detect the existence of "stdlib=libc++", it's now linked to clang's libc++ when it's built by GCC - when previously it would link to GCC's native libstdc++.
Thus, when GCC is used, some programs would be linked to libstdc++, but others may suddenly be linked to clang's libc++. depending on the build system of the program. This would create surprising and somewhat unpredictable situations.
The solution requires careful thought. There are four possibilities:
Disable stdlib= support, so the existing behavior is maintained (more importantly, maintained without the need to patch the build system of countless programs). The disadvantage is that end-users would lose the ability to use stdlib=libc++ to build their own programs when they found it's necessary.
Enable stdlib= support. This allows users to enjoy the interoperability benefits of "stdlib=libc++" should it be necessary. But now some programs would suddenly be linked to clang's libc++ when GCC is used, while others would still use GCC. This is unexpected and would be surprising to end-users. And Since Gentoo Prefix currently assumes a consistent GCC environment, it may potentially create compatibility problems as well. To maintain the historical behavior (programs built by GCC always links to GCC's libstdc++), we need to patch the "stdlib=libc++" out of the build system of countless programs... On the other hand, perhaps it's still doable, since many programs are moving away from "stdlib=libc++" as modern macOS defaults to libc++.
Enable stdlib= support, and pass stdlib=libstdc++ in the global CXXFLAGS of Portage.
Enable stdlib= support, and pass stdlib=libc++ in the global CXXFLAGS of Portage.
The last two options sound more reasonable, perhaps in the future, it can be Portage's responsibility to decide which libc++ is used, just like how it currently can decide when to use GCC or clang. Since in GCC, new compiler flags can override previous flag, we can force a "stdlib=" choice to allow well-defined, predictable selection of C++ libraries. Option 2 or 1 is also imaginable, depending on the circumstances. But we clearly need further considerations.
For now, we choose the simplest solution, disable support for "stdlib=" to maintain the existing behavior, at least as a stop-gap solution. This may change in the future.
Closes: 905152