From fdead0d154ec4e343ad38637ff20a5ff06fde7d0 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 6 Dec 2011 17:24:49 +0400 Subject: [PATCH] =?UTF-8?q?Fixed=20#21=20=E2=80=94=20Added=20-lib=20switch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dmd2/mars.c | 3 ++ gen/cl_options.cpp | 4 +++ gen/cl_options.h | 1 + gen/linker.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++++ gen/linker.h | 5 +++ gen/main.cpp | 6 +++- gen/programs.cpp | 49 +++++++++++++++++--------- gen/programs.h | 1 + 8 files changed, 137 insertions(+), 18 deletions(-) diff --git a/dmd2/mars.c b/dmd2/mars.c index f05ea012..82123751 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -72,7 +72,10 @@ 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 b6b51261..0be4aa97 100644 --- a/gen/cl_options.cpp +++ b/gen/cl_options.cpp @@ -39,6 +39,10 @@ cl::opt compileOnly("c", cl::desc("Do not link"), cl::ZeroOrMore); +cl::opt createStaticLib("lib", + cl::desc("Create static library"), + 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 c3ffcda9..6c44b3a2 100644 --- a/gen/cl_options.h +++ b/gen/cl_options.h @@ -19,6 +19,7 @@ namespace opts { extern cl::list fileList; extern cl::list runargs; extern cl::opt compileOnly; + extern cl::opt createStaticLib; extern cl::opt noAsm; extern cl::opt dontWriteObj; extern cl::opt objectFile; diff --git a/gen/linker.cpp b/gen/linker.cpp index 24874e50..4996a2f2 100644 --- a/gen/linker.cpp +++ b/gen/linker.cpp @@ -357,6 +357,92 @@ int linkObjToExecutable(const char* argv0) ////////////////////////////////////////////////////////////////////////////// +void createStaticLibrary() +{ + Logger::println("*** Creating static library ***"); + + // error string + std::string errstr; + + // find archiver + llvm::sys::Path ar = getArchiver(); + + // build arguments + std::vector args; + + // first the program name ?? + args.push_back(ar.c_str()); + + // ask ar to create a new library + args.push_back("rcs"); + + // output filename + std::string libName; + if (global.params.objname) + { // explicit + libName = global.params.objname; + } + else + { // inferred + // try root module name + if (Module::rootModule) + libName = Module::rootModule->toChars(); + else if (global.params.objfiles->dim) + libName = FileName::removeExt((char*)global.params.objfiles->data[0]); + else + libName = "a"; + } + std::string libExt = std::string(".") + global.lib_ext; + if (libExt.length() > libName.length() || + !std::equal(libExt.rbegin(), libExt.rend(), libName.rbegin())) + { + libName.append(libExt); + } + args.push_back(libName.c_str()); + + // object files + for (unsigned i = 0; i < global.params.objfiles->dim; i++) + { + char *p = (char *)global.params.objfiles->data[i]; + args.push_back(p); + } + + // create path to the library + llvm::sys::Path libdir(llvm::sys::path::parent_path(libName.c_str())); + if (!libdir.empty() && !llvm::sys::fs::exists(libdir.str())) + { + libdir.createDirectoryOnDisk(true, &errstr); + if (!errstr.empty()) + { + error("failed to create path to linking output: %s\n%s", libdir.c_str(), errstr.c_str()); + fatal(); + } + } + + // print the command? + if (!quiet || global.params.verbose) + { + // Print it + for (int i = 0; i < args.size(); i++) + printf("%s ", args[i]); + printf("\n"); + fflush(stdout); + } + + // terminate args list + args.push_back(NULL); + + // try to call archiver + if (int status = llvm::sys::Program::ExecuteAndWait(ar, &args[0], NULL, NULL, 0,0, &errstr)) + { + error("archiver failed:\nstatus: %d", status); + if (!errstr.empty()) + error("message: %s", errstr.c_str()); + } +} + +////////////////////////////////////////////////////////////////////////////// + void deleteExecutable() { if (!gExePath.isEmpty()) diff --git a/gen/linker.h b/gen/linker.h index 0977f556..c5c26e62 100644 --- a/gen/linker.h +++ b/gen/linker.h @@ -32,6 +32,11 @@ int linkExecutable(const char* argv0); */ int linkObjToExecutable(const char* argv0); +/** + * Create a static library from object files. +*/ +void createStaticLibrary(); + /** * Delete the executable that was previously linked with linkExecutable. */ diff --git a/gen/main.cpp b/gen/main.cpp index fa70434d..cebfd741 100644 --- a/gen/main.cpp +++ b/gen/main.cpp @@ -388,7 +388,7 @@ int main(int argc, char** argv) } // only link if possible - if (!global.params.obj || !global.params.output_o) + if (!global.params.obj || !global.params.output_o || createStaticLib) global.params.link = 0; if (global.params.link) @@ -1028,11 +1028,15 @@ LDC_TARGETS { if (global.params.link) error("no object files to link"); + else if (createStaticLib) + error("no object files"); } else { if (global.params.link) status = linkObjToExecutable(global.params.argv0); + else if (createStaticLib) + createStaticLibrary(); if (global.params.run) { diff --git a/gen/programs.cpp b/gen/programs.cpp index 00134314..7fb4effe 100644 --- a/gen/programs.cpp +++ b/gen/programs.cpp @@ -13,27 +13,42 @@ static cl::opt gcc("gcc", cl::Hidden, cl::ZeroOrMore); +static cl::opt ar("ar", + cl::desc("Archiver"), + cl::Hidden, + cl::ZeroOrMore); -sys::Path getGcc() { - const char *cc = NULL; - - if (gcc.getNumOccurrences() > 0 && gcc.length() > 0) - cc = gcc.c_str(); - - if (!cc) - cc = getenv("CC"); - if (!cc) - cc = "gcc"; - - sys::Path path = sys::Program::FindProgramByName(cc); - if (path.empty() && !cc) { - if (cc) { - path.set(cc); +sys::Path getProgram(const char *name, const cl::opt &opt, const char *envVar = 0) +{ + const char *prog = NULL; + + if (opt.getNumOccurrences() > 0 && opt.length() > 0) + prog = gcc.c_str(); + + if (!prog && envVar) + prog = getenv(envVar); + if (!prog) + prog = name; + + sys::Path path = sys::Program::FindProgramByName(prog); + if (path.empty() && !prog) { + if (prog) { + path.set(prog); } else { - error("failed to locate gcc"); + error("failed to locate %s", name); fatal(); } } - + return path; } + +sys::Path getGcc() +{ + return getProgram("gcc", gcc, "CC"); +} + +sys::Path getArchiver() +{ + return getProgram("ar", ar); +} diff --git a/gen/programs.h b/gen/programs.h index 38f3135b..e3c9c2ee 100644 --- a/gen/programs.h +++ b/gen/programs.h @@ -4,5 +4,6 @@ #include "llvm/Support/Path.h" llvm::sys::Path getGcc(); +llvm::sys::Path getArchiver(); #endif