OSDN Git Service

719cf621c1ce69ede644bbf5a9ee388087bc6442
[uclinux-h8/uclibc-ng.git] / extra / gcc-uClibc / gcc-uClibc.c
1
2 /*
3  * Copyright (C) 2000 Manuel Novoa III
4  *
5  * This is a crude wrapper to use uClibc with gcc.
6  * It was originally written to work around ./configure for ext2fs-utils.
7  * It certainly can be improved, but it works for me in the normal cases.
8  *
9  * April 7, 2001
10  *
11  * A bug was fixed in building the gcc command line when dynamic linking.
12  * The functions dlopen, etc. now work.  At this time, you must make sure
13  * the correct libdl.so is included however.  It is safest to, for example,
14  * add /lib/libdl.so.1 if using ld-linux.so.1 rather than adding -ldl to the
15  * command line.
16  *
17  * Note: This is only a problem if devel and target archs are the same.  To
18  * avoid the problem, you can use a customized dynamic linker.
19  *
20  *
21  * April 18, 2001
22  *
23  * The wrapper now works with either installed and uninstalled uClibc versions.
24  * If you want to use the uninstalled header files and libs, either include
25  * the string "build" in the invocation name such as
26  *       'ln -s <ARCH>-uclibc-gcc <ARCH>-uclibc-gcc-build'
27  * or include it in the environment variable setting of UCLIBC_GCC.
28  * Note: This automatically enables the "rpath" behavior described below.
29  *
30  * The wrapper will now pass the location of the uClibc shared libs used to
31  * the linker with the "-rpath" option if the invocation name includes the
32  * string "rpath" or if the environment variable UCLIBC_GCC include it (as
33  * with "build" above).  This is primarily intended to be used on devel
34  * platforms of the same arch as the target.  A good place to use this feature
35  * would be in the uClibc/test directory.
36  *
37  * The wrapper now displays the command line passed to gcc when '-v' is used.
38  *
39  * May 31, 2001
40  *
41  * "rpath" and "build" behavior are now decoupled.  You can of course get
42  * the old "build" behavior by setting UCLIBC_GCC="rpath-build".  Order
43  * isn't important here, as only the substrings are searched for.
44  *
45  * Added environment variable check for UCLIBC_GCC_DLOPT to let user specify
46  * an alternative dynamic linker at runtime without using command line args.
47  * Since this wouldn't commonly be used, I made it easy on myself.  You have
48  * to match the option you would have passed to the gcc wrapper.  As an
49  * example,
50  *
51  *   export UCLIBC_GCC_DLOPT="-Wl,--dynamic-linker,/lib/ld-alt-linker.so.3"
52  *
53  * This is really only useful if target arch == devel arch and DEVEL_PREFIX
54  * isn't empty.  It involves a recompile, but you can at least test apps
55  * on your devel system if combined with the "rpath" behavor if by using
56  * LD_LIBRARY_PATH, etc.
57  *
58  * Also added check for "-Wl,--dynamic-linker" on the command line.  The
59  * use default dynamic linker or the envirnment-specified dynamic linker
60  * is disabled in that case.
61  *
62  * Added options --uclibc-use-build-dir and --uclibc-use-rpath so that those
63  * behaviors can be invoked from the command line.
64  *
65  */
66
67 /*
68  *
69  * TODO:
70  * Check/modify gcc-specific environment variables?
71  */
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <unistd.h>
77
78 #include "gcc-uClibc.h"
79
80 static char *rpath_link[] = {
81         "-Wl,-rpath-link,"UCLIBC_DEVEL_PREFIX UCLIBC_ROOT_DIR"/lib",
82         "-Wl,-rpath-link,"UCLIBC_BUILD_DIR"/lib"
83 };
84
85 static char *rpath[] = {
86         "-Wl,-rpath,"UCLIBC_DEVEL_PREFIX UCLIBC_ROOT_DIR"/lib",
87         "-Wl,-rpath,"UCLIBC_BUILD_DIR"/lib"
88 };
89
90 static char *uClibc_inc[] = {
91         "-I"UCLIBC_DEVEL_PREFIX UCLIBC_ROOT_DIR"/usr/include/",
92         "-I"UCLIBC_BUILD_DIR"/include/"
93 };
94
95 static char *crt0_path[] = {
96         UCLIBC_DEVEL_PREFIX UCLIBC_ROOT_DIR"/usr/lib/crt0.o",
97         UCLIBC_BUILD_DIR"/lib/crt0.o"
98 };
99
100 static char *lib_path[] = {
101         "-L"UCLIBC_DEVEL_PREFIX UCLIBC_ROOT_DIR"/lib",
102         "-L"UCLIBC_BUILD_DIR"/lib"
103 };
104
105 static char *usr_lib_path = "-L"UCLIBC_DEVEL_PREFIX UCLIBC_ROOT_DIR"/usr/lib";
106
107 static char static_linking[] = "-static";
108 static char nostdinc[] = "-nostdinc";
109 static char nostartfiles[] = "-nostartfiles";
110 static char nodefaultlibs[] = "-nodefaultlibs";
111 static char nostdlib[] = "-nostdlib";
112
113 int main(int argc, char **argv)
114 {
115         int use_build_dir = 0, linking = 1, use_static_linking = 0;
116         int use_stdinc = 1, use_start = 1, use_stdlib = 1;
117         int source_count = 0, use_rpath = 0, verbose = 0;
118         int i, j;
119         char ** gcc_argv;
120         char *dlstr;
121         char *build_dlstr;
122         char *ep;
123
124         build_dlstr = "-Wl,--dynamic-linker," BUILD_DYNAMIC_LINKER;
125         dlstr = getenv("UCLIBC_GCC_DLOPT");
126         if (!dlstr) {
127                 dlstr = "-Wl,--dynamic-linker," DYNAMIC_LINKER;
128         }
129
130         ep = getenv("UCLIBC_GCC");
131         if (!ep) {
132                 ep = "";
133         }
134
135         if (strstr(ep,"build") != 0) {
136                 use_build_dir = 1;
137         }
138
139         if (strstr(ep,"rpath") != 0) {
140                 use_rpath = 1;
141         }
142
143         for ( i = 1 ; i < argc ; i++ ) {
144                 if (argv[i][0] == '-') { /* option */
145                         switch (argv[i][1]) {
146                                 case 'c':               /* compile or assemble */
147                                 case 'S':               /* generate assembler code */
148                                 case 'E':               /* preprocess only */
149                                 case 'r':               /* partial-link */
150                                 case 'i':               /* partial-link */
151                                 case 'M':       /* map file generation */
152                                         if (argv[i][2] == 0) linking = 0;
153                                         break;
154                                 case 'v':               /* verbose */
155                                         if (argv[i][2] == 0) verbose = 1;
156                                         break;
157                                 case 'n':
158                                         if (strcmp(nostdinc,argv[i]) == 0) {
159                                                 use_stdinc = 0;
160                                         } else if (strcmp(nostartfiles,argv[i]) == 0) {
161                                                 use_start = 0;
162                                         } else if (strcmp(nodefaultlibs,argv[i]) == 0) {
163                                                 use_stdlib = 0;
164                                         } else if (strcmp(nostdlib,argv[i]) == 0) {
165                                                 use_start = 0;
166                                                 use_stdlib = 0;
167                                         }
168                                         break;
169                                 case 's':
170                                         if (strcmp(static_linking,argv[i]) == 0) {
171                                                 use_static_linking = 1;
172                                         }
173                                         break;
174                             case 'W':           /* -static could be passed directly to ld */
175                                         if (strncmp("-Wl,",argv[i],4) == 0) {
176                                                 if (strstr(argv[i],static_linking) != 0) {
177                                                         use_static_linking = 1;
178                                                 }
179                                                 if (strstr(argv[i],"--dynamic-linker") != 0) {
180                                                         dlstr = 0;
181                                                 }
182                                         }
183                                         break;
184                                 case '-':
185                                         if (strcmp(static_linking,argv[i]+1) == 0) {
186                                                 use_static_linking = 1;
187                                         }
188                                         break;
189                         }
190                 } else {                                /* assume it is an existing source file */
191                         ++source_count;
192                 }
193         }
194
195 #if 1
196         gcc_argv = __builtin_alloca(sizeof(char*) * (argc + 20));
197 #else
198         if (!(gcc_argv = malloc(sizeof(char) * (argc + 20)))) {
199                 return EXIT_FAILURE;
200         }
201 #endif
202
203         i = 0;
204         gcc_argv[i++] = GCC_BIN;
205         for ( j = 1 ; j < argc ; j++ ) {
206                 if (strcmp("--uclibc-use-build-dir",argv[j]) == 0) {
207                         use_build_dir = 1;
208                 } else if (strcmp("--uclibc-use-rpath",argv[j]) == 0) {
209                         use_rpath = 1;
210                 } else {
211                         gcc_argv[i++] = argv[j];
212                 }
213         }
214         if (use_stdinc) {
215                 gcc_argv[i++] = nostdinc;
216                 gcc_argv[i++] = uClibc_inc[use_build_dir];
217                 gcc_argv[i++] = GCC_INCDIR;
218         }
219         if (linking && source_count) {
220                 if (!use_static_linking) {
221                         if (dlstr && use_build_dir) {
222                                 gcc_argv[i++] = build_dlstr;
223                         } else if (dlstr) {
224                                 gcc_argv[i++] = dlstr;
225                         }
226                         if (use_rpath) {
227                                 gcc_argv[i++] = rpath[use_build_dir];
228                         }
229                 }
230                 gcc_argv[i++] = rpath_link[use_build_dir]; /* just to be safe */
231                 gcc_argv[i++] = lib_path[use_build_dir];
232                 if (!use_build_dir) {
233                         gcc_argv[i++] = usr_lib_path;
234                 }
235                 if (use_start) {
236                         gcc_argv[i++] = crt0_path[use_build_dir];
237                 }
238                 if (use_stdlib) {
239                         gcc_argv[i++] = nostdlib;
240                         gcc_argv[i++] = "-lc";
241                         gcc_argv[i++] = GCC_LIB;
242                 }
243         }
244         gcc_argv[i++] = NULL;
245
246         if (verbose) {
247                 printf("Invoked as %s\n", argv[0]);
248                 for ( j = 0 ; gcc_argv[j] ; j++ ) {
249                         printf("arg[%2i] = %s\n", j, gcc_argv[j]);
250                 }
251         }
252
253         return execvp(GCC_BIN, gcc_argv);
254 }