<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2013/9/11 Hans Wennborg <span dir="ltr"><<a href="mailto:hans@hanshq.net" target="_blank" class="cremed">hans@hanshq.net</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Author: hans<br>
Date: Tue Sep 10 15:18:04 2013<br>
New Revision: 190428<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=190428&view=rev" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project?rev=190428&view=rev</a><br>
Log:<br>
clang-cl: Support building DLLs (PR17083)<br>
<br>
This adds driver support for building DLLs (the /LD and /LDd flags).<br>
It basically does two things: runtime selection and passing -dll and<br>
-implib to the linker.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Driver/CLCompatOptions.td<br>
    cfe/trunk/lib/Driver/Driver.cpp<br>
    cfe/trunk/lib/Driver/Tools.cpp<br>
    cfe/trunk/test/Driver/cl-link.c<br>
    cfe/trunk/test/Driver/cl-outputs.c<br>
    cfe/trunk/test/Driver/cl-runtime-flags.c<br>
<br>
Modified: cfe/trunk/include/clang/Driver/CLCompatOptions.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CLCompatOptions.td?rev=190428&r1=190427&r2=190428&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CLCompatOptions.td?rev=190428&r1=190427&r2=190428&view=diff</a><br>


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


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


==============================================================================<br>
--- cfe/trunk/lib/Driver/Tools.cpp (original)<br>
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Sep 10 15:18:04 2013<br>
@@ -3714,6 +3714,11 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(co<br>
 void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {<br>
   unsigned RTOptionID = options::OPT__SLASH_MT;<br>
<br>
+  if (Args.hasArg(options::OPT__SLASH_LDd))<br>
+    // The /LDd option implies /MTd. The dependent lib part can be overridden,<br>
+    // but defining _DEBUG is sticky.<br>
+    RTOptionID = options::OPT__SLASH_MTd;<br>
+<br>
   if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD,<br>
                                options::OPT__SLASH_MDd,<br>
                                options::OPT__SLASH_MT,<br>
@@ -3723,6 +3728,8 @@ void Clang::AddClangCLArgs(const ArgList<br>
<br>
   switch(RTOptionID) {<br>
     case options::OPT__SLASH_MD:<br>
+      if (Args.hasArg(options::OPT__SLASH_LDd))<br>
+        CmdArgs.push_back("-D_DEBUG");<br>
       CmdArgs.push_back("-D_MT");<br>
       CmdArgs.push_back("-D_DLL");<br>
       CmdArgs.push_back("--dependent-lib=msvcrt");<br>
@@ -3734,6 +3741,8 @@ void Clang::AddClangCLArgs(const ArgList<br>
       CmdArgs.push_back("--dependent-lib=msvcrtd");<br>
       break;<br>
     case options::OPT__SLASH_MT:<br>
+      if (Args.hasArg(options::OPT__SLASH_LDd))<br>
+        CmdArgs.push_back("-D_DEBUG");<br>
       CmdArgs.push_back("-D_MT");<br>
       CmdArgs.push_back("--dependent-lib=libcmt");<br>
       break;<br>
@@ -6584,13 +6593,29 @@ void visualstudio::Link::ConstructJob(Co<br>
<br>
   CmdArgs.push_back("-nologo");<br>
<br>
+  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);<br>
+<br>
+  if (DLL) {<br>
+    CmdArgs.push_back(Args.MakeArgString("-dll"));<br>
+<br>
+    SmallString<128> ImplibName(Output.getFilename());<br>
+    llvm::sys::path::replace_extension(ImplibName, "lib");<br>
+    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +<br>
+                                         ImplibName.str()));<br>
+  }<br>
+<br>
   if (getToolChain().getDriver().getOrParseSanitizerArgs(Args).needsAsanRt()) {<br>
     CmdArgs.push_back(Args.MakeArgString("-debug"));<br>
     CmdArgs.push_back(Args.MakeArgString("-incremental:no"));<br>
     SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir);<br>
-    // FIXME: Handle 64-bit. Use asan_dll_thunk.dll when building a DLL.<br>
-    llvm::sys::path::append(<br>
-        LibSanitizer, "lib", "windows", "clang_rt.asan-i386.lib");<br>
+    llvm::sys::path::append(LibSanitizer, "lib", "windows");<br>
+    if (DLL) {<br>
+      // FIXME: Not sure what the final name of the thunk lib is.<br>
+      llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386-dll_thunk.lib");<br></blockquote><div><br></div><div>FYI</div><div>I've fixed that in r190516.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


+    } else {<br>
+      llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");<br>
+    }<br>
+    // FIXME: Handle 64-bit.<br>
     CmdArgs.push_back(Args.MakeArgString(LibSanitizer));<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/test/Driver/cl-link.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-link.c?rev=190428&r1=190427&r2=190428&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-link.c?rev=190428&r1=190427&r2=190428&view=diff</a><br>


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


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


==============================================================================<br>
--- cfe/trunk/test/Driver/cl-runtime-flags.c (original)<br>
+++ cfe/trunk/test/Driver/cl-runtime-flags.c Tue Sep 10 15:18:04 2013<br>
@@ -20,6 +20,7 @@<br>
 // CHECK-MT: "--dependent-lib=oldnames"<br>
<br>
 // RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s<br>
+// RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s<br>
 // CHECK-MTd: "-D_DEBUG"<br>
 // CHECK-MTd: "-D_MT"<br>
 // CHECK-MTd-NOT: "-D_DLL"<br>
@@ -39,3 +40,47 @@<br>
 // CHECK-MDd: "-D_DLL"<br>
 // CHECK-MDd: "--dependent-lib=msvcrtd"<br>
 // CHECK-MDd: "--dependent-lib=oldnames"<br>
+<br>
+// RUN: %clang_cl -### /LD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LD %s<br>
+// RUN: %clang_cl -### /LD /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-LD %s<br>
+// CHECK-LD-NOT: "-D_DEBUG"<br>
+// CHECK-LD: "-D_MT"<br>
+// CHECK-LD-NOT: "-D_DLL"<br>
+// CHECK-LD: "--dependent-lib=libcmt"<br>
+<br>
+// RUN: %clang_cl -### /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDd %s<br>
+// RUN: %clang_cl -### /LDd /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDd %s<br>
+// CHECK-LDd: "-D_DEBUG"<br>
+// CHECK-LDd: "-D_MT"<br>
+// CHECK-LDd-NOT: "-D_DLL"<br>
+// CHECK-LDd: "--dependent-lib=libcmtd"<br>
+<br>
+// RUN: %clang_cl -### /LDd /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMT %s<br>
+// RUN: %clang_cl -### /MT /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMT %s<br>
+// CHECK-LDdMT: "-D_DEBUG"<br>
+// CHECK-LDdMT: "-D_MT"<br>
+// CHECK-LDdMT-NOT: "-D_DLL"<br>
+// CHECK-LDdMT: "--dependent-lib=libcmt"<br>
+<br>
+// RUN: %clang_cl -### /LD /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMD %s<br>
+// RUN: %clang_cl -### /MD /LD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMD %s<br>
+// CHECK-LDMD-NOT: "-D_DEBUG"<br>
+// CHECK-LDMD: "-D_MT"<br>
+// CHECK-LDMD: "-D_DLL"<br>
+// CHECK-LDMD: "--dependent-lib=msvcrt"<br>
+<br>
+// RUN: %clang_cl -### /LDd /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMD %s<br>
+// RUN: %clang_cl -### /MD /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDdMD %s<br>
+// CHECK-LDdMD: "-D_DEBUG"<br>
+// CHECK-LDdMD: "-D_MT"<br>
+// CHECK-LDdMD: "-D_DLL"<br>
+// CHECK-LDdMD: "--dependent-lib=msvcrt"<br>
+<br>
+// RUN: %clang_cl -### /LD /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s<br>
+// RUN: %clang_cl -### /MDd /LD -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s<br>
+// RUN: %clang_cl -### /LDd /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s<br>
+// RUN: %clang_cl -### /MDd /LDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-LDMDd %s<br>
+// CHECK-LDMDd: "-D_DEBUG"<br>
+// CHECK-LDMDd: "-D_MT"<br>
+// CHECK-LDMDd: "-D_DLL"<br>
+// CHECK-LDMDd: "--dependent-lib=msvcrtd"<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" class="cremed">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank" class="cremed">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>