diff mbox series

[v2] C++ : Add the -stdlib= option.

Message ID FE07E514-2D96-467A-A6AC-F1BB11FCF953@sandoe.co.uk
State New
Headers show
Series [v2] C++ : Add the -stdlib= option. | expand

Commit Message

Iain Sandoe Dec. 22, 2020, 8:39 p.m. UTC
Hi Jason,

Jason Merrill <jason@redhat.com> wrote:

> On 11/11/20 3:58 PM, Iain Sandoe wrote:

>> 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.
>> 

>> +  /* 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.

done - it is also noted that it must track the enum in the opt file.

>> @@ -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.

done (JFTR, it’s because libc++ doesn’t include the abi library for most platforms, so that also has to be
appended to the link line).

>> +#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.

done.

(re-)tested on x86_64-darwin{11,16,17,19, 20} with the installed libc++ and x86_64-linux-gnu with an
LLVM-9 build.  Bootstrapped and smoke-tested for libc++ (regular testing for libstdc++).

OK for master now?
thanks
Iain

==== revised patch


This option allows the user to specifiy 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.
	* cppdefault.h (struct default_include): Amend comments
	to reflect the extended use of the cplusplus field.
	* 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.
	(enum stdcxxlib_kind): New.
	(lang_specific_driver): Allow selection amongst multiple
	c++ runtime libraries.
---
 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    | 74 ++++++++++++++++++++++++++++++++++++++++-----
 gcc/cppdefault.c    |  5 +++
 gcc/cppdefault.h    |  7 ++++-
 gcc/doc/invoke.texi | 10 ++++++
 gcc/incpath.c       |  6 ++--
 10 files changed, 216 insertions(+), 13 deletions(-)

Comments

Jason Merrill Dec. 22, 2020, 8:53 p.m. UTC | #1
On 12/22/20 3:39 PM, Iain Sandoe wrote:
> Hi Jason,
> 
> Jason Merrill <jason@redhat.com> wrote:
> 
>> On 11/11/20 3:58 PM, Iain Sandoe wrote:
> 
>>> 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.
>>>
> 
>>> +  /* 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.
> 
> done - it is also noted that it must track the enum in the opt file.
> 
>>> @@ -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.
> 
> done (JFTR, it’s because libc++ doesn’t include the abi library for most platforms, so that also has to be
> appended to the link line).
> 
>>> +#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.
> 
> done.
> 
> (re-)tested on x86_64-darwin{11,16,17,19, 20} with the installed libc++ and x86_64-linux-gnu with an
> LLVM-9 build.  Bootstrapped and smoke-tested for libc++ (regular testing for libstdc++).
> 
> OK for master now?

OK.

> thanks
> Iain
> 
> ==== revised patch
> 
> 
> This option allows the user to specifiy 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.
> 	* cppdefault.h (struct default_include): Amend comments
> 	to reflect the extended use of the cplusplus field.
> 	* 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.
> 	(enum stdcxxlib_kind): New.
> 	(lang_specific_driver): Allow selection amongst multiple
> 	c++ runtime libraries.
> ---
>   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    | 74 ++++++++++++++++++++++++++++++++++++++++-----
>   gcc/cppdefault.c    |  5 +++
>   gcc/cppdefault.h    |  7 ++++-
>   gcc/doc/invoke.texi | 10 ++++++
>   gcc/incpath.c       |  6 ++--
>   10 files changed, 216 insertions(+), 13 deletions(-)
> 
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 178e4eaa513..6847022f108 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -679,6 +679,9 @@ build_tooldir = $(exec_prefix)/$(target_noncanonical)
>   # Directory in which the compiler finds target-independent g++ includes.
>   gcc_gxx_include_dir = @gcc_gxx_include_dir@
>   gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@
> +# Directory in which the compiler finds libc++ includes.
> +gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@
> +gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@
>   # Directory to search for site-specific includes.
>   local_includedir = $(local_prefix)/include
>   includedir = $(prefix)/include
> @@ -1185,6 +1188,7 @@ FLAGS_TO_PASS = \
>   	"prefix=$(prefix)" \
>   	"local_prefix=$(local_prefix)" \
>   	"gxx_include_dir=$(gcc_gxx_include_dir)" \
> +	"gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \
>   	"build_tooldir=$(build_tooldir)" \
>   	"gcc_tooldir=$(gcc_tooldir)" \
>   	"bindir=$(bindir)" \
> @@ -3004,6 +3008,8 @@ PREPROCESSOR_DEFINES = \
>     -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \
>     -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \
>     -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
> +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \
> +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \
>     -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
>     -DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
>     -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index 21d8cd03709..e0c322f61ae 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -2356,6 +2356,20 @@ std=iso9899:2018
>   C ObjC Alias(std=c17)
>   Conform to the ISO 2017 C standard (published in 2018).
>   
> +stdlib=
> +Driver C++ ObjC++ Common 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/config.in b/gcc/config.in
> index 216505abd2c..10a13cde586 100644
> --- a/gcc/config.in
> +++ b/gcc/config.in
> @@ -240,6 +240,12 @@
>      standards-compatible mode on s390 targets. */
>   #undef ENABLE_S390_EXCESS_FLOAT_PRECISION
>   
> +/* Define if the -stdlib= option should be enabled. */
> +#ifndef USED_FOR_TARGET
> +#undef ENABLE_STDLIB_OPTION
> +#endif
> +
> +
>   /* Define if you want all operations on trees (the basic data structure of the
>      front ends) to be checked for dynamic type safety at runtime. This is
>      moderately expensive. */
> diff --git a/gcc/configure b/gcc/configure
> index fbe92089640..ee9760354b6 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -675,6 +675,8 @@ host_xm_defines
>   host_xm_include_list
>   host_xm_file_list
>   host_exeext
> +gcc_gxx_libcxx_include_dir_add_sysroot
> +gcc_gxx_libcxx_include_dir
>   gcc_gxx_include_dir_add_sysroot
>   gcc_gxx_include_dir
>   gcc_config_arguments
> @@ -937,6 +939,7 @@ with_native_system_header_dir
>   with_build_sysroot
>   with_sysroot
>   with_gxx_include_dir
> +with_gxx_libcxx_include_dir
>   with_cpp_install_dir
>   enable_generated_files_in_srcdir
>   with_gnu_ld
> @@ -1801,6 +1804,8 @@ Optional Packages:
>     --with-sysroot[=DIR]    search for usr/lib, usr/include, et al, within DIR
>     --with-gxx-include-dir=DIR
>                             specifies directory to put g++ header files
> +  --with-gxx-libcxx-include-dir=DIR
> +                          specifies directory to find libc++ header files
>     --with-cpp-install-dir=DIR
>                             install the user visible C preprocessor in DIR
>                             (relative to PREFIX) as well as PREFIX/bin
> @@ -3731,6 +3736,52 @@ 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
> +
> +# Check whether --with-gxx-libcxx-include-dir was given.
> +if test "${with_gxx_libcxx_include_dir+set}" = set; then :
> +  withval=$with_gxx_libcxx_include_dir; case "${withval}" in
> +yes)	as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;
> +no)	;;
> +*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
> +esac
> +fi
> +
> +
> +# 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
> +
> +$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h
> +
> +else
> +  $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h
> +
> +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
> +
>   
>   # Check whether --with-cpp_install_dir was given.
>   if test "${with_cpp_install_dir+set}" = set; then :
> @@ -19186,7 +19237,7 @@ else
>     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>     lt_status=$lt_dlunknown
>     cat > conftest.$ac_ext <<_LT_EOF
> -#line 19189 "configure"
> +#line 19240 "configure"
>   #include "confdefs.h"
>   
>   #if HAVE_DLFCN_H
> @@ -19292,7 +19343,7 @@ else
>     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>     lt_status=$lt_dlunknown
>     cat > conftest.$ac_ext <<_LT_EOF
> -#line 19295 "configure"
> +#line 19346 "configure"
>   #include "confdefs.h"
>   
>   #if HAVE_DLFCN_H
> @@ -31175,6 +31226,8 @@ fi
>   
>   
>   
> +
> +
>   
>   
>   
> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index 89b9981e872..6fcf154d987 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
> @@ -7096,6 +7138,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 0f17148ccbd..a8254cd34c9 100644
> --- a/gcc/cp/g++spec.c
> +++ b/gcc/cp/g++spec.c
> @@ -49,6 +49,34 @@ 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
> +
> +/* The values used here must match those of the stdlib_kind enumeration
> +   in c.opt.  */
> +enum stdcxxlib_kind
> +{
> +  USE_LIBSTDCXX = 1,
> +  USE_LIBCXX = 2
> +};
> +
>   void
>   lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>   		      unsigned int *in_decoded_options_count,
> @@ -59,13 +87,16 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>     /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
>     int saw_profile_flag = 0;
>   
> -  /* What do with libstdc++:
> -     -1 means we should not link in libstdc++
> -     0  means we should link in libstdc++ if it is needed
> -     1  means libstdc++ is needed and should be linked in.
> -     2  means libstdc++ is needed and should be linked statically.  */
> +  /* What action to take for the c++ runtime library:
> +    -1  means we should not link it in.
> +     0  means we should link it if it is needed.
> +     1  means it is needed and should be linked in.
> +     2  means it is needed but should be linked statically.  */
>     int library = 0;
>   
> +  /* Which c++ runtime library to link.  */
> +  stdcxxlib_kind which_library = USE_LIBSTDCXX;
> +
>     /* 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.  */
> @@ -194,6 +225,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>   	  args[i] |= SKIPOPT;
>   	  break;
>   
> +	case OPT_stdlib_:
> +	  which_library = (stdcxxlib_kind) decoded_options[i].value;
> +	  break;
> +
>   	case OPT_SPECIAL_input_file:
>   	  {
>   	    int len;
> @@ -250,6 +285,13 @@ 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;
> +  /* For libc++, on most platforms, the ABI library (usually called libc++abi)
> +     is provided as a separate DSO, which we must also append.
> +     However, a platform might have the ability to forward the ABI library
> +     from libc++, or combine it in some other way; in that case, LIBCXXABI
> +     should be set to NULL to signal that it need not be appended.  */
> +  if (which_library == USE_LIBCXX && LIBCXXABI != NULL)
> +    num_args += 4;
>     new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
>   
>     i = 0;
> @@ -323,9 +365,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 == USE_LIBCXX)
> +	{
> +	  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/cppdefault.h b/gcc/cppdefault.h
> index a681264f75e..35cf24ec29e 100644
> --- a/gcc/cppdefault.h
> +++ b/gcc/cppdefault.h
> @@ -36,7 +36,12 @@ struct default_include
>     const char *const fname;	/* The name of the directory.  */
>     const char *const component;	/* The component containing the directory
>   				   (see update_path in prefix.c) */
> -  const char cplusplus;		/* Only look here if we're compiling C++.  */
> +  const char cplusplus;		/* When this is non-zero, we should only
> +				   consider this if we're compiling C++.
> +				   When the -stdlib option is configured, this
> +				   may take values greater than 1 to indicate
> +				   which C++ standard library should be
> +				   used.  */
>     const char cxx_aware;		/* Includes in this directory don't need to
>   				   be wrapped in extern "C" when compiling
>   				   C++.  */
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index d7d354fc4de..3b8b003c51d 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -242,6 +242,7 @@ in the following sections.
>   -fext-numeric-literals @gol
>   -flang-info-include-translate@r{[}=@var{name}@r{]} @gol
>   -flang-info-include-translate-not @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
> @@ -3368,6 +3369,15 @@ is used when building the C++ library.)
>   @opindex flang-info-include-translate-not
>   Diagnose include translation events.
>   
> +@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;
>   
>
Eric Gallager March 29, 2021, 6:44 p.m. UTC | #2
Hi Iain, could you add a note about this change to the
gcc-11/changes.html page? There are probably some people who would be
interested in this who could use a note about it. Thanks

