Fixed #21 — Added -lib switch

This commit is contained in:
Alexey Prokhin 2011-12-06 17:24:49 +04:00
parent 859ae8481f
commit fdead0d154
8 changed files with 137 additions and 18 deletions

View file

@ -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

View file

@ -39,6 +39,10 @@ cl::opt<bool> compileOnly("c",
cl::desc("Do not link"),
cl::ZeroOrMore);
cl::opt<bool> createStaticLib("lib",
cl::desc("Create static library"),
cl::ZeroOrMore);
static cl::opt<bool, true> verbose("v",
cl::desc("Verbose"),
cl::ZeroOrMore,

View file

@ -19,6 +19,7 @@ namespace opts {
extern cl::list<std::string> fileList;
extern cl::list<std::string> runargs;
extern cl::opt<bool> compileOnly;
extern cl::opt<bool> createStaticLib;
extern cl::opt<bool> noAsm;
extern cl::opt<bool> dontWriteObj;
extern cl::opt<std::string> objectFile;

View file

@ -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<const char*> 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())

View file

@ -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.
*/

View file

@ -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)
{

View file

@ -13,27 +13,42 @@ static cl::opt<std::string> gcc("gcc",
cl::Hidden,
cl::ZeroOrMore);
static cl::opt<std::string> ar("ar",
cl::desc("Archiver"),
cl::Hidden,
cl::ZeroOrMore);
sys::Path getGcc() {
const char *cc = NULL;
sys::Path getProgram(const char *name, const cl::opt<std::string> &opt, const char *envVar = 0)
{
const char *prog = NULL;
if (gcc.getNumOccurrences() > 0 && gcc.length() > 0)
cc = gcc.c_str();
if (opt.getNumOccurrences() > 0 && opt.length() > 0)
prog = gcc.c_str();
if (!cc)
cc = getenv("CC");
if (!cc)
cc = "gcc";
if (!prog && envVar)
prog = getenv(envVar);
if (!prog)
prog = name;
sys::Path path = sys::Program::FindProgramByName(cc);
if (path.empty() && !cc) {
if (cc) {
path.set(cc);
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);
}

View file

@ -4,5 +4,6 @@
#include "llvm/Support/Path.h"
llvm::sys::Path getGcc();
llvm::sys::Path getArchiver();
#endif