OSDN Git Service

Kill off these headers, which are supposed to be part of binutils-dev,
[uclinux-h8/uClibc.git] / debian / gcc-uClibc / gcc-uClibc.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Copyright (C) 2000 Manuel Novoa III
4  * Copyright (C) 2002-2003 Erik Andersen
5  *
6  * This is a crude wrapper to use uClibc with gcc.
7  * It was originally written to work around ./configure for ext2fs-utils.
8  * It certainly can be improved, but it works for me in the normal cases.
9  *
10  * April 7, 2001
11  *
12  * A bug was fixed in building the gcc command line when dynamic linking.
13  * The functions dlopen, etc. now work.  At this time, you must make sure
14  * the correct libdl.so is included however.  It is safest to, for example,
15  * add /lib/libdl.so.1 if using ld-linux.so.1 rather than adding -ldl to the
16  * command line.
17  *
18  * Note: This is only a problem if devel and target archs are the same.  To
19  * avoid the problem, you can use a customized dynamic linker.
20  *
21  *
22  * April 18, 2001
23  *
24  * The wrapper now works with either installed and uninstalled uClibc versions.
25  * If you want to use the uninstalled header files and libs, either include
26  * the string "build" in the invocation name such as
27  *       'ln -s <ARCH>-uclibc-gcc <ARCH>-uclibc-gcc-build'
28  * or include it in the environment variable setting of UCLIBC_ENV.
29  * Note: This automatically enables the "rpath" behavior described below.
30  *
31  * The wrapper will now pass the location of the uClibc shared libs used to
32  * the linker with the "-rpath" option if the invocation name includes the
33  * string "rpath" or if the environment variable UCLIBC_ENV include it (as
34  * with "build" above).  This is primarily intended to be used on devel
35  * platforms of the same arch as the target.  A good place to use this feature
36  * would be in the uClibc/test directory.
37  *
38  * The wrapper now displays the command line passed to gcc when '-v' is used.
39  *
40  * May 31, 2001
41  *
42  * "rpath" and "build" behavior are now decoupled.  You can of course get
43  * the old "build" behavior by setting UCLIBC_ENV="rpath-build".  Order
44  * isn't important here, as only the substrings are searched for.
45  *
46  * Added environment variable check for UCLIBC_GCC_DLOPT to let user specify
47  * an alternative dynamic linker at runtime without using command line args.
48  * Since this wouldn't commonly be used, I made it easy on myself.  You have
49  * to match the option you would have passed to the gcc wrapper.  As an
50  * example,
51  *
52  *   export UCLIBC_GCC_DLOPT="-Wl,--dynamic-linker,/lib/ld-alt-linker.so.3"
53  *
54  * This is really only useful if target arch == devel arch and DEVEL_PREFIX
55  * isn't empty.  It involves a recompile, but you can at least test apps
56  * on your devel system if combined with the "rpath" behavor if by using
57  * LD_LIBRARY_PATH, etc.
58  *
59  * Also added check for "-Wl,--dynamic-linker" on the command line.  The
60  * use default dynamic linker or the envirnment-specified dynamic linker
61  * is disabled in that case.
62  *
63  * Added options --uclibc-use-build-dir and --uclibc-use-rpath so that those
64  * behaviors can be invoked from the command line.
65  *
66  */
67
68 /*
69  *
70  * TODO:
71  * Check/modify gcc-specific environment variables?
72  */
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <stdarg.h>
77 #include <string.h>
78 #include <unistd.h>
79 #include <errno.h>
80 #include <sys/stat.h>
81 #include <sys/wait.h>
82
83 #include "gcc-uClibc.h"
84
85 static char *our_usr_lib_path = "-L"UCLIBC_DEVEL_PREFIX"/lib";
86
87 static char static_linking[] = "-static";
88 static char nostdinc[] = "-nostdinc";
89 static char nostartfiles[] = "-nostartfiles";
90 static char nodefaultlibs[] = "-nodefaultlibs";
91 static char nostdlib[] = "-nostdlib";
92 #ifdef __UCLIBC_CTOR_DTOR__
93 static char nostdinc_plus[] = "-nostdinc++";
94 #endif
95
96 /* Include a local implementation of basename, since this
97  * uses the host system's C lib, and CYGWIN apparently
98  * doesn't provide an implementation of basename(). */
99 char *basename(const char *path)
100 {
101         register const char *s;
102         register const char *p;
103         p = s = path;
104         while (*s) {
105                 if (*s++ == '/') {
106                         p = s;
107                 }
108         }
109         return (char *) p;
110 }
111
112 char *dirname(char *path)
113 {
114         static const char null_or_empty_or_noslash[] = ".";
115         register char *s;
116         register char *last;
117         char *first;
118
119         last = s = path;
120
121         if (s != NULL) {
122
123 LOOP:
124                 while (*s && (*s != '/')) ++s;
125                 first = s;
126                 while (*s == '/') ++s;
127                 if (*s) {
128                         last = first;
129                         goto LOOP;
130                 }
131
132                 if (last == path) {
133                         if (*last != '/') {
134                                 goto DOT;
135                         }
136                         if ((*++last == '/') && (last[1] == '\0')) {
137                                 ++last;
138                         }
139                 }
140                 *last = '\0';
141                 return path;
142         }
143 DOT:
144         return (char *) null_or_empty_or_noslash;
145 }
146
147
148 extern void *xmalloc(size_t size)
149 {
150         void *ptr = malloc(size);
151
152         if (!ptr) {
153                 fprintf(stderr, "memory exhausted");
154                 exit(EXIT_FAILURE);
155         }
156         return ptr;
157 }
158
159 void xstrcat(char **string, ...)
160 {
161         const char *c;
162         va_list p; 
163         /* Don't bother to calculate how big exerything 
164          * will be, just be careful to not overflow...  */
165         va_start(p, string);
166         *string = xmalloc(BUFSIZ);
167         **string = '\0';
168         while ((c = va_arg(p, const char *))) {
169                 strcat(*string, c); 
170         }
171         va_end(p);
172 }
173
174 int main(int argc, char **argv)
175 {
176         int use_build_dir = 0, linking = 1, use_static_linking = 0;
177         int use_stdinc = 1, use_start = 1, use_stdlib = 1, use_pic = 0;
178         int source_count = 0, use_rpath = 0, verbose = 0;
179         int minusx = 0;
180         int i, j, k, l, m, n;
181         char ** gcc_argv;
182         char ** gcc_argument;
183         char ** libraries;
184         char ** libpath;
185         char *dlstr;
186         char *incstr;
187         char *devprefix;
188         char *builddir;
189         char *libstr;
190         char *build_dlstr = NULL;
191         char *cc;
192         char *ep;
193         char *rpath_link[2];
194         char *rpath[2];
195         char *uClibc_inc[2];
196         char *our_lib_path[2];
197         char *crt0_path[2];
198         char *crtbegin_path[2];
199         char *crtend_path[2];
200         const char *application_name;
201 #ifdef __UCLIBC_CTOR_DTOR__
202         char *crti_path[2];
203         char *crtn_path[2];
204         int len;
205         int ctor_dtor = 1, cplusplus = 0, use_nostdinc_plus = 0;
206         int findlibgcc = 1;
207         char *cpp = NULL;
208 #endif
209 #ifdef __UCLIBC_PROFILING__
210         int profile = 0;
211         char *gcrt1_path[2];
212 #endif
213
214         cc = getenv("UCLIBC_CC");
215         if (cc == NULL) {
216                 cc = GCC_BIN;
217 #ifdef __UCLIBC_CTOR_DTOR__
218                 findlibgcc = 0;
219 #endif
220         }
221
222         application_name = basename(argv[0]);
223         if (application_name[0] == '-')
224                 application_name++;
225
226 #ifdef __UCLIBC_CTOR_DTOR__
227         /* We must use strstr since g++ might be named like a
228          * cross compiler (i.e. arm-linux-g++).   We must also
229          * search carefully, in case we are searching something 
230          * like /opt/c++/gcc-3.1/bin/arm-linux-g++ or some similar 
231          * perversion...  */
232         len = strlen(application_name);
233         if ((strcmp(application_name+len-3, "g++") == 0) ||
234             (strcmp(application_name+len-3, "c++") == 0)) {
235                 len = strlen(cc);
236                 if (strcmp(cc+len-3, "gcc") == 0) {
237                         cpp = strdup(cc);
238                         cpp[len-1] = '+';
239                         cpp[len-2] = '+';
240                 }
241                 cplusplus = 1;
242                 use_nostdinc_plus = 1;
243         }
244 #endif
245
246         devprefix = getenv("UCLIBC_DEVEL_PREFIX");
247         if (!devprefix) {
248                 devprefix = UCLIBC_DEVEL_PREFIX;
249         }
250
251         builddir = getenv("UCLIBC_BUILD_DIR");
252         if (!builddir) {
253                 builddir = UCLIBC_BUILD_DIR;
254         }
255
256         incstr = getenv("UCLIBC_GCC_INC");
257         libstr = getenv("UCLIBC_GCC_LIB");
258
259         ep     = getenv("UCLIBC_ENV");
260         if (!ep) {
261                 ep = "";
262         }
263
264         if (strstr(ep,"build") != NULL) {
265                 use_build_dir = 1;
266         }
267
268         if (strstr(ep,"rpath") != NULL) {
269                 use_rpath = 1;
270         }
271
272
273         xstrcat(&(rpath_link[0]), "-Wl,-rpath-link,", devprefix, "/lib", NULL);
274         xstrcat(&(rpath_link[1]), "-Wl,-rpath-link,", builddir, "/lib", NULL);
275
276         xstrcat(&(rpath[0]), "-Wl,-rpath,", devprefix, "/lib", NULL);
277         xstrcat(&(rpath[1]), "-Wl,-rpath,", builddir, "/lib", NULL);
278
279         xstrcat(&(uClibc_inc[0]), devprefix, "/include/", NULL);
280         xstrcat(&(uClibc_inc[1]), builddir, "/include/", NULL);
281
282 #ifdef __UCLIBC_CTOR_DTOR__
283         xstrcat(&(crt0_path[0]), devprefix, "/lib/crt1.o", NULL);
284         xstrcat(&(crt0_path[1]), builddir, "/lib/crt1.o", NULL);
285         xstrcat(&(crti_path[0]), devprefix, "/lib/crti.o", NULL);
286         xstrcat(&(crti_path[1]), builddir, "/lib/crti.o", NULL);
287         xstrcat(&(crtn_path[0]), devprefix, "/lib/crtn.o", NULL);
288         xstrcat(&(crtn_path[1]), builddir, "/lib/crtn.o", NULL);
289 #else
290         xstrcat(&(crt0_path[0]), devprefix, "/lib/crt0.o", NULL);
291         xstrcat(&(crt0_path[1]), builddir, "/lib/crt0.o", NULL);
292 #endif
293 #ifdef __UCLIBC_PROFILING__
294         xstrcat(&(gcrt1_path[0]), devprefix, "/lib/gcrt1.o", NULL);
295         xstrcat(&(gcrt1_path[1]), builddir, "/lib/gcrt1.o", NULL);
296 #endif
297
298         xstrcat(&(our_lib_path[0]), "-L", devprefix, "/lib", NULL);
299         xstrcat(&(our_lib_path[1]), "-L", builddir, "/lib", NULL);
300
301 #ifdef __UCLIBC_HAS_SHARED__
302         build_dlstr = "-Wl,--dynamic-linker," BUILD_DYNAMIC_LINKER;
303         dlstr = getenv("UCLIBC_GCC_DLOPT");
304         if (!dlstr) {
305                 dlstr = "-Wl,--dynamic-linker," DYNAMIC_LINKER;
306         }
307 #endif
308
309         m = 0;
310         libraries = __builtin_alloca(sizeof(char*) * (argc));
311         libraries[m] = NULL;
312
313         n = 0;
314         libpath = __builtin_alloca(sizeof(char*) * (argc));
315         libpath[n] = NULL;
316
317         for ( i = 1 ; i < argc ; i++ ) {
318                 if (argv[i][0] == '-' && argv[i][1] != '\0') { /* option */
319                         switch (argv[i][1]) {
320                                 case 'c':               /* compile or assemble */
321                                 case 'S':               /* generate assembler code */
322                                 case 'E':               /* preprocess only */
323                                 case 'M':           /* generate dependencies */
324                                         linking = 0;
325                                         break;
326                                 case 'L':               /* library */
327                                         libpath[n++] = argv[i];
328                                         libpath[n] = NULL;
329                                         if (argv[i][2] == '\0') {
330                                                 argv[i] = NULL;
331                                                 libpath[n++] = argv[++i];
332                                                 libpath[n] = NULL;
333                                         }
334                                         argv[i] = NULL;
335                                         break;
336                                 case 'l':               /* library */
337                                         libraries[m++] = argv[i];
338                                         libraries[m] = NULL;
339                                         argv[i] = NULL;
340                                         break;
341                                 case 'x':               /* Set target language */
342                                         minusx = 1;
343                                         i++;
344                                         break;
345                                 case 'v':               /* verbose */
346                                         if (argv[i][2] == '\0') verbose = 1;
347                                         printf("Invoked as %s\n", argv[0]);
348                                         break;
349                                 case 'n':
350                                         if (strcmp(nostdinc, argv[i]) == 0) {
351                                                 use_stdinc = 0;
352                                         } else if (strcmp(nostartfiles, argv[i]) == 0) {
353 #ifdef __UCLIBC_CTOR_DTOR__
354                                                 ctor_dtor = 0;
355 #endif
356                                                 use_start = 0;
357                                         } else if (strcmp(nodefaultlibs, argv[i]) == 0) {
358                                                 use_stdlib = 0;
359                                                 argv[i] = NULL;
360                                         } else if (strcmp(nostdlib, argv[i]) == 0) {
361 #ifdef __UCLIBC_CTOR_DTOR__
362                                                 ctor_dtor = 0;
363 #endif
364                                                 use_start = 0;
365                                                 use_stdlib = 0;
366                                         } 
367 #ifdef __UCLIBC_CTOR_DTOR__
368                                         else if (strcmp(nostdinc_plus, argv[i]) == 0) {
369                                                 if (cplusplus) {
370                                                         use_nostdinc_plus = 0;
371                                                 }
372                                         }
373 #endif
374                                         break;
375                                 case 's':
376                                         if (strstr(argv[i], static_linking) != NULL) {
377                                                 use_static_linking = 1;
378                                         }
379                                         if (strcmp("-shared", argv[i]) == 0) {
380                                                 use_start = 0;
381                                                 use_pic = 1;
382                                         }
383                                         break;
384                                 case 'W':               /* -static could be passed directly to ld */
385                                         if (strncmp("-Wl,", argv[i], 4) == 0) {
386                                                 if (strstr(argv[i], static_linking) != NULL) {
387                                                         use_static_linking = 1;
388                                                 }
389                                                 if (strstr(argv[i], "--dynamic-linker") != NULL) {
390                                                         dlstr = NULL;
391                                                 }
392                                         }
393                                         break;
394 #ifdef __UCLIBC_PROFILING__
395                                 case 'p':
396                                         if (strcmp("-pg", argv[i]) == 0) {
397                                                 profile = 1;
398                                         }
399                                         break;
400 #endif
401                                 case 'f':
402                                         /* Check if we are doing PIC */
403                                         if (strcmp("-fPIC", argv[i]) == 0) {
404                                                 use_pic = 1;
405                                         } else if (strcmp("-fpic", argv[i]) == 0) {
406                                                 use_pic = 1;
407                                         } 
408 #ifdef __UCLIBC_PROFILING__
409                                         else if (strcmp("-fprofile-arcs", argv[i]) == 0) {
410                                                 profile = 1;
411                                         }
412 #endif
413                                         break;
414
415                                 case '-':
416                                         if (strstr(argv[i]+1, static_linking) != NULL) {
417                                                 use_static_linking = 1;
418                                                 argv[i] = NULL;
419                                         } else if (strcmp("--uclibc-use-build-dir", argv[i]) == 0) {
420                                                 use_build_dir = 1;
421                                                 argv[i] = NULL;
422                                         } else if (strcmp("--uclibc-use-rpath", argv[i]) == 0) {
423                                                 use_rpath = 1;
424                                                 argv[i] = NULL;
425                                         } else if (strcmp ("--uclibc-cc", argv[i]) == 0 && argv[i + 1]) {
426                                                 cc = argv[i + 1];
427                                                 argv[i++] = NULL;
428                                                 argv[i] = NULL;
429                                         } else if (strncmp ("--uclibc-cc=", argv[i], 12) == 0) {
430                                                 cc = argv[i] + 12;
431                                                 argv[i] = NULL;
432                                         }
433 #ifdef __UCLIBC_CTOR_DTOR__
434                                         else if (strcmp("--uclibc-no-ctors",argv[i]) == 0) {
435                                                 ctor_dtor = 0;
436                                                 argv[i] = NULL;
437                                         }
438 #endif
439                                         break;
440                         }
441                 } else if (argv[i][0] == '-' && argv[i][1] == '\0') {
442                         /* Reading code from stdin - crazy eh? */
443                         ++source_count;
444                 } else {                                /* assume it is an existing source file */
445                         ++source_count;
446                 }
447         }
448
449         gcc_argv = __builtin_alloca(sizeof(char*) * (argc + 64));
450         gcc_argument = __builtin_alloca(sizeof(char*) * (argc + 20));
451
452         i = 0; k = 0;
453 #ifdef __UCLIBC_CTOR_DTOR__
454         if (ctor_dtor) {
455                 struct stat statbuf;
456                 if (findlibgcc || stat(LIBGCC_DIR, &statbuf) < 0 ||
457                     !S_ISDIR(statbuf.st_mode))
458                 {
459                         /* Bummer, gcc is hiding from us. This is going
460                          * to really slow things down... bummer.  */
461                         int status, gcc_pipe[2];
462                         pid_t pid, wpid;
463
464                         pipe(gcc_pipe);
465                         if (!(pid = fork())) {
466                                 char *argv[4];
467                                 close(gcc_pipe[0]);
468                                 close(1);
469                                 close(2);
470                                 dup2(gcc_pipe[1], 1);
471                                 dup2(gcc_pipe[1], 2);
472                                 argv[0] = cc;
473                                 argv[1] = "-print-libgcc-file-name";
474                                 argv[2] = NULL;
475                                 execvp(cc, argv);
476                                 close(gcc_pipe[1]);
477                                 _exit(EXIT_FAILURE);
478                         }
479                         wpid = 0;
480                         while (wpid != pid) {
481                                 wpid = wait(&status);
482                         }
483                         close(gcc_pipe[1]);
484                         if (WIFEXITED(status) && WEXITSTATUS(status)) {
485 crash_n_burn:
486                                 fprintf(stderr, "Unable to locale crtbegin.o provided by gcc");
487                                 exit(EXIT_FAILURE);
488                         }
489                         if (WIFSIGNALED(status)) {
490                                 fprintf(stderr, "%s exited because of uncaught signal %d", cc, WTERMSIG(status));
491                                 exit(EXIT_FAILURE);
492                         }
493
494                         {
495                                 char buf[1024], *dir;
496                                 status = read(gcc_pipe[0], buf, sizeof(buf));
497                                 close(gcc_pipe[0]);
498                                 if (status < 0) {
499                                         goto crash_n_burn;
500                                 }
501                                 dir = dirname(buf);
502                                 xstrcat(&(crtbegin_path[0]), dir, "/crtbegin.o", NULL);
503                                 xstrcat(&(crtbegin_path[1]), dir, "/crtbeginS.o", NULL);
504                                 xstrcat(&(crtend_path[0]), dir, "/crtend.o", NULL);
505                                 xstrcat(&(crtend_path[1]), dir, "/crtendS.o", NULL);
506                         }
507
508                 } else {
509                         xstrcat(&(crtbegin_path[0]), LIBGCC_DIR, "crtbegin.o", NULL);
510                         xstrcat(&(crtbegin_path[1]), LIBGCC_DIR, "crtbeginS.o", NULL);
511                         xstrcat(&(crtend_path[0]), LIBGCC_DIR, "crtend.o", NULL);
512                         xstrcat(&(crtend_path[1]), LIBGCC_DIR, "crtendS.o", NULL);
513                 }
514         }
515
516         if (cplusplus && cpp)
517                 gcc_argv[i++] = cpp;
518         else
519 #endif
520                 gcc_argv[i++] = cc;
521
522         for ( j = 1 ; j < argc ; j++ ) {
523                 if (argv[j] != NULL) {
524                         gcc_argument[k++] = argv[j];
525                 }
526         }
527         gcc_argument[k] = NULL;
528
529         if (linking && source_count) {
530 #if defined __HAVE_ELF__ && ! defined __UCLIBC_HAS_MMU__
531                 gcc_argv[i++] = "-Wl,-elf2flt";
532 #endif
533                 gcc_argv[i++] = nostdlib;
534                 if (use_static_linking) {
535                         gcc_argv[i++] = static_linking;
536                 }
537                 if (!use_static_linking) {
538                         if (dlstr && use_build_dir) {
539                                 gcc_argv[i++] = build_dlstr;
540                         } else if (dlstr) {
541                                 gcc_argv[i++] = dlstr;
542                         }
543                         if (use_rpath) {
544                                 gcc_argv[i++] = rpath[use_build_dir];
545                         }
546                 }
547                 for ( l = 0 ; l < n ; l++ ) {
548                         if (libpath[l]) gcc_argv[i++] = libpath[l];
549                 }
550                 gcc_argv[i++] = rpath_link[use_build_dir]; /* just to be safe */
551                 if (libstr)
552                         gcc_argv[i++] = libstr;
553                 gcc_argv[i++] = our_lib_path[use_build_dir];
554                 if (!use_build_dir) {
555                         gcc_argv[i++] = our_usr_lib_path;
556                 }
557         }
558         if (use_stdinc && source_count) {
559                 gcc_argv[i++] = nostdinc;
560 #ifdef __UCLIBC_CTOR_DTOR__
561                 if (cplusplus) {
562                         char *cppinc;
563                         if (use_nostdinc_plus) {
564                                 gcc_argv[i++] = nostdinc_plus;
565                         }
566                         xstrcat(&cppinc, uClibc_inc[use_build_dir], "g++/", NULL);
567                         gcc_argv[i++] = "-isystem";
568                         gcc_argv[i++] = cppinc;
569                         xstrcat(&cppinc, uClibc_inc[use_build_dir], "g++-v3/", NULL);
570                         gcc_argv[i++] = "-isystem";
571                         gcc_argv[i++] = cppinc;
572                 }
573 #endif
574                 gcc_argv[i++] = "-isystem";
575                 gcc_argv[i++] = uClibc_inc[use_build_dir];
576                 gcc_argv[i++] = "-iwithprefix";
577                 gcc_argv[i++] = "include";
578                 if (incstr)
579                         gcc_argv[i++] = incstr;
580         }
581
582         if (linking && source_count) {
583
584 #ifdef __UCLIBC_PROFILING__
585                 if (profile) {
586                         gcc_argv[i++] = gcrt1_path[use_build_dir];
587                 }
588 #endif
589 #ifdef __UCLIBC_CTOR_DTOR__
590                 if (ctor_dtor) {
591                         gcc_argv[i++] = crti_path[use_build_dir];
592                         if (use_pic) {
593                                 gcc_argv[i++] = crtbegin_path[1];
594                         } else {
595                                 gcc_argv[i++] = crtbegin_path[0];
596                         }
597                 }
598 #endif
599                 if (use_start) {
600 #ifdef __UCLIBC_PROFILING__
601                         if (!profile)
602 #endif
603                         {
604                                 gcc_argv[i++] = crt0_path[use_build_dir];
605                         }
606                 }
607                 for ( l = 0 ; l < k ; l++ ) {
608                         if (gcc_argument[l]) gcc_argv[i++] = gcc_argument[l];
609                 }
610                 if (use_stdlib) {
611                         //gcc_argv[i++] = "-Wl,--start-group";
612                         gcc_argv[i++] = "-lgcc";
613                 }
614                 for ( l = 0 ; l < m ; l++ ) {
615                         if (libraries[l]) gcc_argv[i++] = libraries[l];
616                 }
617                 if (use_stdlib) {
618 #ifdef __UCLIBC_CTOR_DTOR__
619                         if (cplusplus) {
620                                 gcc_argv[i++] = "-lstdc++";
621                                 gcc_argv[i++] = "-lm";
622                         }
623 #endif
624                         gcc_argv[i++] = "-lc";
625                         gcc_argv[i++] = "-lgcc";
626                         //gcc_argv[i++] = "-Wl,--end-group";
627                 }
628 #ifdef __UCLIBC_CTOR_DTOR__
629                 if (ctor_dtor) {
630                         if (minusx) {
631                                 gcc_argv[i++] = "-x";
632                                 gcc_argv[i++] = "none";
633                         }
634                         if (use_pic) {
635                                 gcc_argv[i++] = crtend_path[1];
636                         } else {
637                                 gcc_argv[i++] = crtend_path[0];
638                         }
639
640                         gcc_argv[i++] = crtn_path[use_build_dir];
641                 }
642 #endif
643         } else {
644                 for ( l = 0 ; l < k ; l++ ) {
645                         if (gcc_argument[l]) gcc_argv[i++] = gcc_argument[l];
646                 }
647         }
648         gcc_argv[i++] = NULL;
649
650         if (verbose) {
651                 for ( j = 0 ; gcc_argv[j] ; j++ ) {
652                         printf("arg[%2i] = %s\n", j, gcc_argv[j]);
653                 }
654                 fflush(stdout);
655         }
656         //no need to free memory from xstrcat because we never return... 
657 #ifdef __UCLIBC_CTOR_DTOR__
658         if (cplusplus && cpp) {
659                 execvp(cpp, gcc_argv);
660                 fprintf(stderr, "%s: %s\n", cpp, strerror(errno));
661         } else
662 #endif
663         {
664                 execvp(cc, gcc_argv);
665                 fprintf(stderr, "%s: %s\n", cc, strerror(errno));
666         }
667         exit(EXIT_FAILURE);
668 }