On Tue, Dec 22, 2020 at 3:53 PM Jason Merrill via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On 12/22/20 3:39 PM, Iain Sandoe wrote:
> > Hi Jason,
> >
> > Jason Merrill <jason@redhat.com> wrote:
> >
> >> On 11/11/20 3:58 PM, Iain Sandoe wrote:
> >
> >>> 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.
> >>>
> >
> >>> +  /* 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.
> >
> > done - it is also noted that it must track the enum in the opt file.
> >
> >>> @@ -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.
> >
> > done (JFTR, it’s because libc++ doesn’t include the abi library for most platforms, so that also has to be
> > appended to the link line).
> >
> >>> +#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.
> >
> > done.
> >
> > (re-)tested on x86_64-darwin{11,16,17,19, 20} with the installed libc++ and x86_64-linux-gnu with an
> > LLVM-9 build.  Bootstrapped and smoke-tested for libc++ (regular testing for libstdc++).
> >
> > OK for master now?
>
> OK.
>
> > thanks
> > Iain
> >
> > ==== revised patch
> >
> >
> > This option allows the user to specifiy 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.
> >       * cppdefault.h (struct default_include): Amend comments
> >       to reflect the extended use of the cplusplus field.
> >       * 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.
> >       (enum stdcxxlib_kind): New.
> >       (lang_specific_driver): Allow selection amongst multiple
> >       c++ runtime libraries.
> > ---
> >   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    | 74 ++++++++++++++++++++++++++++++++++++++++-----
> >   gcc/cppdefault.c    |  5 +++
> >   gcc/cppdefault.h    |  7 ++++-
> >   gcc/doc/invoke.texi | 10 ++++++
> >   gcc/incpath.c       |  6 ++--
> >   10 files changed, 216 insertions(+), 13 deletions(-)
> >
> > diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> > index 178e4eaa513..6847022f108 100644
> > --- a/gcc/Makefile.in
> > +++ b/gcc/Makefile.in
> > @@ -679,6 +679,9 @@ build_tooldir = $(exec_prefix)/$(target_noncanonical)
> >   # Directory in which the compiler finds target-independent g++ includes.
> >   gcc_gxx_include_dir = @gcc_gxx_include_dir@
> >   gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@
> > +# Directory in which the compiler finds libc++ includes.
> > +gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@
> > +gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@
> >   # Directory to search for site-specific includes.
> >   local_includedir = $(local_prefix)/include
> >   includedir = $(prefix)/include
> > @@ -1185,6 +1188,7 @@ FLAGS_TO_PASS = \
> >       "prefix=$(prefix)" \
> >       "local_prefix=$(local_prefix)" \
> >       "gxx_include_dir=$(gcc_gxx_include_dir)" \
> > +     "gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \
> >       "build_tooldir=$(build_tooldir)" \
> >       "gcc_tooldir=$(gcc_tooldir)" \
> >       "bindir=$(bindir)" \
> > @@ -3004,6 +3008,8 @@ PREPROCESSOR_DEFINES = \
> >     -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \
> >     -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \
> >     -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
> > +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \
> > +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \
> >     -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
> >     -DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
> >     -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
> > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> > index 21d8cd03709..e0c322f61ae 100644
> > --- a/gcc/c-family/c.opt
> > +++ b/gcc/c-family/c.opt
> > @@ -2356,6 +2356,20 @@ std=iso9899:2018
> >   C ObjC Alias(std=c17)
> >   Conform to the ISO 2017 C standard (published in 2018).
> >
> > +stdlib=
> > +Driver C++ ObjC++ Common 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/config.in b/gcc/config.in
> > index 216505abd2c..10a13cde586 100644
> > --- a/gcc/config.in
> > +++ b/gcc/config.in
> > @@ -240,6 +240,12 @@
> >      standards-compatible mode on s390 targets. */
> >   #undef ENABLE_S390_EXCESS_FLOAT_PRECISION
> >
> > +/* Define if the -stdlib= option should be enabled. */
> > +#ifndef USED_FOR_TARGET
> > +#undef ENABLE_STDLIB_OPTION
> > +#endif
> > +
> > +
> >   /* Define if you want all operations on trees (the basic data structure of the
> >      front ends) to be checked for dynamic type safety at runtime. This is
> >      moderately expensive. */
> > diff --git a/gcc/configure b/gcc/configure
> > index fbe92089640..ee9760354b6 100755
> > --- a/gcc/configure
> > +++ b/gcc/configure
> > @@ -675,6 +675,8 @@ host_xm_defines
> >   host_xm_include_list
> >   host_xm_file_list
> >   host_exeext
> > +gcc_gxx_libcxx_include_dir_add_sysroot
> > +gcc_gxx_libcxx_include_dir
> >   gcc_gxx_include_dir_add_sysroot
> >   gcc_gxx_include_dir
> >   gcc_config_arguments
> > @@ -937,6 +939,7 @@ with_native_system_header_dir
> >   with_build_sysroot
> >   with_sysroot
> >   with_gxx_include_dir
> > +with_gxx_libcxx_include_dir
> >   with_cpp_install_dir
> >   enable_generated_files_in_srcdir
> >   with_gnu_ld
> > @@ -1801,6 +1804,8 @@ Optional Packages:
> >     --with-sysroot[=DIR]    search for usr/lib, usr/include, et al, within DIR
> >     --with-gxx-include-dir=DIR
> >                             specifies directory to put g++ header files
> > +  --with-gxx-libcxx-include-dir=DIR
> > +                          specifies directory to find libc++ header files
> >     --with-cpp-install-dir=DIR
> >                             install the user visible C preprocessor in DIR
> >                             (relative to PREFIX) as well as PREFIX/bin
> > @@ -3731,6 +3736,52 @@ 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
> > +
> > +# Check whether --with-gxx-libcxx-include-dir was given.
> > +if test "${with_gxx_libcxx_include_dir+set}" = set; then :
> > +  withval=$with_gxx_libcxx_include_dir; case "${withval}" in
> > +yes) as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;
> > +no)  ;;
> > +*)   gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
> > +esac
> > +fi
> > +
> > +
> > +# 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
> > +
> > +$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h
> > +
> > +else
> > +  $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h
> > +
> > +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
> > +
> >
> >   # Check whether --with-cpp_install_dir was given.
> >   if test "${with_cpp_install_dir+set}" = set; then :
> > @@ -19186,7 +19237,7 @@ else
> >     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> >     lt_status=$lt_dlunknown
> >     cat > conftest.$ac_ext <<_LT_EOF
> > -#line 19189 "configure"
> > +#line 19240 "configure"
> >   #include "confdefs.h"
> >
> >   #if HAVE_DLFCN_H
> > @@ -19292,7 +19343,7 @@ else
> >     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> >     lt_status=$lt_dlunknown
> >     cat > conftest.$ac_ext <<_LT_EOF
> > -#line 19295 "configure"
> > +#line 19346 "configure"
> >   #include "confdefs.h"
> >
> >   #if HAVE_DLFCN_H
> > @@ -31175,6 +31226,8 @@ fi
> >
> >
> >
> > +
> > +
> >
> >
> >
> > diff --git a/gcc/configure.ac b/gcc/configure.ac
> > index 89b9981e872..6fcf154d987 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
> > @@ -7096,6 +7138,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 0f17148ccbd..a8254cd34c9 100644
> > --- a/gcc/cp/g++spec.c
> > +++ b/gcc/cp/g++spec.c
> > @@ -49,6 +49,34 @@ 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
> > +
> > +/* The values used here must match those of the stdlib_kind enumeration
> > +   in c.opt.  */
> > +enum stdcxxlib_kind
> > +{
> > +  USE_LIBSTDCXX = 1,
> > +  USE_LIBCXX = 2
> > +};
> > +
> >   void
> >   lang_specific_driver (struct cl_decoded_option **in_decoded_options,
> >                     unsigned int *in_decoded_options_count,
> > @@ -59,13 +87,16 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
> >     /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
> >     int saw_profile_flag = 0;
> >
> > -  /* What do with libstdc++:
> > -     -1 means we should not link in libstdc++
> > -     0  means we should link in libstdc++ if it is needed
> > -     1  means libstdc++ is needed and should be linked in.
> > -     2  means libstdc++ is needed and should be linked statically.  */
> > +  /* What action to take for the c++ runtime library:
> > +    -1  means we should not link it in.
> > +     0  means we should link it if it is needed.
> > +     1  means it is needed and should be linked in.
> > +     2  means it is needed but should be linked statically.  */
> >     int library = 0;
> >
> > +  /* Which c++ runtime library to link.  */
> > +  stdcxxlib_kind which_library = USE_LIBSTDCXX;
> > +
> >     /* 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.  */
> > @@ -194,6 +225,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
> >         args[i] |= SKIPOPT;
> >         break;
> >
> > +     case OPT_stdlib_:
> > +       which_library = (stdcxxlib_kind) decoded_options[i].value;
> > +       break;
> > +
> >       case OPT_SPECIAL_input_file:
> >         {
> >           int len;
> > @@ -250,6 +285,13 @@ 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;
> > +  /* For libc++, on most platforms, the ABI library (usually called libc++abi)
> > +     is provided as a separate DSO, which we must also append.
> > +     However, a platform might have the ability to forward the ABI library
> > +     from libc++, or combine it in some other way; in that case, LIBCXXABI
> > +     should be set to NULL to signal that it need not be appended.  */
> > +  if (which_library == USE_LIBCXX && LIBCXXABI != NULL)
> > +    num_args += 4;
> >     new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
> >
> >     i = 0;
> > @@ -323,9 +365,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 == USE_LIBCXX)
> > +     {
> > +       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/cppdefault.h b/gcc/cppdefault.h
> > index a681264f75e..35cf24ec29e 100644
> > --- a/gcc/cppdefault.h
> > +++ b/gcc/cppdefault.h
> > @@ -36,7 +36,12 @@ struct default_include
> >     const char *const fname;  /* The name of the directory.  */
> >     const char *const component;      /* The component containing the directory
> >                                  (see update_path in prefix.c) */
> > -  const char cplusplus;              /* Only look here if we're compiling C++.  */
> > +  const char cplusplus;              /* When this is non-zero, we should only
> > +                                consider this if we're compiling C++.
> > +                                When the -stdlib option is configured, this
> > +                                may take values greater than 1 to indicate
> > +                                which C++ standard library should be
> > +                                used.  */
> >     const char cxx_aware;             /* Includes in this directory don't need to
> >                                  be wrapped in extern "C" when compiling
> >                                  C++.  */
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index d7d354fc4de..3b8b003c51d 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -242,6 +242,7 @@ in the following sections.
> >   -fext-numeric-literals @gol
> >   -flang-info-include-translate@r{[}=@var{name}@r{]} @gol
> >   -flang-info-include-translate-not @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
> > @@ -3368,6 +3369,15 @@ is used when building the C++ library.)
> >   @opindex flang-info-include-translate-not
> >   Diagnose include translation events.
> >
> > +@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 mbox series

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 178e4eaa513..6847022f108 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -679,6 +679,9 @@  build_tooldir = $(exec_prefix)/$(target_noncanonical)
 # Directory in which the compiler finds target-independent g++ includes.
 gcc_gxx_include_dir = @gcc_gxx_include_dir@
 gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@
+# Directory in which the compiler finds libc++ includes.
+gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@
+gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@
 # Directory to search for site-specific includes.
 local_includedir = $(local_prefix)/include
 includedir = $(prefix)/include
@@ -1185,6 +1188,7 @@  FLAGS_TO_PASS = \
 	"prefix=$(prefix)" \
 	"local_prefix=$(local_prefix)" \
 	"gxx_include_dir=$(gcc_gxx_include_dir)" \
+	"gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \
 	"build_tooldir=$(build_tooldir)" \
 	"gcc_tooldir=$(gcc_tooldir)" \
 	"bindir=$(bindir)" \
@@ -3004,6 +3008,8 @@  PREPROCESSOR_DEFINES = \
   -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \
   -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \
   -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
+  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \
+  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \
   -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
   -DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
   -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 21d8cd03709..e0c322f61ae 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -2356,6 +2356,20 @@  std=iso9899:2018
 C ObjC Alias(std=c17)
 Conform to the ISO 2017 C standard (published in 2018).
 
+stdlib=
+Driver C++ ObjC++ Common 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/config.in b/gcc/config.in
index 216505abd2c..10a13cde586 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -240,6 +240,12 @@ 
    standards-compatible mode on s390 targets. */
 #undef ENABLE_S390_EXCESS_FLOAT_PRECISION
 
+/* Define if the -stdlib= option should be enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_STDLIB_OPTION
+#endif
+
+
 /* Define if you want all operations on trees (the basic data structure of the
    front ends) to be checked for dynamic type safety at runtime. This is
    moderately expensive. */
diff --git a/gcc/configure b/gcc/configure
index fbe92089640..ee9760354b6 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -675,6 +675,8 @@  host_xm_defines
 host_xm_include_list
 host_xm_file_list
 host_exeext
+gcc_gxx_libcxx_include_dir_add_sysroot
+gcc_gxx_libcxx_include_dir
 gcc_gxx_include_dir_add_sysroot
 gcc_gxx_include_dir
 gcc_config_arguments
@@ -937,6 +939,7 @@  with_native_system_header_dir
 with_build_sysroot
 with_sysroot
 with_gxx_include_dir
+with_gxx_libcxx_include_dir
 with_cpp_install_dir
 enable_generated_files_in_srcdir
 with_gnu_ld
@@ -1801,6 +1804,8 @@  Optional Packages:
   --with-sysroot[=DIR]    search for usr/lib, usr/include, et al, within DIR
   --with-gxx-include-dir=DIR
                           specifies directory to put g++ header files
+  --with-gxx-libcxx-include-dir=DIR
+                          specifies directory to find libc++ header files
   --with-cpp-install-dir=DIR
                           install the user visible C preprocessor in DIR
                           (relative to PREFIX) as well as PREFIX/bin
@@ -3731,6 +3736,52 @@  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
+
+# Check whether --with-gxx-libcxx-include-dir was given.
+if test "${with_gxx_libcxx_include_dir+set}" = set; then :
+  withval=$with_gxx_libcxx_include_dir; case "${withval}" in
+yes)	as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;
+no)	;;
+*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
+esac
+fi
+
+
+# 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
+
+$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h
+
+else
+  $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h
+
+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
+
 
 # Check whether --with-cpp_install_dir was given.
 if test "${with_cpp_install_dir+set}" = set; then :
