diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index cc1538372d5f8d..04b46782467d6a 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -628,8 +628,9 @@ class Driver { /// treated before building actions or binding tools. /// /// \return Whether any compilation should be built for this - /// invocation. - bool HandleImmediateArgs(const Compilation &C); + /// invocation. The compilation can only be modified when + /// this function returns false. + bool HandleImmediateArgs(Compilation &C); /// ConstructAction - Construct the appropriate action to do for /// \p Phase on the \p Input, taking in to account arguments diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 28c3b52483e510..8e44d5afa40e05 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2128,7 +2128,7 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const { llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n'; } -bool Driver::HandleImmediateArgs(const Compilation &C) { +bool Driver::HandleImmediateArgs(Compilation &C) { // The order these options are handled in gcc is all over the place, but we // don't expect inconsistencies w.r.t. that to matter in practice. @@ -2271,6 +2271,14 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) { ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs()); const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs())); + // The 'Darwin' toolchain is initialized only when its arguments are + // computed. Get the default arguments for OFK_None to ensure that + // initialization is performed before trying to access properties of + // the toolchain in the functions below. + // FIXME: Remove when darwin's toolchain is initialized during construction. + // FIXME: For some more esoteric targets the default toolchain is not the + // correct one. + C.getArgsForToolChain(&TC, Triple.getArchName(), Action::OFK_None); RegisterEffectiveTriple TripleRAII(TC, Triple); switch (RLT) { case ToolChain::RLT_CompilerRT: diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index f354b0974d5f27..c6f9d7beffb1db 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1272,23 +1272,8 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const { void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, StringRef Component, RuntimeLinkOptions Opts, bool IsShared) const { - SmallString<64> DarwinLibName = StringRef("libclang_rt."); - // On Darwin the builtins component is not in the library name. - if (Component != "builtins") { - DarwinLibName += Component; - if (!(Opts & RLO_IsEmbedded)) - DarwinLibName += "_"; - } - - DarwinLibName += getOSLibraryNameSuffix(); - DarwinLibName += IsShared ? "_dynamic.dylib" : ".a"; - SmallString<128> Dir(getDriver().ResourceDir); - llvm::sys::path::append(Dir, "lib", "darwin"); - if (Opts & RLO_IsEmbedded) - llvm::sys::path::append(Dir, "macho_embedded"); - - SmallString<128> P(Dir); - llvm::sys::path::append(P, DarwinLibName); + std::string P = getCompilerRT( + Args, Component, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static); // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build (unless @@ -1303,18 +1288,56 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, // rpaths. This is currently true from this place, but we need to be // careful if this function is ever called before user's rpaths are emitted. if (Opts & RLO_AddRPath) { - assert(DarwinLibName.ends_with(".dylib") && "must be a dynamic library"); + assert(StringRef(P).ends_with(".dylib") && "must be a dynamic library"); // Add @executable_path to rpath to support having the dylib copied with // the executable. CmdArgs.push_back("-rpath"); CmdArgs.push_back("@executable_path"); - // Add the path to the resource dir to rpath to support using the dylib - // from the default location without copying. + // Add the compiler-rt library's directory to rpath to support using the + // dylib from the default location without copying. CmdArgs.push_back("-rpath"); - CmdArgs.push_back(Args.MakeArgString(Dir)); + CmdArgs.push_back(Args.MakeArgString(llvm::sys::path::parent_path(P))); + } +} + +std::string MachO::getCompilerRT(const ArgList &, StringRef Component, + FileType Type) const { + assert(Type != ToolChain::FT_Object && + "it doesn't make sense to ask for the compiler-rt library name as an " + "object file"); + SmallString<64> MachOLibName = StringRef("libclang_rt"); + // On MachO, the builtins component is not in the library name + if (Component != "builtins") { + MachOLibName += '.'; + MachOLibName += Component; + } + MachOLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a"; + + SmallString<128> FullPath(getDriver().ResourceDir); + llvm::sys::path::append(FullPath, "lib", "darwin", "macho_embedded", + MachOLibName); + return std::string(FullPath); +} + +std::string Darwin::getCompilerRT(const ArgList &, StringRef Component, + FileType Type) const { + assert(Type != ToolChain::FT_Object && + "it doesn't make sense to ask for the compiler-rt library name as an " + "object file"); + SmallString<64> DarwinLibName = StringRef("libclang_rt."); + // On Darwin, the builtins component is not in the library name + if (Component != "builtins") { + DarwinLibName += Component; + DarwinLibName += '_'; } + DarwinLibName += getOSLibraryNameSuffix(); + DarwinLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a"; + + SmallString<128> FullPath(getDriver().ResourceDir); + llvm::sys::path::append(FullPath, "lib", "darwin", DarwinLibName); + return std::string(FullPath); } StringRef Darwin::getPlatformFamily() const { diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index b45279ecedeb25..2e55b49682a7e9 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -223,6 +223,13 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain { // There aren't any profiling libs for embedded targets currently. } + // Return the full path of the compiler-rt library on a non-Darwin MachO + // system. Those are under + // /lib/darwin/macho_embedded/<...>(.dylib|.a). + std::string + getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, + FileType Type = ToolChain::FT_Static) const override; + /// } /// @name ToolChain Implementation /// { @@ -356,6 +363,12 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; + // Return the full path of the compiler-rt library on a Darwin MachO system. + // Those are under /lib/darwin/<...>(.dylib|.a). + std::string + getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, + FileType Type = ToolChain::FT_Static) const override; + protected: /// } /// @name Darwin specific Toolchain functions diff --git a/clang/test/Driver/darwin-print-libgcc-file-name.c b/clang/test/Driver/darwin-print-libgcc-file-name.c new file mode 100644 index 00000000000000..73e89b6718642c --- /dev/null +++ b/clang/test/Driver/darwin-print-libgcc-file-name.c @@ -0,0 +1,91 @@ +// Test the output of -print-libgcc-file-name on Darwin. + +// +// All platforms +// + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=x86_64-apple-macos \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-MACOS %s +// CHECK-CLANGRT-MACOS: libclang_rt.osx.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=arm64-apple-ios \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-IOS %s +// CHECK-CLANGRT-IOS: libclang_rt.ios.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=arm64-apple-watchos \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-WATCHOS %s +// CHECK-CLANGRT-WATCHOS: libclang_rt.watchos.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=arm64-apple-tvos \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-TVOS %s +// CHECK-CLANGRT-TVOS: libclang_rt.tvos.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=arm64-apple-driverkit \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-DRIVERKIT %s +// CHECK-CLANGRT-DRIVERKIT: libclang_rt.driverkit.a + +// +// Simulators +// + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=arm64-apple-ios-simulator \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-IOS-SIMULATOR %s +// CHECK-CLANGRT-IOS-SIMULATOR: libclang_rt.iossim.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=arm64-apple-watchos-simulator \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-WATCHOS-SIMULATOR %s +// CHECK-CLANGRT-WATCHOS-SIMULATOR: libclang_rt.watchossim.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: --target=arm64-apple-tvos-simulator \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-TVOS-SIMULATOR %s +// CHECK-CLANGRT-TVOS-SIMULATOR: libclang_rt.tvossim.a + +// Check the sanitizer and profile variants +// While the driver also links in sanitizer-specific dylibs, the result of +// -print-libgcc-file-name is the path of the basic compiler-rt library. + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: -fsanitize=address --target=x86_64-apple-macos \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-MACOS-SAN %s +// CHECK-CLANGRT-MACOS-SAN: libclang_rt.osx.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: -fsanitize=address --target=arm64-apple-ios \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-IOS-SAN %s +// CHECK-CLANGRT-IOS-SAN: libclang_rt.ios.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: -fsanitize=address --target=arm64-apple-watchos \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-WATCHOS-SAN %s +// CHECK-CLANGRT-WATCHOS-SAN: libclang_rt.watchos.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: -fsanitize=address --target=arm64-apple-tvos \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-TVOS-SAN %s +// CHECK-CLANGRT-TVOS-SAN: libclang_rt.tvos.a + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name \ +// RUN: -fsanitize=address --target=arm64-apple-driverkit \ +// RUN: -resource-dir=%S/Inputs/resource_dir 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-DRIVERKIT-SAN %s +// CHECK-CLANGRT-DRIVERKIT-SAN: libclang_rt.driverkit.a