r190428 - clang-cl: Support building DLLs (PR17083)

Hans Wennborg hans at hanshq.net
Tue Sep 10 13:18:04 PDT 2013


Author: hans
Date: Tue Sep 10 15:18:04 2013
New Revision: 190428

URL: http://llvm.org/viewvc/llvm-project?rev=190428&view=rev
Log:
clang-cl: Support building DLLs (PR17083)

This adds driver support for building DLLs (the /LD and /LDd flags).
It basically does two things: runtime selection and passing -dll and
-implib to the linker.

Modified:
    cfe/trunk/include/clang/Driver/CLCompatOptions.td
    cfe/trunk/lib/Driver/Driver.cpp
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/Driver/cl-link.c
    cfe/trunk/test/Driver/cl-outputs.c
    cfe/trunk/test/Driver/cl-runtime-flags.c

Modified: cfe/trunk/include/clang/Driver/CLCompatOptions.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CLCompatOptions.td?rev=190428&r1=190427&r2=190428&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CLCompatOptions.td (original)
+++ cfe/trunk/include/clang/Driver/CLCompatOptions.td Tue Sep 10 15:18:04 2013
@@ -99,6 +99,8 @@ def _SLASH_Fe : CLJoined<"Fe">,
 def _SLASH_Fo : CLJoined<"Fo">,
   HelpText<"Set output object file, or directory (ends in / or \\)">,
   MetaVarName<"<file or directory>">;
+def _SLASH_LD : CLFlag<"LD">, HelpText<"Create DLL">;
+def _SLASH_LDd : CLFlag<"LDd">, HelpText<"Create debug DLL">;
 def _SLASH_link : CLRemainingArgs<"link">,
   HelpText<"Forward options to the linker">, MetaVarName<"<options>">;
 def _SLASH_MD : CLFlag<"MD">,

