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