diff --git a/dmd/link.c b/dmd/link.c deleted file mode 100644 index 88175e7fd4..0000000000 --- a/dmd/link.c +++ /dev/null @@ -1,224 +0,0 @@ - - -// Copyright (c) 1999-2007 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include -#include -#include -#include - -#if _WIN32 -#include -#endif - -#if linux -#include -#include -#include -#endif - -#include "root.h" - -#include "mars.h" - -#include "mem.h" - -#include "gen/logger.h" - -int executecmd(char *cmd, char *args, int useenv); -int executearg0(char *cmd, char *args); - -/********************************** - * Delete generated EXE file. - */ - -void deleteExeFile() -{ - if (global.params.exefile) - { - //printf("deleteExeFile() %s\n", global.params.exefile); - remove(global.params.exefile); - } -} - -/****************************** - * Execute a rule. Return the status. - * cmd program to run - * args arguments to cmd, as a string - * useenv if cmd knows about _CMDLINE environment variable - */ - -#if _WIN32 -int executecmd(char *cmd, char *args, int useenv) -{ - int status; - char *buff; - size_t len; - - if (!global.params.quiet || global.params.verbose) - { - printf("%s %s\n", cmd, args); - fflush(stdout); - } - - if ((len = strlen(args)) > 255) - { char *q; - static char envname[] = "@_CMDLINE"; - - envname[0] = '@'; - switch (useenv) - { case 0: goto L1; - case 2: envname[0] = '%'; break; - } - q = (char *) alloca(sizeof(envname) + len + 1); - sprintf(q,"%s=%s", envname + 1, args); - status = putenv(q); - if (status == 0) - args = envname; - else - { - L1: - error("command line length of %d is too long",len); - } - } - - status = executearg0(cmd,args); -#if _WIN32 - if (status == -1) - status = spawnlp(0,cmd,cmd,args,NULL); -#endif -// if (global.params.verbose) -// printf("\n"); - if (status) - { - if (status == -1) - printf("Can't run '%s', check PATH\n", cmd); - else - printf("--- errorlevel %d\n", status); - } - return status; -} -#endif - -/************************************** - * Attempt to find command to execute by first looking in the directory - * where DMD was run from. - * Returns: - * -1 did not find command there - * !=-1 exit status from command - */ - -#if _WIN32 -int executearg0(char *cmd, char *args) -{ - char *file; - char *argv0 = global.params.argv0; - - //printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args); - - // If cmd is fully qualified, we don't do this - if (FileName::absolute(cmd)) - return -1; - - file = FileName::replaceName(argv0, cmd); - - //printf("spawning '%s'\n",file); -#if _WIN32 - return spawnl(0,file,file,args,NULL); -#elif linux - char *full; - int cmdl = strlen(cmd); - - full = (char*) mem.malloc(cmdl + strlen(args) + 2); - if (full == NULL) - return 1; - strcpy(full, cmd); - full [cmdl] = ' '; - strcpy(full + cmdl + 1, args); - - int result = system(full); - - mem.free(full); - return result; -#else - assert(0); -#endif -} -#endif - -/*************************************** - * Run the compiled program. - * Return exit status. - */ - -int runProgram() -{ - //printf("runProgram()\n"); - if (global.params.verbose) - { - printf("%s", global.params.exefile); - for (size_t i = 0; i < global.params.runargs_length; i++) - printf(" %s", (char *)global.params.runargs[i]); - printf("\n"); - } - - // Build argv[] - Array argv; - - argv.push((void *)global.params.exefile); - for (size_t i = 0; i < global.params.runargs_length; i++) - { char *a = global.params.runargs[i]; - -#if _WIN32 - // BUG: what about " appearing in the string? - if (strchr(a, ' ')) - { char *b = (char *)mem.malloc(3 + strlen(a)); - sprintf(b, "\"%s\"", a); - a = b; - } -#endif - argv.push((void *)a); - } - argv.push(NULL); - -#if _WIN32 - char *ex = FileName::name(global.params.exefile); - if (ex == global.params.exefile) - ex = FileName::combine(".", ex); - else - ex = global.params.exefile; - return spawnv(0,ex,(char **)argv.data); -#elif linux - pid_t childpid; - int status; - - childpid = fork(); - if (childpid == 0) - { - char *fn = (char *)argv.data[0]; - if (!FileName::absolute(fn)) - { // Make it "./fn" - fn = FileName::combine(".", fn); - } - execv(fn, (char **)argv.data); - perror(fn); // failed to execute - return -1; - } - - waitpid(childpid, &status, 0); - - status = WEXITSTATUS(status); - return status; -#else - assert(0); -#endif -} diff --git a/dmd/mars.c b/dmd/mars.c index 2c60d7abe6..129831300d 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -43,6 +43,7 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); #include "lexer.h" #include "gen/logger.h" +#include "gen/linker.h" void getenv_setargv(const char *envvar, int *pargc, char** *pargv); @@ -1110,7 +1111,7 @@ int main(int argc, char *argv[]) { if (!status) { - status = runProgram(); + status = runExectuable(); /* Delete .obj files and .exe file */ @@ -1119,7 +1120,7 @@ int main(int argc, char *argv[]) m = (Module *)modules.data[i]; m->deleteObjFile(); } - deleteExeFile(); + deleteExecutable(); } } } diff --git a/dmd/mars.h b/dmd/mars.h index f41bb3c839..4167a5392a 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -304,15 +304,9 @@ void error(Loc loc, const char *format, ...); void verror(Loc loc, const char *format, va_list); void fatal(); void err_nomem(); -//int runLINK(); // no longer used -void deleteExeFile(); -int runProgram(); void inifile(char *argv0, char *inifile); void halt(); -// LLVMDC -int linkExecutable(); - /*** Where to send error messages ***/ #if IN_GCC #define stdmsg stderr diff --git a/gen/linker.cpp b/gen/linker.cpp index f89be7abf2..fa59b45d8b 100644 --- a/gen/linker.cpp +++ b/gen/linker.cpp @@ -33,6 +33,8 @@ void linkModules(llvm::Module* dst, const Module_vector& MV) ////////////////////////////////////////////////////////////////////////////// +static llvm::sys::Path gExePath; + int linkExecutable() { Logger::println("*** Linking executable ***"); @@ -74,10 +76,14 @@ int linkExecutable() std::string outopt = "-o=" + exestr; args.push_back(outopt.c_str()); + // set the global gExePath + gExePath.set(exestr); + assert(gExePath.isValid()); + // create path to exe - llvm::sys::Path exepath(exestr); - exepath.set(exepath.getDirname()); - exepath.createDirectoryOnDisk(true, &errstr); + llvm::sys::Path exedir(gExePath); + exedir.set(gExePath.getDirname()); + exedir.createDirectoryOnDisk(true, &errstr); if (!errstr.empty()) { error("failed to create path to linking output\n%s", errstr.c_str()); @@ -181,3 +187,44 @@ int linkExecutable() fatal(); } } + +////////////////////////////////////////////////////////////////////////////// + +void deleteExecutable() +{ + if (!gExePath.isEmpty()) + { + assert(gExePath.isValid()); + assert(!gExePath.isDirectory()); + gExePath.eraseFromDisk(false); + } +} + +////////////////////////////////////////////////////////////////////////////// + +int runExectuable() +{ + assert(!gExePath.isEmpty()); + assert(gExePath.isValid()); + + // build arguments + std::vector args; + for (size_t i = 0; i < global.params.runargs_length; i++) + { + char *a = global.params.runargs[i]; + args.push_back(a); + } + // terminate args list + args.push_back(NULL); + + // try to call linker!!! + std::string errstr; + int status = llvm::sys::Program::ExecuteAndWait(gExePath, &args[0], NULL, NULL, 0,0, &errstr); + if (!errstr.empty()) + { + error("failed to execute program"); + if (!errstr.empty()) + error("error message: %s", errstr.c_str()); + fatal(); + } +} diff --git a/gen/linker.h b/gen/linker.h index 6842bf2b9e..2426f40684 100644 --- a/gen/linker.h +++ b/gen/linker.h @@ -14,4 +14,15 @@ void linkModules(llvm::Module* dst, const std::vector& MV); */ int linkExecutable(); +/** + * Delete the executable that was previously linked with linkExecutable. + */ +void deleteExecutable(); + +/** + * Runs the executable that was previously linked with linkExecutable. + * @return the return status of the executable. + */ +int runExectuable(); + #endif // LLVMDC_GEN_LINKER_H