[Driver][BareMetal] Support --emit-static-lib in BareMetal driver
authorPetr Hosek <phosek@google.com>
Fri, 21 Apr 2023 02:50:46 +0000 (02:50 +0000)
committerPetr Hosek <phosek@google.com>
Mon, 26 Jun 2023 23:19:02 +0000 (23:19 +0000)
This allows building static libraries with Clang driver.

Differential Revision: https://reviews.llvm.org/D148869

clang/lib/Driver/ToolChains/BareMetal.cpp
clang/lib/Driver/ToolChains/BareMetal.h
clang/test/Driver/baremetal.cpp

index 09cc72f..47a5335 100644 (file)
@@ -232,6 +232,10 @@ Tool *BareMetal::buildLinker() const {
   return new tools::baremetal::Linker(*this);
 }
 
+Tool *BareMetal::buildStaticLibTool() const {
+  return new tools::baremetal::StaticLibTool(*this);
+}
+
 std::string BareMetal::computeSysRoot() const {
   return computeBaseSysRoot(getDriver(), getTriple());
 }
@@ -368,6 +372,51 @@ void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
   llvm_unreachable("Unhandled RuntimeLibType.");
 }
 
+void baremetal::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 <options> <output_file> <input_files>".
+  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<Command>(JA, *this,
+                                         ResponseFileSupport::AtFileCurCP(),
+                                         Exec, CmdArgs, Inputs, Output));
+}
+
 void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
@@ -417,8 +466,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-o");
   CmdArgs.push_back(Output.getFilename());
 
-  C.addCommand(std::make_unique<Command>(JA, *this,
-                                         ResponseFileSupport::AtFileCurCP(),
-                                         Args.MakeArgString(TC.GetLinkerPath()),
-                                         CmdArgs, Inputs, Output));
+  C.addCommand(std::make_unique<Command>(
+      JA, *this, ResponseFileSupport::AtFileCurCP(),
+      Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output));
 }
index e594b12..fc39a2a 100644 (file)
@@ -32,6 +32,7 @@ public:
 
 protected:
   Tool *buildLinker() const override;
+  Tool *buildStaticLibTool() const override;
 
 public:
   bool useIntegratedAs() const override { return true; }
@@ -83,6 +84,20 @@ private:
 namespace tools {
 namespace baremetal {
 
+class LLVM_LIBRARY_VISIBILITY StaticLibTool : public Tool {
+public:
+  StaticLibTool(const ToolChain &TC)
+      : Tool("baremetal::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("baremetal::Linker", "ld.lld", TC) {}
index af511b9..41122f6 100644 (file)
@@ -1,5 +1,9 @@
 // UNSUPPORTED: system-windows
 
+// RUN: %clang -### %s --target=armv6-none-eabi --emit-static-lib 2>&1 \
+// RUN:   | FileCheck -check-prefixes=CHECK-STATIC-LIB %s
+// CHECK-STATIC-LIB: {{.*}}llvm-ar{{.*}}" "rcsD"
+
 // RUN: %clang %s -### --target=armv6m-none-eabi -o %t.out 2>&1 \
 // RUN:     -T semihosted.lds \
 // RUN:     -L some/directory/user/asked/for \