3 // Copyright (c) 1999-2007 by Digital Mars
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
24 #include <sys/types.h>
35 int executecmd(char *cmd
, char *args
, int useenv
);
36 int executearg0(char *cmd
, char *args
);
38 /*****************************
39 * Run the linker. Return status of execution.
50 global
.params
.libfiles
->push((void *) "user32");
51 global
.params
.libfiles
->push((void *) "kernel32");
53 for (i
= 0; i
< global
.params
.objfiles
->dim
; i
++)
56 cmdbuf
.writeByte('+');
57 p
= (char *)global
.params
.objfiles
->data
[i
];
58 char *ext
= FileName::ext(p
);
60 cmdbuf
.write(p
, ext
- p
- 1);
62 cmdbuf
.writestring(p
);
64 cmdbuf
.writeByte(',');
65 if (global
.params
.exefile
)
66 cmdbuf
.writestring(global
.params
.exefile
);
68 { // Generate exe file name from first obj name
69 char *n
= (char *)global
.params
.objfiles
->data
[0];
70 n
= FileName::name(n
);
71 FileName
*fn
= FileName::forceExt(n
, "exe");
72 global
.params
.exefile
= fn
->toChars();
75 // Make sure path to exe file exists
76 { char *p
= FileName::path(global
.params
.exefile
);
77 FileName::ensurePathExists(p
);
81 cmdbuf
.writeByte(',');
82 if (global
.params
.run
)
83 cmdbuf
.writestring("nul");
85 // cmdbuf.writestring(output);
86 cmdbuf
.writeByte(',');
88 for (i
= 0; i
< global
.params
.libfiles
->dim
; i
++)
91 cmdbuf
.writeByte('+');
92 cmdbuf
.writestring((char *) global
.params
.libfiles
->data
[i
]);
95 if (global
.params
.deffile
)
97 cmdbuf
.writeByte(',');
98 cmdbuf
.writestring(global
.params
.deffile
);
101 /* Eliminate unnecessary trailing commas */
104 if (!i
|| cmdbuf
.data
[i
- 1] != ',')
109 if (global
.params
.resfile
)
111 cmdbuf
.writestring("/RC:");
112 cmdbuf
.writestring(global
.params
.resfile
);
117 cmdbuf
.writestring("/m");
119 cmdbuf
.writestring("/li");
122 cmdbuf
.writestring("/co");
124 cmdbuf
.writestring(":3");
127 if (global
.params
.symdebug
)
128 cmdbuf
.writestring("/co");
131 cmdbuf
.writestring("/noi");
132 for (i
= 0; i
< global
.params
.linkswitches
->dim
; i
++)
134 cmdbuf
.writestring((char *) global
.params
.linkswitches
->data
[i
]);
136 cmdbuf
.writeByte(';');
138 p
= cmdbuf
.toChars();
140 FileName
*lnkfilename
= NULL
;
141 size_t plen
= strlen(p
);
144 lnkfilename
= FileName::forceExt(global
.params
.exefile
, "lnk");
145 File
flnk(lnkfilename
);
146 flnk
.setbuffer(p
, plen
);
149 error("error writing file %s", lnkfilename
);
150 if (lnkfilename
->len() < plen
)
151 sprintf(p
, "@%s", lnkfilename
->toChars());
154 char *linkcmd
= getenv("LINKCMD");
157 status
= executecmd(linkcmd
, p
, 1);
160 remove(lnkfilename
->toChars());
172 char *cc
= getenv("CC");
175 argv
.push((void *)cc
);
176 argv
.insert(1, global
.params
.objfiles
);
178 // None of that a.out stuff. Use explicit exe file name, or
179 // generate one from name of first source file.
180 argv
.push((void *)"-o");
181 if (global
.params
.exefile
)
183 argv
.push(global
.params
.exefile
);
186 { // Generate exe file name from first obj name
187 char *n
= (char *)global
.params
.objfiles
->data
[0];
191 n
= FileName::name(n
);
192 e
= FileName::ext(n
);
195 e
--; // back up over '.'
196 ex
= (char *)mem
.malloc(e
- n
+ 1);
197 memcpy(ex
, n
, e
- n
);
201 ex
= (char *)"a.out"; // no extension, so give up
203 global
.params
.exefile
= ex
;
206 // Make sure path to exe file exists
207 { char *p
= FileName::path(global
.params
.exefile
);
208 FileName::ensurePathExists(p
);
212 argv
.insert(argv
.dim
, global
.params
.libfiles
);
214 if (global
.params
.symdebug
)
215 argv
.push((void *)"-g");
217 argv
.push((void *)"-m32");
219 if (0 && global
.params
.exefile
)
221 /* This switch enables what is known as 'smart linking'
222 * in the Windows world, where unreferenced sections
223 * are removed from the executable. It eliminates unreferenced
224 * functions, essentially making a 'library' out of a module.
225 * Although it is documented to work with ld version 2.13,
226 * in practice it does not, but just seems to be ignored.
227 * Thomas Kuehne has verified that it works with ld 2.16.1.
228 * BUG: disabled because it causes exception handling to fail
230 argv
.push((void *)"-Xlinker");
231 argv
.push((void *)"--gc-sections");
234 for (i
= 0; i
< global
.params
.linkswitches
->dim
; i
++)
235 { char *p
= (char *)global
.params
.linkswitches
->data
[i
];
236 if (!p
|| !p
[0] || !(p
[0] == '-' && p
[1] == 'l'))
237 // Don't need -Xlinker if switch starts with -l
238 argv
.push((void *)"-Xlinker");
239 argv
.push((void *) p
);
242 /* Standard libraries must go after user specified libraries
245 char *libname
= (global
.params
.symdebug
)
246 ? global
.params
.debuglibname
247 : global
.params
.defaultlibname
;
248 char *buf
= (char *)malloc(2 + strlen(libname
) + 1);
250 strcpy(buf
+ 2, libname
);
251 argv
.push((void *)buf
); // turns into /usr/lib/libphobos2.a
253 argv
.push((void *)"-lpthread");
254 argv
.push((void *)"-lm");
256 if (!global
.params
.quiet
|| global
.params
.verbose
)
259 for (i
= 0; i
< argv
.dim
; i
++)
260 printf("%s ", (char *)argv
.data
[i
]);
269 execvp((char *)argv
.data
[0], (char **)argv
.data
);
270 perror((char *)argv
.data
[0]); // failed to execute
274 waitpid(childpid
, &status
, 0);
276 status
=WEXITSTATUS(status
);
278 printf("--- errorlevel %d\n", status
);
281 printf ("Linking is not yet supported for this version of DMD.\n");
286 /**********************************
287 * Delete generated EXE file.
292 if (global
.params
.exefile
)
294 //printf("deleteExeFile() %s\n", global.params.exefile);
295 remove(global
.params
.exefile
);
299 /******************************
300 * Execute a rule. Return the status.
302 * args arguments to cmd, as a string
303 * useenv if cmd knows about _CMDLINE environment variable
307 int executecmd(char *cmd
, char *args
, int useenv
)
313 if (!global
.params
.quiet
|| global
.params
.verbose
)
315 printf("%s %s\n", cmd
, args
);
319 if ((len
= strlen(args
)) > 255)
321 static char envname
[] = "@_CMDLINE";
326 case 2: envname
[0] = '%'; break;
328 q
= (char *) alloca(sizeof(envname
) + len
+ 1);
329 sprintf(q
,"%s=%s", envname
+ 1, args
);
336 error("command line length of %d is too long",len
);
340 status
= executearg0(cmd
,args
);
343 status
= spawnlp(0,cmd
,cmd
,args
,NULL
);
345 // if (global.params.verbose)
350 printf("Can't run '%s', check PATH\n", cmd
);
352 printf("--- errorlevel %d\n", status
);
358 /**************************************
359 * Attempt to find command to execute by first looking in the directory
360 * where DMD was run from.
362 * -1 did not find command there
363 * !=-1 exit status from command
367 int executearg0(char *cmd
, char *args
)
370 char *argv0
= global
.params
.argv0
;
372 //printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args);
374 // If cmd is fully qualified, we don't do this
375 if (FileName::absolute(cmd
))
378 file
= FileName::replaceName(argv0
, cmd
);
380 //printf("spawning '%s'\n",file);
382 return spawnl(0,file
,file
,args
,NULL
);
385 int cmdl
= strlen(cmd
);
387 full
= (char*) mem
.malloc(cmdl
+ strlen(args
) + 2);
392 strcpy(full
+ cmdl
+ 1, args
);
394 int result
= system(full
);
404 /***************************************
405 * Run the compiled program.
406 * Return exit status.
411 //printf("runProgram()\n");
412 if (global
.params
.verbose
)
414 printf("%s", global
.params
.exefile
);
415 for (size_t i
= 0; i
< global
.params
.runargs_length
; i
++)
416 printf(" %s", (char *)global
.params
.runargs
[i
]);
423 argv
.push((void *)global
.params
.exefile
);
424 for (size_t i
= 0; i
< global
.params
.runargs_length
; i
++)
425 { char *a
= global
.params
.runargs
[i
];
428 // BUG: what about " appearing in the string?
430 { char *b
= (char *)mem
.malloc(3 + strlen(a
));
431 sprintf(b
, "\"%s\"", a
);
435 argv
.push((void *)a
);
440 char *ex
= FileName::name(global
.params
.exefile
);
441 if (ex
== global
.params
.exefile
)
442 ex
= FileName::combine(".", ex
);
444 ex
= global
.params
.exefile
;
445 return spawnv(0,ex
,(char **)argv
.data
);
453 char *fn
= (char *)argv
.data
[0];
454 if (!FileName::absolute(fn
))
456 fn
= FileName::combine(".", fn
);
458 execv(fn
, (char **)argv
.data
);
459 perror(fn
); // failed to execute
463 waitpid(childpid
, &status
, 0);
465 status
= WEXITSTATUS(status
);