mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 08:30:47 +03:00
[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:
parent
c743549032
commit
41a104c0f4
5 changed files with 64 additions and 235 deletions
224
dmd/link.c
224
dmd/link.c
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
11
gen/linker.h
11
gen/linker.h
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue