diff --git a/clang/lib/Driver/ToolChains/Fuchsia.h b/clang/lib/Driver/ToolChains/Fuchsia.h --- a/clang/lib/Driver/ToolChains/Fuchsia.h +++ b/clang/lib/Driver/ToolChains/Fuchsia.h @@ -18,6 +18,20 @@ namespace driver { namespace tools { namespace fuchsia { +class LLVM_LIBRARY_VISIBILITY StaticLibTool : public Tool { +public: + StaticLibTool(const ToolChain &TC) + : Tool("fuchsia::StaticLibTool", "llvm-ar", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + class LLVM_LIBRARY_VISIBILITY Linker : public Tool { public: Linker(const ToolChain &TC) : Tool("fuchsia::Linker", "ld.lld", TC) {} @@ -100,6 +114,7 @@ protected: Tool *buildLinker() const override; + Tool *buildStaticLibTool() const override; }; } // end namespace toolchains diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -190,6 +190,51 @@ Exec, CmdArgs, Inputs, Output)); } +void fuchsia::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const Driver &D = getToolChain().getDriver(); + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + // Silence warnings when linking C code with a C++ '-stdlib' argument. + Args.ClaimAllArgs(options::OPT_stdlib_EQ); + + // ar tool command "llvm-ar ". + ArgStringList CmdArgs; + // Create and insert file members with a deterministic index. + CmdArgs.push_back("rcsD"); + CmdArgs.push_back(Output.getFilename()); + + for (const auto &II : Inputs) { + if (II.isFilename()) { + CmdArgs.push_back(II.getFilename()); + } + } + + // Delete old output archive file if it already exists before generating a new + // archive file. + const char *OutputFileName = Output.getFilename(); + if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) { + if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) { + D.Diag(diag::err_drv_unable_to_remove_file) << EC.message(); + return; + } + } + + const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath()); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); +} + /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly. Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, @@ -307,6 +352,10 @@ return new tools::fuchsia::Linker(*this); } +Tool *Fuchsia::buildStaticLibTool() const { + return new tools::fuchsia::StaticLibTool(*this); +} + ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType( const ArgList &Args) const { if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) { diff --git a/clang/test/Driver/fuchsia.c b/clang/test/Driver/fuchsia.c --- a/clang/test/Driver/fuchsia.c +++ b/clang/test/Driver/fuchsia.c @@ -54,6 +54,10 @@ // CHECK-NOT: crtend.o // CHECK-NOT: crtn.o +// RUN: %clang -### %s --target=x86_64-unknown-fuchsia \ +// RUN: --emit-static-lib 2>&1 | FileCheck -check-prefixes=CHECK-STATIC-LIB %s +// CHECK-STATIC-LIB: {{.*}}llvm-ar{{.*}}" "rcsD" + // RUN: %clang -### %s --target=x86_64-unknown-fuchsia 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-FP-ALL // RUN: %clang -### %s --target=aarch64-unknown-fuchsia 2>&1 \