changeset 277:90a8c798b0db trunk

[svn r298] Eliminated the dmd/link.c source file entirely in favor of a llvm::sys based approach to the same functionality.
author lindquist
date Fri, 20 Jun 2008 22:09:04 +0200
parents 21f85bac0b1a
children 30941d8ee320
files dmd/link.c dmd/mars.c dmd/mars.h gen/linker.cpp gen/linker.h
diffstat 5 files changed, 64 insertions(+), 235 deletions(-) [+]
line wrap: on
line diff
--- 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	<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
-}
--- 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();
 	    }
 	}
     }
--- 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
--- 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<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();
+    }
+}
--- 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