diff --git a/dmd/mars.h b/dmd/mars.h index d8647322..ac6a72ea 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -271,6 +271,7 @@ struct Global char *bc_ext; char *s_ext; const char *lib_ext; + const char *dll_ext; const char *doc_ext; // for Ddoc generated files const char *ddoc_ext; // for Ddoc macro include files const char *hdr_ext; // for D 'header' import files diff --git a/dmd2/mars.c b/dmd2/mars.c index 82123751..f05ea012 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -72,10 +72,7 @@ Global::Global() s_ext = "s"; obj_ext = "o"; #if _WIN32 - lib_ext = "lib"; obj_ext_alt = "obj"; -#else - lib_ext = "a"; #endif #else #if TARGET_WINDOS diff --git a/gen/cl_options.cpp b/gen/cl_options.cpp index 0be4aa97..eef2d9a9 100644 --- a/gen/cl_options.cpp +++ b/gen/cl_options.cpp @@ -43,6 +43,10 @@ cl::opt createStaticLib("lib", cl::desc("Create static library"), cl::ZeroOrMore); +cl::opt createSharedLib("shared", + cl::desc("Create sharedlibrary"), + cl::ZeroOrMore); + static cl::opt verbose("v", cl::desc("Verbose"), cl::ZeroOrMore, diff --git a/gen/cl_options.h b/gen/cl_options.h index 6c44b3a2..cdfe1343 100644 --- a/gen/cl_options.h +++ b/gen/cl_options.h @@ -20,6 +20,7 @@ namespace opts { extern cl::list runargs; extern cl::opt compileOnly; extern cl::opt createStaticLib; + extern cl::opt createSharedLib; extern cl::opt noAsm; extern cl::opt dontWriteObj; extern cl::opt objectFile; diff --git a/gen/linker.cpp b/gen/linker.cpp index 4996a2f2..72584ab3 100644 --- a/gen/linker.cpp +++ b/gen/linker.cpp @@ -28,6 +28,11 @@ llvm::cl::opt quiet("quiet", ////////////////////////////////////////////////////////////////////////////// +bool endsWith(const std::string &str, const std::string &end) +{ + return (str.length() >= end.length() && std::equal(end.rbegin(), end.rend(), str.rbegin())); +} + typedef std::vector Module_vector; void linkModules(llvm::Module* dst, const Module_vector& MV) @@ -213,7 +218,7 @@ int linkExecutable(const char* argv0) ////////////////////////////////////////////////////////////////////////////// -int linkObjToExecutable(const char* argv0) +int linkObjToBinary(bool sharedLib) { Logger::println("*** Linking executable ***"); @@ -239,29 +244,45 @@ int linkObjToExecutable(const char* argv0) } // output filename - std::string exestr; - if (global.params.exefile) + std::string output; + if (!sharedLib && global.params.exefile) { // explicit - exestr = global.params.exefile; + output = global.params.exefile; + } + else if (sharedLib && global.params.objname) + { // explicit + output = global.params.objname; } else { // inferred // try root module name if (Module::rootModule) - exestr = Module::rootModule->toChars(); + output = Module::rootModule->toChars(); else if (global.params.objfiles->dim) - exestr = FileName::removeExt((char*)global.params.objfiles->data[0]); + output = FileName::removeExt((char*)global.params.objfiles->data[0]); else - exestr = "a.out"; + output = "a.out"; + } + + if (sharedLib) { + std::string libExt = std::string(".") + global.dll_ext; + if (!endsWith(output, libExt)) + { + if (global.params.os != OSWindows) + output = "lib" + output + libExt; + else + output.append(libExt); + } + args.push_back("-shared"); + } else if (global.params.os == OSWindows && !endsWith(output, ".exe")) { + output.append(".exe"); } - if (global.params.os == OSWindows && !(exestr.rfind(".exe") == exestr.length()-4)) - exestr.append(".exe"); args.push_back("-o"); - args.push_back(exestr.c_str()); + args.push_back(output.c_str()); // set the global gExePath - gExePath.set(exestr); + gExePath.set(output); assert(gExePath.isValid()); // create path to exe @@ -390,13 +411,15 @@ void createStaticLibrary() else if (global.params.objfiles->dim) libName = FileName::removeExt((char*)global.params.objfiles->data[0]); else - libName = "a"; + libName = "a.out"; } std::string libExt = std::string(".") + global.lib_ext; - if (libExt.length() > libName.length() || - !std::equal(libExt.rbegin(), libExt.rend(), libName.rbegin())) + if (!endsWith(libName, libExt)) { - libName.append(libExt); + if (global.params.os != OSWindows) + libName = "lib" + libName + libExt; + else + libName.append(libExt); } args.push_back(libName.c_str()); diff --git a/gen/linker.h b/gen/linker.h index c5c26e62..d76c1778 100644 --- a/gen/linker.h +++ b/gen/linker.h @@ -30,7 +30,7 @@ int linkExecutable(const char* argv0); * @param argv0 the argv[0] value as passed to main * @return 0 on success. */ -int linkObjToExecutable(const char* argv0); +int linkObjToBinary(bool sharedLib); /** * Create a static library from object files. diff --git a/gen/main.cpp b/gen/main.cpp index cebfd741..baf8f888 100644 --- a/gen/main.cpp +++ b/gen/main.cpp @@ -391,7 +391,13 @@ int main(int argc, char** argv) if (!global.params.obj || !global.params.output_o || createStaticLib) global.params.link = 0; - if (global.params.link) + if (createStaticLib && createSharedLib) + error("-lib and -shared switches cannot be used together"); + + if (createSharedLib && mRelocModel == llvm::Reloc::Default) + mRelocModel = llvm::Reloc::PIC_; + + if (global.params.link && !createSharedLib) { global.params.exefile = global.params.objname; if (files.dim > 1) @@ -649,6 +655,14 @@ LDC_TARGETS fatal(); } + if (global.params.os == OSWindows) { + global.dll_ext = "dll"; + global.lib_ext = "lib"; + } else { + global.dll_ext = "so"; + global.lib_ext = "a"; + } + // added in 1.039 if (global.params.doDocComments) VersionCondition::addPredefinedGlobalIdent("D_Ddoc"); @@ -1034,7 +1048,7 @@ LDC_TARGETS else { if (global.params.link) - status = linkObjToExecutable(global.params.argv0); + status = linkObjToBinary(createSharedLib); else if (createStaticLib) createStaticLibrary();