Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ clang/lib/Driver/ToolChains/CommonArgs.h @@ -85,6 +85,11 @@ void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); + +void addCXXStdlibLinkDeps(const ToolChain &ToolChain, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs); + /// Returns true, if an OpenMP runtime has been added. bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, const llvm::opt::ArgList &Args, Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1226,6 +1226,48 @@ } } +void tools::addCXXStdlibLinkDeps(const ToolChain &ToolChain, + const ArgList &Args, + ArgStringList &CmdArgs) { + const llvm::Triple &Triple = ToolChain.getTriple(); + + bool StaticLibstdcxx = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + + // TODO: should this be only included when -static-libstdc++ is used? + if ((Triple.getOS() == llvm::Triple::FreeBSD || + Triple.getOS() == llvm::Triple::OpenBSD || + Triple.isPS4CPU()) && Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lm_p"); + else + CmdArgs.push_back("-lm"); + + if (StaticLibstdcxx) { + if (!Triple.isAndroid()) + CmdArgs.push_back("-lpthread"); + + switch (ToolChain.GetCXXStdlibType(Args)) { + case ToolChain::CST_Libcxx: + if (Triple.getOS() != llvm::Triple::FreeBSD && + Triple.getOS() != llvm::Triple::NetBSD && + Triple.getOS() != llvm::Triple::OpenBSD) + CmdArgs.push_back("-ldl"); + break; + + case ToolChain::CST_Libstdcxx: + switch (ToolChain.GetRuntimeLibType(Args)) { + case ToolChain::RLT_CompilerRT: + AddLibgcc(Triple, ToolChain.getDriver(), CmdArgs, Args); + break; + case ToolChain::RLT_Libgcc: + // libgcc will be added by AddLibgcc. + break; + } + break; + } + } +} + /// Add OpenMP linker script arguments at the end of the argument list so that /// the fat binary is built by embedding each of the device images into the /// host. The linker script also defines a few symbols required by the code Index: clang/lib/Driver/ToolChains/DragonFly.cpp =================================================================== --- clang/lib/Driver/ToolChains/DragonFly.cpp +++ clang/lib/Driver/ToolChains/DragonFly.cpp @@ -129,7 +129,7 @@ if (D.CCCIsCXX()) { if (getToolChain().ShouldLinkCXXStdlib(Args)) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); - CmdArgs.push_back("-lm"); + addCXXStdlibLinkDeps(getToolChain(), Args, CmdArgs); } if (Args.hasArg(options::OPT_pthread)) Index: clang/lib/Driver/ToolChains/FreeBSD.cpp =================================================================== --- clang/lib/Driver/ToolChains/FreeBSD.cpp +++ clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -267,10 +267,7 @@ if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); - if (Args.hasArg(options::OPT_pg)) - CmdArgs.push_back("-lm_p"); - else - CmdArgs.push_back("-lm"); + addCXXStdlibLinkDeps(ToolChain, Args, CmdArgs); } if (NeedsSanitizerDeps) linkSanitizerRuntimeDeps(ToolChain, CmdArgs); Index: clang/lib/Driver/ToolChains/Fuchsia.cpp =================================================================== --- clang/lib/Driver/ToolChains/Fuchsia.cpp +++ clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -129,7 +129,7 @@ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bdynamic"); - CmdArgs.push_back("-lm"); + addCXXStdlibLinkDeps(ToolChain, Args, CmdArgs); CmdArgs.push_back("--pop-state"); } } Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -482,6 +482,7 @@ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bdynamic"); + addCXXStdlibLinkDeps(ToolChain, Args, CmdArgs); } CmdArgs.push_back("-lm"); } Index: clang/lib/Driver/ToolChains/Hexagon.cpp =================================================================== --- clang/lib/Driver/ToolChains/Hexagon.cpp +++ clang/lib/Driver/ToolChains/Hexagon.cpp @@ -332,7 +332,7 @@ if (D.CCCIsCXX()) { if (HTC.ShouldLinkCXXStdlib(Args)) HTC.AddCXXStdlibLibArgs(Args, CmdArgs); - CmdArgs.push_back("-lm"); + addCXXStdlibLinkDeps(HTC, Args, CmdArgs); } CmdArgs.push_back("--start-group"); Index: clang/lib/Driver/ToolChains/OpenBSD.cpp =================================================================== --- clang/lib/Driver/ToolChains/OpenBSD.cpp +++ clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -183,10 +183,7 @@ if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); - if (Args.hasArg(options::OPT_pg)) - CmdArgs.push_back("-lm_p"); - else - CmdArgs.push_back("-lm"); + addCXXStdlibLinkDeps(ToolChain, Args, CmdArgs); } if (NeedsSanitizerDeps) { CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins", false)); Index: clang/lib/Driver/ToolChains/PS4CPU.cpp =================================================================== --- clang/lib/Driver/ToolChains/PS4CPU.cpp +++ clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -21,6 +21,7 @@ #include // ::getenv using namespace clang::driver; +using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; @@ -238,10 +239,7 @@ if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); - if (Args.hasArg(options::OPT_pg)) - CmdArgs.push_back("-lm_p"); - else - CmdArgs.push_back("-lm"); + addCXXStdlibLinkDeps(ToolChain, Args, CmdArgs); } // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding // the default system libraries. Just mimic this for now. Index: clang/test/Driver/fuchsia.cpp =================================================================== --- clang/test/Driver/fuchsia.cpp +++ clang/test/Driver/fuchsia.cpp @@ -41,5 +41,7 @@ // CHECK-STATIC: "-lc++" // CHECK-STATIC: "-Bdynamic" // CHECK-STATIC: "-lm" +// CHECK-STATIC: "-lpthread" +// CHECK-STATIC: "-ldl" // CHECK-STATIC: "--pop-state" // CHECK-STATIC: "-lc" Index: clang/test/Driver/linux-ld.c =================================================================== --- clang/test/Driver/linux-ld.c +++ clang/test/Driver/linux-ld.c @@ -572,6 +572,22 @@ // CHECK-BASIC-LIBCXX-C-LINK: "--sysroot=[[SYSROOT]]" // CHECK-BASIC-LIBCXX-C-LINK: "-L[[SYSROOT]]/usr/bin/../lib" // +// Test that we include necessary dependencies when statically linking libc++. +// RUN: %clangxx -no-canonical-prefixes -x c++ %s -### -o %t.o 2>&1 \ +// RUN: -target x86_64-unknown-linux-gnu \ +// RUN: -stdlib=libc++ \ +// RUN: -static-libstdc++ \ +// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ +// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-STATIC %s +// CHECK-BASIC-LIBCXX-STATIC: "-Bstatic" +// CHECK-BASIC-LIBCXX-STATIC: "-lc++" +// CHECK-BASIC-LIBCXX-STATIC: "-Bdynamic" +// CHECK-BASIC-LIBCXX-STATIC: "-lpthread" +// CHECK-BASIC-LIBCXX-STATIC: "-ldl" +// CHECK-BASIC-LIBCXX-STATIC: "-lm" +// // Test a very broken version of multiarch that shipped in Ubuntu 11.04. // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: --target=i386-unknown-linux \