Mercurial > projects > ldc
diff gen/linker.cpp @ 677:075c1272a01d
Link using gcc instead.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Sat, 11 Oct 2008 21:21:21 +0200 |
parents | 6aaa3d3c1183 |
children | ca4a816f2440 |
line wrap: on
line diff
--- a/gen/linker.cpp Sat Oct 11 20:00:36 2008 +0200 +++ b/gen/linker.cpp Sat Oct 11 21:21:21 2008 +0200 @@ -197,6 +197,133 @@ ////////////////////////////////////////////////////////////////////////////// +int linkObjToExecutable(const char* argv0) +{ + Logger::println("*** Linking executable ***"); + + // error string + std::string errstr; + + // find gcc for linking + llvm::sys::Path gcc = llvm::sys::Program::FindProgramByName("gcc"); + if (gcc.isEmpty()) + { + gcc.set("gcc"); + } + + // build arguments + std::vector<const char*> args; + + // first the program name ?? + args.push_back("gcc"); + + // output filename + std::string exestr; + if (global.params.exefile) + { // explicit + exestr = global.params.exefile; + } + else + { // inferred + // try root module name + if (Module::rootModule) + exestr = Module::rootModule->toChars(); + else + exestr = "a.out"; + } + if (global.params.os == OSWindows) + exestr.append(".exe"); + + args.push_back("-o"); + args.push_back(exestr.c_str()); + + // set the global gExePath + gExePath.set(exestr); + assert(gExePath.isValid()); + + // create path to exe + llvm::sys::Path exedir(gExePath); + exedir.set(gExePath.getDirname()); + if (!exedir.exists()) + { + exedir.createDirectoryOnDisk(true, &errstr); + if (!errstr.empty()) + { + error("failed to create path to linking output: %s\n%s", exedir.c_str(), errstr.c_str()); + fatal(); + } + } + + // additional linker switches + for (int i = 0; i < global.params.linkswitches->dim; i++) + { + char *p = (char *)global.params.linkswitches->data[i]; + args.push_back(p); + } + + // user libs + for (int i = 0; i < global.params.libfiles->dim; i++) + { + char *p = (char *)global.params.libfiles->data[i]; + args.push_back(p); + } + + // default libs + switch(global.params.os) { + case OSLinux: + case OSMacOSX: + args.push_back("-ldl"); + case OSFreeBSD: + args.push_back("-lpthread"); + args.push_back("-lm"); + break; + + case OSWindows: + // FIXME: I'd assume kernel32 etc + break; + } + + // object files + for (int i = 0; i < global.params.objfiles->dim; i++) + { + char *p = (char *)global.params.objfiles->data[i]; + args.push_back(p); + } + + // print link command? + if (!global.params.quiet || global.params.verbose) + { + // Print it + for (int i = 0; i < args.size(); i++) + printf("%s ", args[i]); + printf("\n"); + fflush(stdout); + } + + Logger::println("Linking with: "); + std::vector<const char*>::const_iterator I = args.begin(), E = args.end(); + std::ostream& logstr = Logger::cout(); + for (; I != E; ++I) + if (*I) + logstr << "'" << *I << "'" << " "; + logstr << "\n" << std::flush; + + + // terminate args list + args.push_back(NULL); + + // try to call linker!!! + if (int status = llvm::sys::Program::ExecuteAndWait(gcc, &args[0], NULL, NULL, 0,0, &errstr)) + { + error("linking failed:\nstatus: %d", status); + if (!errstr.empty()) + error("message: %s", errstr.c_str()); + fatal(); + } +} + +////////////////////////////////////////////////////////////////////////////// + void deleteExecutable() { if (!gExePath.isEmpty())