diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -149,6 +149,9 @@ typedef SmallVector prefix_list; prefix_list PrefixDirs; + /// Alternative toolchain path in prior to sysroot. + std::string OverlayToolChainPath; + /// sysroot, if present std::string SysRoot; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4178,6 +4178,8 @@ def _output_class_directory : Separate<["--"], "output-class-directory">, Alias; def _output_EQ : Joined<["--"], "output=">, Alias; def _output : Separate<["--"], "output">, Alias; +def _overlay_platform_toolchain_EQ : Joined<["--"], "overlay-platform-toolchain=">; +def _overlay_platform_toolchain : Separate<["--"], "overlay-platform-toolchain">, Alias<_overlay_platform_toolchain_EQ>; def _param : Separate<["--"], "param">, Group; def _param_EQ : Joined<["--"], "param=">, Alias<_param>; def _precompile : Flag<["--"], "precompile">, Flags<[NoXarchOption]>, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1208,6 +1208,11 @@ CompilerPath = Split.second; } } + if (const Arg *A = + Args.getLastArg(options::OPT__overlay_platform_toolchain_EQ)) { + OverlayToolChainPath = A->getValue(); + DyldPrefix = A->getValue(); + } if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) SysRoot = A->getValue(); if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ)) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -1867,6 +1867,10 @@ if (A) return A->getValue(); + if (const Arg *X = Args.getLastArg( + clang::driver::options::OPT__overlay_platform_toolchain_EQ)) + return X->getValue(); + // If we have a SysRoot, ignore GCC_INSTALL_PREFIX. // GCC_INSTALL_PREFIX specifies the gcc installation for the default // sysroot and is likely not valid with a different sysroot. diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -261,6 +261,16 @@ const std::string OSLibDir = std::string(getOSLibDir(Triple, Args)); const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot); + if (!D.OverlayToolChainPath.empty()) { + const std::string &ExtraPath = D.OverlayToolChainPath; + addPathIfExists(D, ExtraPath + "/lib/" + MultiarchTriple, Paths); + addPathIfExists(D, ExtraPath + "/lib/../" + OSLibDir, Paths); + addPathIfExists(D, ExtraPath + "/usr/lib/" + MultiarchTriple, Paths); + addPathIfExists(D, ExtraPath + "/usr/lib/../" + OSLibDir, Paths); + addPathIfExists(D, ExtraPath + "/lib", Paths); + addPathIfExists(D, ExtraPath + "/usr/lib", Paths); + } + // mips32: Debian multilib, we use /libo32, while in other case, /lib is // used. We need add both libo32 and /lib. if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) { @@ -567,6 +577,10 @@ if (DriverArgs.hasArg(options::OPT_nostdlibinc)) return; + if (!D.OverlayToolChainPath.empty()) + addExternCSystemInclude(DriverArgs, CC1Args, + D.OverlayToolChainPath + "/include"); + // LOCAL_INCLUDE_DIR addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include"); // TOOL_INCLUDE_DIR diff --git a/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/include/.keep b/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/include/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/lib64/.keep b/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/lib64/.keep new file mode 100644 diff --git a/clang/test/Driver/gcc-toolchain.cpp b/clang/test/Driver/gcc-toolchain.cpp --- a/clang/test/Driver/gcc-toolchain.cpp +++ b/clang/test/Driver/gcc-toolchain.cpp @@ -37,3 +37,15 @@ // AARCH64: Inputs{{[^"]+}}aarch64-suse-linux/{{[^"]+}}crt1.o" // NO_AARCH64-NOT: Inputs{{[^"]+}}aarch64-suse-linux/{{[^"]+}}crt1.o" + +/// Test option to add 'overlay platform toolchain' +// RUN: %clangxx %s -### --target=powerpc64le-linux-gnu \ +// RUN: --overlay-platform-toolchain=%S/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0 \ +// RUN: 2>&1 | FileCheck %s --check-prefix=OVERLAY + +// OVERLAY: "-internal-externc-isystem" +// OVERLAY: "[[TOOLCHAIN:[^"]+]]/powerpc64le-linux-gnu-tree/gcc-11.2.0/include" +// OVERLAY: "-dynamic-linker" +// OVERLAY: "[[TOOLCHAIN]]/powerpc64le-linux-gnu-tree/gcc-11.2.0/lib64/ld64.so.2" +// OVERLAY: "-L[[TOOLCHAIN]]/powerpc64le-linux-gnu-tree/gcc-11.2.0/lib/../lib64" +// OVERLAY: "-L[[TOOLCHAIN]]/powerpc64le-linux-gnu-tree/gcc-11.2.0/lib"