@@ -19186,7 +19237,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19189 "configure"
+#line 19240 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19292,7 +19343,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19295 "configure"
+#line 19346 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -31175,6 +31226,8 @@  fi
 
 
 
+
+
 
 
 
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 89b9981e872..6fcf154d987 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
@@ -7096,6 +7138,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 0f17148ccbd..a8254cd34c9 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -49,6 +49,34 @@  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
+
+/* The values used here must match those of the stdlib_kind enumeration
+   in c.opt.  */
+enum stdcxxlib_kind
+{
+  USE_LIBSTDCXX = 1,
+  USE_LIBCXX = 2
+};
+
 void
 lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 		      unsigned int *in_decoded_options_count,
@@ -59,13 +87,16 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
   /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
   int saw_profile_flag = 0;
 
-  /* What do with libstdc++:
-     -1 means we should not link in libstdc++
-     0  means we should link in libstdc++ if it is needed
-     1  means libstdc++ is needed and should be linked in.
-     2  means libstdc++ is needed and should be linked statically.  */
+  /* What action to take for the c++ runtime library:
+    -1  means we should not link it in.
+     0  means we should link it if it is needed.
+     1  means it is needed and should be linked in.
+     2  means it is needed but should be linked statically.  */
   int library = 0;
 
+  /* Which c++ runtime library to link.  */
+  stdcxxlib_kind which_library = USE_LIBSTDCXX;
+
   /* 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.  */
