Message ID | ECCBE90A-239F-4073-B54B-E5C0E2639819@sandoe.co.uk |
---|---|
State | New |
Headers | show |
Series | C++ : Add the -stdlib= option. | expand |
Hi Folks, this patch needs C++ review thanks Iain Iain Sandoe <iain@sandoe.co.uk> wrote: > resending - the first & second attempt didn’t seem to make it to > gcc-patches. > > Hi > > This option allows the user to specify alternate C++ runtime libraries, > for example when a platform uses libc++ as the installed C++ runtime. > > It is the same spelling as a clang option that allows that to use > libstdc++. > > I have had this patch for some time now (more than a year) on Darwin > branches. > > For Darwin [>=11] (and I expect modern FreeBSD) the fact that the installed > C++ runtime is libc++ means conflicts can and do occur when using G++. > > I expect that the facility will also be useful for folks who regularly > try to > ensure that GCC and clang stay compatible, it is a credit to that effort > that > the replacement is pretty much “drop in”. > > Testing: > > The patch applies without regression on *darwin* and x86_64-linux-gnu. > > That doesn’t say much about whether it does what’s intended, of course, > and testing in-tree is not a viable option (it would need a lot of work, > not > to mention the fact that it depends on an external source base). So I’ve > tested this quite extensively on x86 Darwin and Linux. > > It’s a lot easier to use an LLVM branch >= 9 for this since there is a > missing __cxa symbol before that (I originally used LLVM-7 for ‘reasons’). > Since coroutines was committed to GCC we have a <coroutine> header > where the libc++ implementation is still using the <experimental/coroutine> > version, so that one needs to account for this. > > Here’s an LLVM-9 tree with an added <coroutine> header (as an example) > https://github.com/iains/llvm-project/tree/9.0.1-gcc-stdlib > (in case someone wants to try this out in the near future; I don’t think > that > LLVM-10 will be much different, at least the coroutine header is unchanged > there) > > I’ve used this ‘in anger’ on Darwin to build a toolset which includes a > number > of C++ heavy applications (e.g. LLVM, cmake, etc) and it allowed some of > these to work effectively where it had not been possible before. > > One can also do an “installed test” of g++ > for that there are (a relatively modest number of) test fails. > AFAICT, there is nothing significant there - some tests fail because the > output > isn’t expecting to see libc++ __1 inline namespace, some fail because > libc++ > (as per current branches) doesn’t allow use with GCC + std=c++98, some > are warning diagnostics etc. > > [how compatible libc++ is, is somewhat independent of the patch itself; but > it seems “very compatible” is a starting assessment]. > > phew… description longer than patch, it seems. > > OK for master? > thanks > Iain > > —— commit message > > This option allows the user to specify alternate C++ runtime libraries, > for example when a platform uses libc++ as the installed C++ runtime. > > We introduce the command line option: -stdlib= which is the user-facing > mechanism to select the C++ runtime to be used when compiling and linking > code. This is the same option spelling as that used by clang to allow the > use of libstdc++. > > The availability (and thus function) of the option are a configure-time > choice using the configuration control: > --with-gxx-libcxx-include-dir= > > Specification of the path for the libc++ headers, enables the -stdlib= > option (using the path as given), default values are set when the path > is unconfigured. > > If --with-gxx-libcxx-include-dir is given together with --with-sysroot=, > then we test to see if the include path starts with the sysroot and, if so, > record the sysroot-relative component as the local path. At runtime, we > prepend the sysroot that is actually active. > > At link time, we use the C++ runtime in force and (if that is libc++) also > append the libc++abi ABI library. As for other cases, if a target sets the > name pointer for the ABI library to NULL the G++ driver will omit it from > the link line. > > gcc/ChangeLog: > > * configure.ac: Add gxx-libcxx-include-dir handled > in the same way as the regular cxx header directory. > * Makefile.in: Regenerated. > * config.in: Likewise. > * configure: Likewise. > * cppdefault.c: Pick up libc++ headers if the option > is enabled. > * incpath.c (add_standard_paths): Allow for multiple > c++ header include path variants. > * doc/invoke.texi: Document the -stdlib= option. > > gcc/c-family/ChangeLog: > > * c.opt: Add -stdlib= option and enumerations for > libstdc++ and libc++. > > gcc/cp/ChangeLog: > > * g++spec.c (LIBCXX, LIBCXX_PROFILE, LIBCXX_STATIC): New. > (LIBCXXABI, LIBCXXABI_PROFILE, LIBCXXABI_STATIC): New. > (lang_specific_driver): Allow selection amongst multiple > c++ libraries to be added to the link command. > --- > gcc/Makefile.in | 6 +++++ > gcc/c-family/c.opt | 14 +++++++++++ > gcc/config.in | 6 +++++ > gcc/configure | 57 +++++++++++++++++++++++++++++++++++++++++++-- > gcc/configure.ac | 44 ++++++++++++++++++++++++++++++++++ > gcc/cp/g++spec.c | 53 ++++++++++++++++++++++++++++++++++++++--- > gcc/cppdefault.c | 5 ++++ > gcc/doc/invoke.texi | 11 +++++++++ > gcc/incpath.c | 6 +++-- > 9 files changed, 195 insertions(+), 7 deletions(-) > > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt > index fe16357db85..5fada472db1 100644 > --- a/gcc/c-family/c.opt > +++ b/gcc/c-family/c.opt > @@ -2269,6 +2269,20 @@ std=iso9899:2018 > C ObjC Alias(std=c17) > Conform to the ISO 2017 C standard (published in 2018). > > +stdlib= > +Driver C++ ObjC++ Common Report Condition(ENABLE_STDLIB_OPTION) > Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1) > +-stdlib=[libstdc++|libc++] The standard library to be used for C++ headers > +and runtime. > + > +Enum > +Name(stdlib_kind) Type(int) > + > +EnumValue > +Enum(stdlib_kind) String(libstdc++) Value(1) > + > +EnumValue > +Enum(stdlib_kind) String(libc++) Value(2) > + > traditional > Driver > > diff --git a/gcc/configure.ac b/gcc/configure.ac > index 73034bb902b..56b32de4c68 100644 > --- a/gcc/configure.ac > +++ b/gcc/configure.ac > @@ -228,6 +228,48 @@ elif test "${with_sysroot+set}" = set; then > fi > fi > > +# Configuration for an alternate set of C++ headers. > +gcc_gxx_libcxx_include_dir= > +# Specify the alternate g++ header file directory > +AC_ARG_WITH(gxx-libcxx-include-dir, > +[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR], > + [specifies directory to find libc++ header files])], > +[case "${withval}" in > +yes) AC_MSG_ERROR(bad value ${withval} given for libc++ include > directory) ;; > +no) ;; > +*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;; > +esac]) > + > +# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we > +# check to see if the latter starts with the former and, upon success, > compute > +# gcc_gxx_libcxx_include_dir as relative to the sysroot. > +gcc_gxx_libcxx_include_dir_add_sysroot=0 > + > +if test x${gcc_gxx_libcxx_include_dir} != x; then > + AC_DEFINE(ENABLE_STDLIB_OPTION, 1, > + [Define if the -stdlib= option should be enabled.]) > +else > + AC_DEFINE(ENABLE_STDLIB_OPTION, 0) > +fi > +# ??? This logic must match > libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO. > +if test x${gcc_gxx_libcxx_include_dir} = x; then > + if test x${enable_version_specific_runtime_libs} = xyes; then > + gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1' > + else > + libcxx_incdir='libc++_include/c++/$(version)/v1' > + if test x$host != x$target; then > + libcxx_incdir="$target_alias/$libcxx_incdir" > + fi > + > gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir" > + fi > +elif test "${with_sysroot+set}" = set; then > + gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" : > "${with_sysroot}"'\(.*\)'` > + if test "${gcc_gxx_libcxx_without_sysroot}"; then > + gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}" > + gcc_gxx_libcxx_include_dir_add_sysroot=1 > + fi > +fi > + > AC_ARG_WITH(cpp_install_dir, > [AC_HELP_STRING([--with-cpp-install-dir=DIR], > [install the user visible C preprocessor in DIR > @@ -6872,6 +6914,8 @@ AC_SUBST(float_h_file) > AC_SUBST(gcc_config_arguments) > AC_SUBST(gcc_gxx_include_dir) > AC_SUBST(gcc_gxx_include_dir_add_sysroot) > +AC_SUBST(gcc_gxx_libcxx_include_dir) > +AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot) > AC_SUBST(host_exeext) > AC_SUBST(host_xm_file_list) > AC_SUBST(host_xm_include_list) > diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c > index 0ab63bcd211..a2f5c7d3cc7 100644 > --- a/gcc/cp/g++spec.c > +++ b/gcc/cp/g++spec.c > @@ -55,6 +55,26 @@ along with GCC; see the file COPYING3. If not see > #define LIBSTDCXX_STATIC NULL > #endif > > +#ifndef LIBCXX > +#define LIBCXX "c++" > +#endif > +#ifndef LIBCXX_PROFILE > +#define LIBCXX_PROFILE LIBCXX > +#endif > +#ifndef LIBCXX_STATIC > +#define LIBCXX_STATIC NULL > +#endif > + > +#ifndef LIBCXXABI > +#define LIBCXXABI "c++abi" > +#endif > +#ifndef LIBCXXABI_PROFILE > +#define LIBCXXABI_PROFILE LIBCXXABI > +#endif > +#ifndef LIBCXXABI_STATIC > +#define LIBCXXABI_STATIC NULL > +#endif > + > void > lang_specific_driver (struct cl_decoded_option **in_decoded_options, > unsigned int *in_decoded_options_count, > @@ -72,6 +92,11 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > 2 means libstdc++ is needed and should be linked statically. */ > int library = 0; > > + /* Which standard library to link. > + 1 = libstdc++ > + 2 = libc++. */ > + int which_library = 1; > + > /* The number of arguments being added to what's in argv, other than > libraries. We use this to track the number of times we've inserted > -xc++/-xnone. */ > @@ -208,6 +233,10 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > args[i] |= SKIPOPT; > break; > > + case OPT_stdlib_: > + which_library = decoded_options[i].value; > + break; > + > case OPT_SPECIAL_input_file: > { > int len; > @@ -264,6 +293,8 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > > /* Add one for shared_libgcc or extra static library. */ > num_args = argc + added + need_math + (library > 0) * 4 + 1; > + if (which_library > 1 && LIBCXXABI != NULL) > + num_args += 4; > new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args); > > i = 0; > @@ -343,9 +374,25 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > j++; > } > #endif > - generate_option (OPT_l, > - saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1, > - CL_DRIVER, &new_decoded_options[j]); > + if (which_library == 2) > + { > + generate_option (OPT_l, > + saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1, > + CL_DRIVER, &new_decoded_options[j]); > + if (LIBCXXABI != NULL) > + { > + j++; > + added_libraries++; > + generate_option (OPT_l, > + saw_profile_flag ? LIBCXXABI_PROFILE > + : LIBCXXABI, 1, > + CL_DRIVER, &new_decoded_options[j]); > + } > + } > + else > + generate_option (OPT_l, > + saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1, > + CL_DRIVER, &new_decoded_options[j]); > added_libraries++; > j++; > /* Add target-dependent static library, if necessary. */ > diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c > index af38cc494ea..eb6f94162cd 100644 > --- a/gcc/cppdefault.c > +++ b/gcc/cppdefault.c > @@ -55,6 +55,11 @@ const struct default_include cpp_include_defaults[] > { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, > GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, > #endif > +#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR > + /* Pick up libc++ include files, if we have -stdlib=libc++. */ > + { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1, > + GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 }, > +#endif > #ifdef GCC_INCLUDE_DIR > /* This is the dir for gcc's private headers. */ > { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 }, > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 8d0d2136831..a14a25c330f 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -233,6 +233,7 @@ in the following sections. > -fvisibility-inlines-hidden @gol > -fvisibility-ms-compat @gol > -fext-numeric-literals @gol > +-stdlib=@var{libstdc++,libc++} @gol > -Wabi-tag -Wcatch-value -Wcatch-value=@var{n} @gol > -Wno-class-conversion -Wclass-memaccess @gol > -Wcomma-subscript -Wconditionally-supported @gol > @@ -3285,6 +3286,16 @@ for ISO C++11 onwards (@option{-std=c++11}, ...). > Do not search for header files in the standard directories specific to > C++, but do still search the other standard directories. (This option > is used when building the C++ library.) > + > +@item -stdlib=@var{libstdc++,libc++} > +@opindex stdlib > +When G++ is configured to support this option, it allows specification of > +alternate C++ runtime libraries. Two options are available: > @var{libstdc++} > +(the default, native C++ runtime for G++) and @var{libc++} which is the > +C++ runtime installed on some operating systems (e.g. Darwin versions from > +Darwin11 onwards). The option switches G++ to use the headers from the > +specified library and to emit @code{-lstdc++} or @code{-lc++} > respectively, > +when a C++ runtime is required for linking. > @end table > > In addition, these warning options have meanings only for C++ programs: > diff --git a/gcc/incpath.c b/gcc/incpath.c > index 8437939bf1e..14593a1f4c3 100644 > --- a/gcc/incpath.c > +++ b/gcc/incpath.c > @@ -137,7 +137,8 @@ add_standard_paths (const char *sysroot, const char > *iprefix, > IPREFIX and search them first. */ > for (p = cpp_include_defaults; p->fname; p++) > { > - if (!p->cplusplus || cxx_stdinc) > + if (p->cplusplus == 0 > + || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind))) > { > /* Should we be translating sysrooted dirs too? Assume > that iprefix and sysroot are mutually exclusive, for > @@ -168,7 +169,8 @@ add_standard_paths (const char *sysroot, const char > *iprefix, > > for (p = cpp_include_defaults; p->fname; p++) > { > - if (!p->cplusplus || cxx_stdinc) > + if (p->cplusplus == 0 > + || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind))) > { > char *str; > > -- > 2.24.1
On 11/11/20 3:58 PM, Iain Sandoe wrote: > resending - the first & second attempt didn’t seem to make it to > gcc-patches. > > Hi > > This option allows the user to specify alternate C++ runtime libraries, > for example when a platform uses libc++ as the installed C++ runtime. > > It is the same spelling as a clang option that allows that to use > libstdc++. > > I have had this patch for some time now (more than a year) on Darwin > branches. > > For Darwin [>=11] (and I expect modern FreeBSD) the fact that the installed > C++ runtime is libc++ means conflicts can and do occur when using G++. > > I expect that the facility will also be useful for folks who regularly > try to > ensure that GCC and clang stay compatible, it is a credit to that effort > that > the replacement is pretty much “drop in”. > > Testing: > > The patch applies without regression on *darwin* and x86_64-linux-gnu. > > That doesn’t say much about whether it does what’s intended, of course, > and testing in-tree is not a viable option (it would need a lot of work, > not > to mention the fact that it depends on an external source base). So I’ve > tested this quite extensively on x86 Darwin and Linux. > > It’s a lot easier to use an LLVM branch >= 9 for this since there is a > missing __cxa symbol before that (I originally used LLVM-7 for ‘reasons’). > Since coroutines was committed to GCC we have a <coroutine> header > where the libc++ implementation is still using the <experimental/coroutine> > version, so that one needs to account for this. > > Here’s an LLVM-9 tree with an added <coroutine> header (as an example) > https://github.com/iains/llvm-project/tree/9.0.1-gcc-stdlib > (in case someone wants to try this out in the near future; I don’t think > that > LLVM-10 will be much different, at least the coroutine header is unchanged > there) > > I’ve used this ‘in anger’ on Darwin to build a toolset which includes a > number > of C++ heavy applications (e.g. LLVM, cmake, etc) and it allowed some of > these to work effectively where it had not been possible before. > > One can also do an “installed test” of g++ > for that there are (a relatively modest number of) test fails. > AFAICT, there is nothing significant there - some tests fail because the > output > isn’t expecting to see libc++ __1 inline namespace, some fail because > libc++ > (as per current branches) doesn’t allow use with GCC + std=c++98, some > are warning diagnostics etc. > > [how compatible libc++ is, is somewhat independent of the patch itself; but > it seems “very compatible” is a starting assessment]. > > phew… description longer than patch, it seems. > > OK for master? > thanks > Iain > > —— commit message > > This option allows the user to specify alternate C++ runtime libraries, > for example when a platform uses libc++ as the installed C++ runtime. > > We introduce the command line option: -stdlib= which is the user-facing > mechanism to select the C++ runtime to be used when compiling and linking > code. This is the same option spelling as that used by clang to allow the > use of libstdc++. > > The availability (and thus function) of the option are a configure-time > choice using the configuration control: > --with-gxx-libcxx-include-dir= > > Specification of the path for the libc++ headers, enables the -stdlib= > option (using the path as given), default values are set when the path > is unconfigured. > > If --with-gxx-libcxx-include-dir is given together with --with-sysroot=, > then we test to see if the include path starts with the sysroot and, if so, > record the sysroot-relative component as the local path. At runtime, we > prepend the sysroot that is actually active. > > At link time, we use the C++ runtime in force and (if that is libc++) also > append the libc++abi ABI library. As for other cases, if a target sets the > name pointer for the ABI library to NULL the G++ driver will omit it from > the link line. > > gcc/ChangeLog: > > * configure.ac: Add gxx-libcxx-include-dir handled > in the same way as the regular cxx header directory. > * Makefile.in: Regenerated. > * config.in: Likewise. > * configure: Likewise. > * cppdefault.c: Pick up libc++ headers if the option > is enabled. > * incpath.c (add_standard_paths): Allow for multiple > c++ header include path variants. > * doc/invoke.texi: Document the -stdlib= option. > > gcc/c-family/ChangeLog: > > * c.opt: Add -stdlib= option and enumerations for > libstdc++ and libc++. > > gcc/cp/ChangeLog: > > * g++spec.c (LIBCXX, LIBCXX_PROFILE, LIBCXX_STATIC): New. > (LIBCXXABI, LIBCXXABI_PROFILE, LIBCXXABI_STATIC): New. > (lang_specific_driver): Allow selection amongst multiple > c++ libraries to be added to the link command. > --- > gcc/Makefile.in | 6 +++++ > gcc/c-family/c.opt | 14 +++++++++++ > gcc/config.in | 6 +++++ > gcc/configure | 57 +++++++++++++++++++++++++++++++++++++++++++-- > gcc/configure.ac | 44 ++++++++++++++++++++++++++++++++++ > gcc/cp/g++spec.c | 53 ++++++++++++++++++++++++++++++++++++++--- > gcc/cppdefault.c | 5 ++++ > gcc/doc/invoke.texi | 11 +++++++++ > gcc/incpath.c | 6 +++-- > 9 files changed, 195 insertions(+), 7 deletions(-) > > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt > index fe16357db85..5fada472db1 100644 > --- a/gcc/c-family/c.opt > +++ b/gcc/c-family/c.opt > @@ -2269,6 +2269,20 @@ std=iso9899:2018 > C ObjC Alias(std=c17) > Conform to the ISO 2017 C standard (published in 2018). > > +stdlib= > +Driver C++ ObjC++ Common Report Condition(ENABLE_STDLIB_OPTION) > Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1) > +-stdlib=[libstdc++|libc++] The standard library to be used for C++ > headers > +and runtime. > + > +Enum > +Name(stdlib_kind) Type(int) > + > +EnumValue > +Enum(stdlib_kind) String(libstdc++) Value(1) > + > +EnumValue > +Enum(stdlib_kind) String(libc++) Value(2) > + > traditional > Driver > > diff --git a/gcc/configure.ac b/gcc/configure.ac > index 73034bb902b..56b32de4c68 100644 > --- a/gcc/configure.ac > +++ b/gcc/configure.ac > @@ -228,6 +228,48 @@ elif test "${with_sysroot+set}" = set; then > fi > fi > > +# Configuration for an alternate set of C++ headers. > +gcc_gxx_libcxx_include_dir= > +# Specify the alternate g++ header file directory > +AC_ARG_WITH(gxx-libcxx-include-dir, > +[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR], > + [specifies directory to find libc++ header files])], > +[case "${withval}" in > +yes) AC_MSG_ERROR(bad value ${withval} given for libc++ include > directory) ;; > +no) ;; > +*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;; > +esac]) > + > +# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we > +# check to see if the latter starts with the former and, upon success, > compute > +# gcc_gxx_libcxx_include_dir as relative to the sysroot. > +gcc_gxx_libcxx_include_dir_add_sysroot=0 > + > +if test x${gcc_gxx_libcxx_include_dir} != x; then > + AC_DEFINE(ENABLE_STDLIB_OPTION, 1, > + [Define if the -stdlib= option should be enabled.]) > +else > + AC_DEFINE(ENABLE_STDLIB_OPTION, 0) > +fi > +# ??? This logic must match > libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO. > +if test x${gcc_gxx_libcxx_include_dir} = x; then > + if test x${enable_version_specific_runtime_libs} = xyes; then > + gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1' > + else > + libcxx_incdir='libc++_include/c++/$(version)/v1' > + if test x$host != x$target; then > + libcxx_incdir="$target_alias/$libcxx_incdir" > + fi > + > gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir" > > + fi > +elif test "${with_sysroot+set}" = set; then > + gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" > : "${with_sysroot}"'\(.*\)'` > + if test "${gcc_gxx_libcxx_without_sysroot}"; then > + gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}" > + gcc_gxx_libcxx_include_dir_add_sysroot=1 > + fi > +fi > + > AC_ARG_WITH(cpp_install_dir, > [AC_HELP_STRING([--with-cpp-install-dir=DIR], > [install the user visible C preprocessor in DIR > @@ -6872,6 +6914,8 @@ AC_SUBST(float_h_file) > AC_SUBST(gcc_config_arguments) > AC_SUBST(gcc_gxx_include_dir) > AC_SUBST(gcc_gxx_include_dir_add_sysroot) > +AC_SUBST(gcc_gxx_libcxx_include_dir) > +AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot) > AC_SUBST(host_exeext) > AC_SUBST(host_xm_file_list) > AC_SUBST(host_xm_include_list) > diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c > index 0ab63bcd211..a2f5c7d3cc7 100644 > --- a/gcc/cp/g++spec.c > +++ b/gcc/cp/g++spec.c > @@ -55,6 +55,26 @@ along with GCC; see the file COPYING3. If not see > #define LIBSTDCXX_STATIC NULL > #endif > > +#ifndef LIBCXX > +#define LIBCXX "c++" > +#endif > +#ifndef LIBCXX_PROFILE > +#define LIBCXX_PROFILE LIBCXX > +#endif > +#ifndef LIBCXX_STATIC > +#define LIBCXX_STATIC NULL > +#endif > + > +#ifndef LIBCXXABI > +#define LIBCXXABI "c++abi" > +#endif > +#ifndef LIBCXXABI_PROFILE > +#define LIBCXXABI_PROFILE LIBCXXABI > +#endif > +#ifndef LIBCXXABI_STATIC > +#define LIBCXXABI_STATIC NULL > +#endif > + > void > lang_specific_driver (struct cl_decoded_option **in_decoded_options, > unsigned int *in_decoded_options_count, > @@ -72,6 +92,11 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > 2 means libstdc++ is needed and should be linked statically. */ > int library = 0; > > + /* Which standard library to link. > + 1 = libstdc++ > + 2 = libc++. */ > + int which_library = 1; Even if this variable is an int, let's introduce an enum for comparing it to specific values. > + > /* The number of arguments being added to what's in argv, other than > libraries. We use this to track the number of times we've inserted > -xc++/-xnone. */ > @@ -208,6 +233,10 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > args[i] |= SKIPOPT; > break; > > + case OPT_stdlib_: > + which_library = decoded_options[i].value; > + break; > + > case OPT_SPECIAL_input_file: > { > int len; > @@ -264,6 +293,8 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > > /* Add one for shared_libgcc or extra static library. */ > num_args = argc + added + need_math + (library > 0) * 4 + 1; > + if (which_library > 1 && LIBCXXABI != NULL) > + num_args += 4; Why does libc++ need more args than libstdc++? Please add a comment. > new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args); > > i = 0; > @@ -343,9 +374,25 @@ lang_specific_driver (struct cl_decoded_option > **in_decoded_options, > j++; > } > #endif > - generate_option (OPT_l, > - saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1, > - CL_DRIVER, &new_decoded_options[j]); > + if (which_library == 2) > + { > + generate_option (OPT_l, > + saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1, > + CL_DRIVER, &new_decoded_options[j]); > + if (LIBCXXABI != NULL) > + { > + j++; > + added_libraries++; > + generate_option (OPT_l, > + saw_profile_flag ? LIBCXXABI_PROFILE > + : LIBCXXABI, 1, > + CL_DRIVER, &new_decoded_options[j]); > + } > + } > + else > + generate_option (OPT_l, > + saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1, > + CL_DRIVER, &new_decoded_options[j]); > added_libraries++; > j++; > /* Add target-dependent static library, if necessary. */ > diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c > index af38cc494ea..eb6f94162cd 100644 > --- a/gcc/cppdefault.c > +++ b/gcc/cppdefault.c > @@ -55,6 +55,11 @@ const struct default_include cpp_include_defaults[] > { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, > GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, > #endif > +#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR > + /* Pick up libc++ include files, if we have -stdlib=libc++. */ > + { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1, If you're going to give cplusplus a non-boolean value, the comment in cppdefault.h needs to reflect that. > + GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 }, > +#endif > #ifdef GCC_INCLUDE_DIR > /* This is the dir for gcc's private headers. */ > { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 }, > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 8d0d2136831..a14a25c330f 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -233,6 +233,7 @@ in the following sections. > -fvisibility-inlines-hidden @gol > -fvisibility-ms-compat @gol > -fext-numeric-literals @gol > +-stdlib=@var{libstdc++,libc++} @gol > -Wabi-tag -Wcatch-value -Wcatch-value=@var{n} @gol > -Wno-class-conversion -Wclass-memaccess @gol > -Wcomma-subscript -Wconditionally-supported @gol > @@ -3285,6 +3286,16 @@ for ISO C++11 onwards (@option{-std=c++11}, ...). > Do not search for header files in the standard directories specific to > C++, but do still search the other standard directories. (This option > is used when building the C++ library.) > + > +@item -stdlib=@var{libstdc++,libc++} > +@opindex stdlib > +When G++ is configured to support this option, it allows specification of > +alternate C++ runtime libraries. Two options are available: > @var{libstdc++} > +(the default, native C++ runtime for G++) and @var{libc++} which is the > +C++ runtime installed on some operating systems (e.g. Darwin versions from > +Darwin11 onwards). The option switches G++ to use the headers from the > +specified library and to emit @code{-lstdc++} or @code{-lc++} > respectively, > +when a C++ runtime is required for linking. > @end table > > In addition, these warning options have meanings only for C++ programs: > diff --git a/gcc/incpath.c b/gcc/incpath.c > index 8437939bf1e..14593a1f4c3 100644 > --- a/gcc/incpath.c > +++ b/gcc/incpath.c > @@ -137,7 +137,8 @@ add_standard_paths (const char *sysroot, const char > *iprefix, > IPREFIX and search them first. */ > for (p = cpp_include_defaults; p->fname; p++) > { > - if (!p->cplusplus || cxx_stdinc) > + if (p->cplusplus == 0 > + || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind))) > { > /* Should we be translating sysrooted dirs too? Assume > that iprefix and sysroot are mutually exclusive, for > @@ -168,7 +169,8 @@ add_standard_paths (const char *sysroot, const char > *iprefix, > > for (p = cpp_include_defaults; p->fname; p++) > { > - if (!p->cplusplus || cxx_stdinc) > + if (p->cplusplus == 0 > + || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind))) > { > char *str; >
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index fe16357db85..5fada472db1 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -2269,6 +2269,20 @@ std=iso9899:2018 C ObjC Alias(std=c17) Conform to the ISO 2017 C standard (published in 2018). +stdlib= +Driver C++ ObjC++ Common Report Condition(ENABLE_STDLIB_OPTION) Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1) +-stdlib=[libstdc++|libc++] The standard library to be used for C++ headers +and runtime. + +Enum +Name(stdlib_kind) Type(int) + +EnumValue +Enum(stdlib_kind) String(libstdc++) Value(1) + +EnumValue +Enum(stdlib_kind) String(libc++) Value(2) + traditional Driver diff --git a/gcc/configure.ac b/gcc/configure.ac index 73034bb902b..56b32de4c68 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -228,6 +228,48 @@ elif test "${with_sysroot+set}" = set; then fi fi +# Configuration for an alternate set of C++ headers. +gcc_gxx_libcxx_include_dir= +# Specify the alternate g++ header file directory +AC_ARG_WITH(gxx-libcxx-include-dir, +[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR], + [specifies directory to find libc++ header files])], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for libc++ include directory) ;; +no) ;; +*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;; +esac]) + +# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we +# check to see if the latter starts with the former and, upon success, compute +# gcc_gxx_libcxx_include_dir as relative to the sysroot. +gcc_gxx_libcxx_include_dir_add_sysroot=0 + +if test x${gcc_gxx_libcxx_include_dir} != x; then + AC_DEFINE(ENABLE_STDLIB_OPTION, 1, + [Define if the -stdlib= option should be enabled.]) +else + AC_DEFINE(ENABLE_STDLIB_OPTION, 0) +fi +# ??? This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO. +if test x${gcc_gxx_libcxx_include_dir} = x; then + if test x${enable_version_specific_runtime_libs} = xyes; then + gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1' + else + libcxx_incdir='libc++_include/c++/$(version)/v1' + if test x$host != x$target; then + libcxx_incdir="$target_alias/$libcxx_incdir" + fi + gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir" + fi +elif test "${with_sysroot+set}" = set; then + gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" : "${with_sysroot}"'\(.*\)'` + if test "${gcc_gxx_libcxx_without_sysroot}"; then + gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}" + gcc_gxx_libcxx_include_dir_add_sysroot=1 + fi +fi + AC_ARG_WITH(cpp_install_dir, [AC_HELP_STRING([--with-cpp-install-dir=DIR], [install the user visible C preprocessor in DIR @@ -6872,6 +6914,8 @@ AC_SUBST(float_h_file) AC_SUBST(gcc_config_arguments) AC_SUBST(gcc_gxx_include_dir) AC_SUBST(gcc_gxx_include_dir_add_sysroot) +AC_SUBST(gcc_gxx_libcxx_include_dir) +AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot) AC_SUBST(host_exeext) AC_SUBST(host_xm_file_list) AC_SUBST(host_xm_include_list) diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c index 0ab63bcd211..a2f5c7d3cc7 100644 --- a/gcc/cp/g++spec.c +++ b/gcc/cp/g++spec.c @@ -55,6 +55,26 @@ along with GCC; see the file COPYING3. If not see #define LIBSTDCXX_STATIC NULL #endif +#ifndef LIBCXX +#define LIBCXX "c++" +#endif +#ifndef LIBCXX_PROFILE +#define LIBCXX_PROFILE LIBCXX +#endif +#ifndef LIBCXX_STATIC +#define LIBCXX_STATIC NULL +#endif + +#ifndef LIBCXXABI +#define LIBCXXABI "c++abi" +#endif +#ifndef LIBCXXABI_PROFILE +#define LIBCXXABI_PROFILE LIBCXXABI +#endif +#ifndef LIBCXXABI_STATIC +#define LIBCXXABI_STATIC NULL +#endif + void lang_specific_driver (struct cl_decoded_option **in_decoded_options, unsigned int *in_decoded_options_count, @@ -72,6 +92,11 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, 2 means libstdc++ is needed and should be linked statically. */ int library = 0; + /* Which standard library to link. + 1 = libstdc++ + 2 = libc++. */ + int which_library = 1; + /* The number of arguments being added to what's in argv, other than libraries. We use this to track the number of times we've inserted -xc++/-xnone. */ @@ -208,6 +233,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, args[i] |= SKIPOPT; break; + case OPT_stdlib_: + which_library = decoded_options[i].value; + break; + case OPT_SPECIAL_input_file: { int len; @@ -264,6 +293,8 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, /* Add one for shared_libgcc or extra static library. */ num_args = argc + added + need_math + (library > 0) * 4 + 1; + if (which_library > 1 && LIBCXXABI != NULL) + num_args += 4; new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args); i = 0; @@ -343,9 +374,25 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, j++; } #endif - generate_option (OPT_l, - saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1, - CL_DRIVER, &new_decoded_options[j]); + if (which_library == 2) + { + generate_option (OPT_l, + saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1, + CL_DRIVER, &new_decoded_options[j]); + if (LIBCXXABI != NULL) + { + j++; + added_libraries++; + generate_option (OPT_l, + saw_profile_flag ? LIBCXXABI_PROFILE + : LIBCXXABI, 1, + CL_DRIVER, &new_decoded_options[j]); + } + } + else + generate_option (OPT_l, + saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1, + CL_DRIVER, &new_decoded_options[j]); added_libraries++; j++; /* Add target-dependent static library, if necessary. */ diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c index af38cc494ea..eb6f94162cd 100644 --- a/gcc/cppdefault.c +++ b/gcc/cppdefault.c @@ -55,6 +55,11 @@ const struct default_include cpp_include_defaults[] { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, #endif +#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR + /* Pick up libc++ include files, if we have -stdlib=libc++. */ + { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1, + GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 }, +#endif #ifdef GCC_INCLUDE_DIR /* This is the dir for gcc's private headers. */ { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 }, diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 8d0d2136831..a14a25c330f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -233,6 +233,7 @@ in the following sections. -fvisibility-inlines-hidden @gol -fvisibility-ms-compat @gol -fext-numeric-literals @gol +-stdlib=@var{libstdc++,libc++} @gol -Wabi-tag -Wcatch-value -Wcatch-value=@var{n} @gol -Wno-class-conversion -Wclass-memaccess @gol -Wcomma-subscript -Wconditionally-supported @gol @@ -3285,6 +3286,16 @@ for ISO C++11 onwards (@option{-std=c++11}, ...). Do not search for header files in the standard directories specific to C++, but do still search the other standard directories. (This option is used when building the C++ library.) + +@item -stdlib=@var{libstdc++,libc++} +@opindex stdlib +When G++ is configured to support this option, it allows specification of +alternate C++ runtime libraries. Two options are available: @var{libstdc++} +(the default, native C++ runtime for G++) and @var{libc++} which is the +C++ runtime installed on some operating systems (e.g. Darwin versions from +Darwin11 onwards). The option switches G++ to use the headers from the +specified library and to emit @code{-lstdc++} or @code{-lc++} respectively, +when a C++ runtime is required for linking. @end table In addition, these warning options have meanings only for C++ programs: diff --git a/gcc/incpath.c b/gcc/incpath.c index 8437939bf1e..14593a1f4c3 100644 --- a/gcc/incpath.c +++ b/gcc/incpath.c @@ -137,7 +137,8 @@ add_standard_paths (const char *sysroot, const char *iprefix, IPREFIX and search them first. */ for (p = cpp_include_defaults; p->fname; p++) { - if (!p->cplusplus || cxx_stdinc) + if (p->cplusplus == 0 + || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind))) { /* Should we be translating sysrooted dirs too? Assume