Modified: cfe/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=190428&r1=190427&r2=190428&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Driver.cpp (original)
+++ cfe/trunk/lib/Driver/Driver.cpp Tue Sep 10 15:18:04 2013
@@ -1585,9 +1585,11 @@ void Driver::BuildJobsForAction(Compilat
 static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
                                         StringRef BaseName, types::ID FileType) {
   SmallString<128> Filename = ArgValue;
-  assert(!ArgValue.empty() && "Output filename argument must not be empty.");
   
-  if (llvm::sys::path::is_separator(Filename.back())) {
+  if (ArgValue.empty()) {
+    // If the argument is empty, output to BaseName in the current dir.
+    Filename = BaseName;
+  } else if (llvm::sys::path::is_separator(Filename.back())) {
     // If the argument is a directory, output to BaseName in that dir.
     llvm::sys::path::append(Filename, BaseName);
   }
@@ -1595,6 +1597,13 @@ static const char *MakeCLOutputFilename(
   if (!llvm::sys::path::has_extension(ArgValue)) {
     // If the argument didn't provide an extension, then set it.
     const char *Extension = types::getTypeTempSuffix(FileType, true);
+
+    if (FileType == types::TY_Image &&
+        Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd)) {
+      // The output file is a dll.
+      Extension = "dll";
+    }
+
     llvm::sys::path::replace_extension(Filename, Extension);
   }
 
@@ -1656,12 +1665,11 @@ const char *Driver::GetNamedOutputPath(C
     StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe)->getValue();
     NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
                                        types::TY_Image);
-  } else if (JA.getType() == types::TY_Image) {    
+  } else if (JA.getType() == types::TY_Image) {
     if (IsCLMode()) {
       // clang-cl uses BaseName for the executable name.
-      SmallString<128> Filename = BaseName;
-      llvm::sys::path::replace_extension(Filename, "exe");
-      NamedOutput = C.getArgs().MakeArgString(Filename.c_str());
+      NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName,
+                                         types::TY_Image);
     } else if (MultipleArchs && BoundArch) {
       SmallString<128> Output(DefaultImageName.c_str());
       Output += "-";

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=190428&r1=190427&r2=190428&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Sep 10 15:18:04 2013
@@ -3714,6 +3714,11 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(co
 void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
   unsigned RTOptionID = options::OPT__SLASH_MT;
 
+  if (Args.hasArg(options::OPT__SLASH_LDd))
+    // The /LDd option implies /MTd. The dependent lib part can be overridden,
+    // but defining _DEBUG is sticky.
+    RTOptionID = options::OPT__SLASH_MTd;
+
   if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD,
                                options::OPT__SLASH_MDd,
                                options::OPT__SLASH_MT,
@@ -3723,6 +3728,8 @@ void Clang::AddClangCLArgs(const ArgList
 
   switch(RTOptionID) {
     case options::OPT__SLASH_MD:
+      if (Args.hasArg(options::OPT__SLASH_LDd))
+        CmdArgs.push_back("-D_DEBUG");
       CmdArgs.push_back("-D_MT");
       CmdArgs.push_back("-D_DLL");
       CmdArgs.push_back("--dependent-lib=msvcrt");
@@ -3734,6 +3741,8 @@ void Clang::AddClangCLArgs(const ArgList
       CmdArgs.push_back("--dependent-lib=msvcrtd");
       break;
     case options::OPT__SLASH_MT:
+      if (Args.hasArg(options::OPT__SLASH_LDd))
+        CmdArgs.push_back("-D_DEBUG");
       CmdArgs.push_back("-D_MT");
       CmdArgs.push_back("--dependent-lib=libcmt");
       break;
@@ -6584,13 +6593,29 @@ void visualstudio::Link::ConstructJob(Co
 
   CmdArgs.push_back("-nologo");
 
+  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
+
+  if (DLL) {
+    CmdArgs.push_back(Args.MakeArgString("-dll"));
+
+    SmallString<128> ImplibName(Output.getFilename());
+    llvm::sys::path::replace_extension(ImplibName, "lib");
+    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
+                                         ImplibName.str()));
+  }
+
   if (getToolChain().getDriver().getOrParseSanitizerArgs(Args).needsAsanRt()) {
     CmdArgs.push_back(Args.MakeArgString("-debug"));
     CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
     SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir);
-    // FIXME: Handle 64-bit. Use asan_dll_thunk.dll when building a DLL.
-    llvm::sys::path::append(
-        LibSanitizer, "lib", "windows", "clang_rt.asan-i386.lib");
+    llvm::sys::path::append(LibSanitizer, "lib", "windows");
+    if (DLL) {
+      // FIXME: Not sure what the final name of the thunk lib is.
+      llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386-dll_thunk.lib");
+    } else {
+      llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");
+    }
+    // FIXME: Handle 64-bit.
     CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
   }
 

Modified: cfe/trunk/test/Driver/cl-link.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-link.c?rev=190428&r1=190427&r2=190428&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-link.c (original)
+++ cfe/trunk/test/Driver/cl-link.c Tue Sep 10 15:18:04 2013
@@ -17,3 +17,17 @@
 // ASAN: "-incremental:no"
 // ASAN: "{{.*}}clang_rt.asan-i386.lib"
 // ASAN: "{{.*}}cl-link{{.*}}.obj"
+
+// RUN: %clang_cl /LD -### %s 2>&1 | FileCheck --check-prefix=DLL %s
+// RUN: %clang_cl /LDd -### %s 2>&1 | FileCheck --check-prefix=DLL %s
+// DLL: link.exe
+// "-dll"
+
+// RUN: %clang_cl /LD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s
+// RUN: %clang_cl /LDd /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s
+// ASAN-DLL: link.exe
+// ASAN-DLL: "-dll"
+// ASAN-DLL: "-debug"
+// ASAN-DLL: "-incremental:no"
+// ASAN-DLL: "{{.*}}clang_rt.asan-i386-dll_thunk.lib"
+// ASAN-DLL: "{{.*}}cl-link{{.*}}.obj"

Modified: cfe/trunk/test/Driver/cl-outputs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-outputs.c?rev=190428&r1=190427&r2=190428&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-outputs.c (original)
+++ cfe/trunk/test/Driver/cl-outputs.c Tue Sep 10 15:18:04 2013
@@ -39,24 +39,54 @@
 // RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULTEXE %s
 // DEFAULTEXE: cl-outputs.exe
 
+// RUN: %clang_cl /LD -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULTDLL %s
+// RUN: %clang_cl /LDd -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULTDLL %s
+// DEFAULTDLL: "-out:cl-outputs.dll"
+// DEFAULTDLL: "-implib:cl-outputs.lib"
+
 // RUN: %clang_cl /Fefoo -### -- %s 2>&1 | FileCheck -check-prefix=FeNOEXT %s
-// FeNOEXT: foo.exe
+// FeNOEXT: "-out:foo.exe"
+
+// RUN: %clang_cl /Fefoo /LD -### -- %s 2>&1 | FileCheck -check-prefix=FeNOEXTDLL %s
+// RUN: %clang_cl /Fefoo /LDd -### -- %s 2>&1 | FileCheck -check-prefix=FeNOEXTDLL %s
+// FeNOEXTDLL: "-out:foo.dll"
+// FeNOEXTDLL: "-implib:foo.lib"
 
 // RUN: %clang_cl /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s
-// FeEXT: foo.ext
+// FeEXT: "-out:foo.ext"
+
+// RUN: %clang_cl /LD /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXTDLL %s
+// RUN: %clang_cl /LDd /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXTDLL %s
+// FeEXTDLL: "-out:foo.ext"
+// FeEXTDLL: "-implib:foo.lib"
 
 // RUN: %clang_cl /Fefoo.dir/ -### -- %s 2>&1 | FileCheck -check-prefix=FeDIR %s
-// FeDIR: foo.dir{{[/\\]+}}cl-outputs.exe
+// FeDIR: "-out:foo.dir{{[/\\]+}}cl-outputs.exe"
+
+// RUN: %clang_cl /LD /Fefoo.dir/ -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRDLL %s
+// RUN: %clang_cl /LDd /Fefoo.dir/ -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRDLL %s
+// FeDIRDLL: "-out:foo.dir{{[/\\]+}}cl-outputs.dll"
+// FeDIRDLL: "-implib:foo.dir{{[/\\]+}}cl-outputs.lib"
 
 // RUN: %clang_cl /Fefoo.dir/a -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAME %s
-// FeDIRNAME: foo.dir{{[/\\]+}}a.exe
+// FeDIRNAME: "-out:foo.dir{{[/\\]+}}a.exe"
+
+// RUN: %clang_cl /LD /Fefoo.dir/a -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAMEDLL %s
+// RUN: %clang_cl /LDd /Fefoo.dir/a -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAMEDLL %s
+// FeDIRNAMEDLL: "-out:foo.dir{{[/\\]+}}a.dll"
+// FeDIRNAMEDLL: "-implib:foo.dir{{[/\\]+}}a.lib"
 
 // RUN: %clang_cl /Fefoo.dir/a.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAMEEXT %s
-// FeDIRNAMEEXT: foo.dir{{[/\\]+}}a.ext
+// FeDIRNAMEEXT: "-out:foo.dir{{[/\\]+}}a.ext"
+
+// RUN: %clang_cl /LD /Fefoo.dir/a.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAMEEXTDLL %s
+// RUN: %clang_cl /LDd /Fefoo.dir/a.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAMEEXTDLL %s
+// FeDIRNAMEEXTDLL: "-out:foo.dir{{[/\\]+}}a.ext"
+// FeDIRNAMEEXTDLL: "-implib:foo.dir{{[/\\]+}}a.lib"
 
 // RUN: %clang_cl /Fe -### 2>&1 | FileCheck -check-prefix=FeMISSINGARG %s
 // FeMISSINGARG: error: argument to '/Fe' is missing (expected 1 value)
 
 // RUN: %clang_cl /Fefoo /Febar -### -- %s 2>&1 | FileCheck -check-prefix=FeOVERRIDE %s
 // FeOVERRIDE: warning: overriding '/Fefoo' option with '/Febar'
-// FeOVERRIDE: bar.exe
+// FeOVERRIDE: "-out:bar.exe"

Modified: cfe/trunk/test/Driver/cl-runtime-flags.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-runtime-flags.c?rev=190428&r1=190427&r2=190428&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-runtime-flags.c (original)
+++ cfe/trunk/test/Driver/cl-runtime-flags.c Tue Sep 10 15:18:04 2013
@@ -20,6 +20,7 @@
 // CHECK-MT: "--dependent-lib=oldnames"
 
 // RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
+// RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
 // CHECK-MTd: "-D_DEBUG"
 // CHECK-MTd: "-D_MT"
 // CHECK-MTd-NOT: "-D_DLL"
@@ -39,3 +40,47 @@
 // CHECK-MDd: "-D_DLL"
 // CHECK-MDd: "--dependent-lib=msvcrtd"
 // CHECK-MDd: "--dependent-lib=oldnames"
+
+// RUN: %clang_cl -### /LD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LD %s
+// RUN: %clang_cl -### /LD /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-LD %s
+// CHECK-LD-NOT: "-D_DEBUG"
+// CHECK-LD: "-D_MT"
+// CHECK-LD-NOT: "-D_DLL"
+// CHECK-LD: "--dependent-lib=libcmt"
+
+// RUN: %clang_cl -### /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDd %s
+// RUN: %clang_cl -### /LDd /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDd %s
+// CHECK-LDd: "-D_DEBUG"
+// CHECK-LDd: "-D_MT"
+// CHECK-LDd-NOT: "-D_DLL"
+// CHECK-LDd: "--dependent-lib=libcmtd"
+
+// RUN: %clang_cl -### /LDd /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMT %s
+// RUN: %clang_cl -### /MT /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMT %s
+// CHECK-LDdMT: "-D_DEBUG"
+// CHECK-LDdMT: "-D_MT"
+// CHECK-LDdMT-NOT: "-D_DLL"
+// CHECK-LDdMT: "--dependent-lib=libcmt"
+
+// RUN: %clang_cl -### /LD /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMD %s
+// RUN: %clang_cl -### /MD /LD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMD %s
+// CHECK-LDMD-NOT: "-D_DEBUG"
+// CHECK-LDMD: "-D_MT"
+// CHECK-LDMD: "-D_DLL"
+// CHECK-LDMD: "--dependent-lib=msvcrt"
+
+// RUN: %clang_cl -### /LDd /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMD %s
+// RUN: %clang_cl -### /MD /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMD %s
+// CHECK-LDdMD: "-D_DEBUG"
+// CHECK-LDdMD: "-D_MT"
+// CHECK-LDdMD: "-D_DLL"
+// CHECK-LDdMD: "--dependent-lib=msvcrt"
+
+// RUN: %clang_cl -### /LD /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s
+// RUN: %clang_cl -### /MDd /LD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s
+// RUN: %clang_cl -### /LDd /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s
+// RUN: %clang_cl -### /MDd /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s
+// CHECK-LDMDd: "-D_DEBUG"
+// CHECK-LDMDd: "-D_MT"
+// CHECK-LDMDd: "-D_DLL"
+// CHECK-LDMDd: "--dependent-lib=msvcrtd"





More information about the cfe-commits mailing list