@@ -194,6 +225,10 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 	  args[i] |= SKIPOPT;
 	  break;
 
+	case OPT_stdlib_:
+	  which_library = (stdcxxlib_kind) decoded_options[i].value;
+	  break;
+
 	case OPT_SPECIAL_input_file:
 	  {
 	    int len;
@@ -250,6 +285,13 @@  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;
+  /* For libc++, on most platforms, the ABI library (usually called libc++abi)
+     is provided as a separate DSO, which we must also append.
+     However, a platform might have the ability to forward the ABI library
+     from libc++, or combine it in some other way; in that case, LIBCXXABI
+     should be set to NULL to signal that it need not be appended.  */
+  if (which_library == USE_LIBCXX && LIBCXXABI != NULL)
+    num_args += 4;
   new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
 
   i = 0;
@@ -323,9 +365,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 == USE_LIBCXX)
+	{
+	  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/cppdefault.h b/gcc/cppdefault.h
index a681264f75e..35cf24ec29e 100644
--- a/gcc/cppdefault.h
+++ b/gcc/cppdefault.h
@@ -36,7 +36,12 @@  struct default_include
   const char *const fname;	/* The name of the directory.  */
   const char *const component;	/* The component containing the directory
 				   (see update_path in prefix.c) */
-  const char cplusplus;		/* Only look here if we're compiling C++.  */
+  const char cplusplus;		/* When this is non-zero, we should only
+				   consider this if we're compiling C++.
+				   When the -stdlib option is configured, this
+				   may take values greater than 1 to indicate
+				   which C++ standard library should be
+				   used.  */
   const char cxx_aware;		/* Includes in this directory don't need to
 				   be wrapped in extern "C" when compiling
 				   C++.  */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d7d354fc4de..3b8b003c51d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -242,6 +242,7 @@  in the following sections.
 -fext-numeric-literals @gol
 -flang-info-include-translate@r{[}=@var{name}@r{]} @gol
 -flang-info-include-translate-not @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
@@ -3368,6 +3369,15 @@  is used when building the C++ library.)
 @opindex flang-info-include-translate-not
 Diagnose include translation events.
 
+@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;