[svn r298] Eliminated the dmd/link.c source file entirely in favor of a llvm::sys based approach to the same functionality.

This commit is contained in:
Tomas Lindquist Olsen 2008-06-20 22:09:04 +02:00
parent c743549032
commit 41a104c0f4
5 changed files with 64 additions and 235 deletions

View file

@ -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 <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#if _WIN32
#include <process.h>
#endif
#if linux
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#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
}

View file

@ -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();
}
}
}

View file

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

View file

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

View file

@ -14,4 +14,15 @@ void linkModules(llvm::Module* dst, const std::vector<llvm::Module*>& 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