# HG changeset patch # User lindquist # Date 1213992544 -7200 # Node ID 90a8c798b0dba0394eda1f6edcb03d2bebc821a1 # Parent 21f85bac0b1ab1d580d050ae798cf53b2981547d [svn r298] Eliminated the dmd/link.c source file entirely in favor of a llvm::sys based approach to the same functionality. diff -r 21f85bac0b1a -r 90a8c798b0db dmd/link.c --- a/dmd/link.c Fri Jun 20 17:45:13 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r 21f85bac0b1a -r 90a8c798b0db dmd/mars.c --- a/dmd/mars.c Fri Jun 20 17:45:13 2008 +0200 +++ b/dmd/mars.c Fri Jun 20 22:09:04 2008 +0200 @@ -43,6 +43,7 @@ #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 @@ { if (!status) { - status = runProgram(); + status = runExectuable(); /* Delete .obj files and .exe file */ @@ -1119,7 +1120,7 @@ m = (Module *)modules.data[i]; m->deleteObjFile(); } - deleteExeFile(); + deleteExecutable(); } } } diff -r 21f85bac0b1a -r 90a8c798b0db dmd/mars.h --- a/dmd/mars.h Fri Jun 20 17:45:13 2008 +0200 +++ b/dmd/mars.h Fri Jun 20 22:09:04 2008 +0200 @@ -304,15 +304,9 @@ 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 -r 21f85bac0b1a -r 90a8c798b0db gen/linker.cpp --- a/gen/linker.cpp Fri Jun 20 17:45:13 2008 +0200 +++ b/gen/linker.cpp Fri Jun 20 22:09:04 2008 +0200 @@ -33,6 +33,8 @@ ////////////////////////////////////////////////////////////////////////////// +static llvm::sys::Path gExePath; + int linkExecutable() { Logger::println("*** Linking executable ***"); @@ -74,10 +76,14 @@ 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 @@ 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 -r 21f85bac0b1a -r 90a8c798b0db gen/linker.h --- a/gen/linker.h Fri Jun 20 17:45:13 2008 +0200 +++ b/gen/linker.h Fri Jun 20 22:09:04 2008 +0200 @@ -14,4 +14,15 @@ */ 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