Lines 94-99
Link Here
|
94 |
#define MAXPATHLEN 1023 |
94 |
#define MAXPATHLEN 1023 |
95 |
#endif |
95 |
#endif |
96 |
|
96 |
|
|
|
97 |
#ifndef FALSE |
98 |
#define FALSE 0 |
99 |
#endif |
100 |
#ifndef TRUE |
101 |
#define TRUE 1 |
102 |
#endif |
103 |
|
97 |
typedef struct { |
104 |
typedef struct { |
98 |
/* The CHOST being compiled for. This is determined by $ABI (deprecated), |
105 |
/* The CHOST being compiled for. This is determined by $ABI (deprecated), |
99 |
* the prefix of the executable, the environment ($CHOST), or the default |
106 |
* the prefix of the executable, the environment ($CHOST), or the default |
Lines 136-154
Link Here
|
136 |
"-m32", "-m64", "-mabi", NULL |
143 |
"-m32", "-m64", "-mabi", NULL |
137 |
}; |
144 |
}; |
138 |
|
145 |
|
139 |
retargv = argv; |
|
|
140 |
|
141 |
/* make sure user hasn't specified any ABI flags already ... |
146 |
/* make sure user hasn't specified any ABI flags already ... |
142 |
* if they have, lets just get out of here */ |
147 |
* if they have, lets just get out of here */ |
143 |
for (argc = 0; argv[argc]; ++argc) |
148 |
for (argc = 0; argv[argc]; ++argc) |
144 |
for (i = 0; abiFlags[i]; ++i) |
149 |
for (i = 0; abiFlags[i]; ++i) |
145 |
if (!strncmp(argv[argc], abiFlags[i], strlen(abiFlags[i]))) |
150 |
if (!strncmp(argv[argc], abiFlags[i], strlen(abiFlags[i]))) |
146 |
return retargv; |
151 |
return argv; |
147 |
|
152 |
|
148 |
/* Tokenize the flag list and put it into newflags array */ |
153 |
/* Tokenize the flag list and put it into newflags array */ |
149 |
flagsTokenized = strdup(newFlagsStr); |
154 |
flagsTokenized = strdup(newFlagsStr); |
150 |
if (flagsTokenized == NULL) |
155 |
if (flagsTokenized == NULL) |
151 |
return retargv; |
156 |
return argv; |
152 |
i = 0; |
157 |
i = 0; |
153 |
newFlags[i] = strtok_r(flagsTokenized, " \t\n", &state); |
158 |
newFlags[i] = strtok_r(flagsTokenized, " \t\n", &state); |
154 |
while (newFlags[i] != NULL && i < MAX_NEWFLAGS-1) |
159 |
while (newFlags[i] != NULL && i < MAX_NEWFLAGS-1) |
Lines 156-161
Link Here
|
156 |
|
161 |
|
157 |
/* allocate memory for our spiffy new argv */ |
162 |
/* allocate memory for our spiffy new argv */ |
158 |
retargv = (char**)calloc(argc + i + 1, sizeof(char*)); |
163 |
retargv = (char**)calloc(argc + i + 1, sizeof(char*)); |
|
|
164 |
if (retargv == NULL) { |
165 |
free(flagsTokenized); |
166 |
return argv; |
167 |
} |
159 |
/* start building retargv */ |
168 |
/* start building retargv */ |
160 |
retargv[0] = argv[0]; |
169 |
retargv[0] = argv[0]; |
161 |
/* insert the ABI flags first so cmdline always overrides ABI flags */ |
170 |
/* insert the ABI flags first so cmdline always overrides ABI flags */ |
Lines 164-172
Link Here
|
164 |
if (argc > 1) |
173 |
if (argc > 1) |
165 |
memcpy(retargv+1+i, argv+1, (argc-1) * sizeof(char*)); |
174 |
memcpy(retargv+1+i, argv+1, (argc-1) * sizeof(char*)); |
166 |
|
175 |
|
|
|
176 |
free(flagsTokenized); |
177 |
|
178 |
return retargv; |
179 |
} |
180 |
|
181 |
/** Prepend SPECS to the argv list */ |
182 |
static char **buildNewArgvSpecs(char **argv, const char *newSpecsStr) { |
183 |
#define MAX_NEWSPECS 32 |
184 |
char *newSpecs[MAX_NEWSPECS]; |
185 |
char **retargv; |
186 |
unsigned int argc; |
187 |
size_t nspecs; |
188 |
char *state, *flagsTokenized; |
189 |
char *spec; |
190 |
|
191 |
for (argc = 0; argv[argc]; ++argc); |
192 |
|
193 |
/* Tokenize the flag list and put it into newflags array */ |
194 |
flagsTokenized = strdup(newSpecsStr); |
195 |
if (flagsTokenized == NULL) |
196 |
return argv; |
197 |
nspecs = 0; |
198 |
for (spec = strtok_r(flagsTokenized, ":", &state); |
199 |
spec != NULL && nspecs < MAX_NEWSPECS; |
200 |
spec = strtok_r(NULL, ":", &state)) { |
201 |
newSpecs[nspecs] = (char *)malloc((strlen(spec)+8) * sizeof(char)); |
202 |
if (newSpecs[nspecs] == NULL) { |
203 |
free(flagsTokenized); |
204 |
return argv; |
205 |
} |
206 |
snprintf(newSpecs[nspecs], strlen(spec)+8, "-specs=%s", spec); |
207 |
nspecs++; |
208 |
} |
209 |
|
210 |
/* allocate memory for our spiffy new argv */ |
211 |
retargv = (char**)calloc(argc + nspecs + 1, sizeof(char*)); |
212 |
if (retargv == NULL) { |
213 |
free(flagsTokenized); |
214 |
return argv; |
215 |
} |
216 |
/* start building retargv */ |
217 |
retargv[0] = argv[0]; |
218 |
/* insert the ABI flags first so cmdline always overrides ABI flags */ |
219 |
memcpy(retargv+1, newSpecs, nspecs * sizeof(char*)); |
220 |
/* copy over the old argv */ |
221 |
if (argc > 1) |
222 |
memcpy(retargv+1+nspecs, argv+1, (argc-1) * sizeof(char*)); |
223 |
|
224 |
free(flagsTokenized); |
225 |
|
167 |
return retargv; |
226 |
return retargv; |
168 |
} |
227 |
} |
169 |
|
228 |
|
|
|
229 |
/** Add path to the environment variable envVar */ |
230 |
static int addPathToEnv(char *envVar, char *path) { |
231 |
char *envVal; |
232 |
char *newEnvVal; |
233 |
|
234 |
envVal = getenv(envVar); |
235 |
if (envVal == NULL) { |
236 |
newEnvVal=strdup(path); |
237 |
if (newEnvVal == NULL) |
238 |
return FALSE; |
239 |
} else { |
240 |
newEnvVal = (char *)malloc((strlen(envVal)+1+strlen(path)+1)*sizeof(char)); |
241 |
if (newEnvVal == NULL) |
242 |
return FALSE; |
243 |
snprintf(newEnvVal, strlen(envVal)+1+strlen(path)+1, "%s:%s", envVal,path); |
244 |
} |
245 |
setenv(envVar,newEnvVal,TRUE); |
246 |
return TRUE; |
247 |
} |
248 |
|
249 |
static char **prependArgv(char **argv, char *bin) { |
250 |
int argc; |
251 |
char **newArgv; |
252 |
for (argc=0; argv[argc]; argc++); |
253 |
newArgv = (char**)calloc(argc + 2, sizeof(char*)); |
254 |
if (newArgv == NULL) |
255 |
return argv; |
256 |
newArgv[0]=bin; |
257 |
memcpy(newArgv+1,argv,(argc + 1) * sizeof(char *)); |
258 |
return newArgv; |
259 |
} |
260 |
|
261 |
/** Return TRUE iff word is in COMPILER_FEATURES and -word is not (last wins) */ |
262 |
static int inFeatures(char *word) { |
263 |
char *features, *feature; |
264 |
char *state, *featuresTokenised; |
265 |
int on; |
266 |
|
267 |
features = getenv("COMPILER_FEATURES"); |
268 |
if (features==NULL) |
269 |
return FALSE; |
270 |
featuresTokenised = strdup(features); |
271 |
if (featuresTokenised == NULL) |
272 |
return FALSE; |
273 |
on = FALSE; |
274 |
for (feature = strtok_r(featuresTokenised, " \t\n", &state); |
275 |
feature != NULL; |
276 |
feature = strtok_r(NULL, " \t\n", &state)) { |
277 |
if (strcmp(feature,word)==0) { |
278 |
on = TRUE; |
279 |
} else if (word[0]=='-' && strcmp(feature,word+1)==0) { |
280 |
on = FALSE; |
281 |
} |
282 |
} |
283 |
return on; |
284 |
} |
285 |
|
286 |
/** Return TRUE iff distcc is wanted */ |
287 |
static int distccRequired(void) { |
288 |
return inFeatures("distcc"); |
289 |
} |
290 |
|
291 |
/** Return TRUE iff distcc is wanted */ |
292 |
static int ccacheRequired(void) { |
293 |
return inFeatures("ccache"); |
294 |
} |
295 |
|
296 |
/** Set environment variable envVar to environment variable envDir |
297 |
* suffixed with , provided envVar is empty or not defined. |
298 |
* Returns TRUE if the envVar is already set, or if it is |
299 |
* successfully set. */ |
300 |
static int appendEnv(char *envVar, char *envDir, char *suffix) { |
301 |
char *envVarVal; |
302 |
char *envDirVal; |
303 |
envVarVal = getenv (envVar); |
304 |
if (envVarVal == NULL || strlen(envVarVal)==0) { |
305 |
if (envDir == NULL) { |
306 |
setenv(envVar,suffix,TRUE); |
307 |
} else { |
308 |
envDirVal = getenv(envDir); |
309 |
if (envDirVal == NULL) |
310 |
return FALSE; |
311 |
envVarVal = (char *)malloc((strlen(envDirVal)+strlen(suffix)+1)*sizeof(char)); |
312 |
if (envVarVal == NULL) |
313 |
return FALSE; |
314 |
if (snprintf(envVarVal, strlen(envDirVal)+strlen(suffix)+1,"%s%s",envDirVal,suffix) < 0) |
315 |
return FALSE; |
316 |
setenv(envVar,envVarVal,TRUE); |
317 |
} |
318 |
} |
319 |
return TRUE; |
320 |
} |
321 |
|
170 |
/** Set the ctarget and profile */ |
322 |
/** Set the ctarget and profile */ |
171 |
static void setCtargetAndProfile(WrapperData *data) { |
323 |
static void setCtargetAndProfile(WrapperData *data) { |
172 |
char tmp[MAXPATHLEN + 1]; |
324 |
char tmp[MAXPATHLEN + 1]; |
Lines 265-293
Link Here
|
265 |
} |
417 |
} |
266 |
|
418 |
|
267 |
int main(int argc, char *argv[]) { |
419 |
int main(int argc, char *argv[]) { |
268 |
WrapperData *data; |
420 |
WrapperData data; |
269 |
char *extraCflags = NULL; |
421 |
char *extraCflags = NULL; |
|
|
422 |
char *gcc_specs; |
270 |
|
423 |
|
271 |
data = (WrapperData *)alloca(sizeof(WrapperData)); |
|
|
272 |
if(data == NULL) |
273 |
die("Memory allocation failure."); |
274 |
|
275 |
/* Load the config file */ |
424 |
/* Load the config file */ |
276 |
data->selectionConf = loadSelectionConf(CONFIGURATION_DIR, 1); |
425 |
data.selectionConf = loadSelectionConf(CONFIGURATION_DIR, 1); |
277 |
if(data->selectionConf == NULL) |
426 |
if(data.selectionConf == NULL) |
278 |
die("Memory allocation failure."); |
427 |
die("Memory allocation failure."); |
279 |
|
428 |
|
280 |
/* The argv to pass to the forked process. Defaults to be the same */ |
429 |
/* The argv to pass to the forked process. Defaults to be the same */ |
281 |
data->argv = argv; |
430 |
data.argv = argv; |
282 |
|
431 |
|
283 |
/* Figure out out CTARGET and our Profile */ |
432 |
/* Figure out out CTARGET and our Profile */ |
284 |
setCtargetAndProfile(data); |
433 |
setCtargetAndProfile(&data); |
285 |
|
434 |
|
286 |
/* Determine what binary we will be executing */ |
435 |
/* Determine what binary we will be executing */ |
287 |
setExecBinary(data); |
436 |
setExecBinary(&data); |
288 |
|
437 |
|
289 |
/* Do we need to set any additional CFLAGS? */ |
438 |
/* Do we need to set any additional CFLAGS? */ |
290 |
if(data->selectionConf->useABI && getenv("ABI")) { |
439 |
if(data.selectionConf->useABI && getenv("ABI")) { |
291 |
/* This functionality is deprecated and subject to be removed |
440 |
/* This functionality is deprecated and subject to be removed |
292 |
* once all profiles in portage nolonger depend on it. |
441 |
* once all profiles in portage nolonger depend on it. |
293 |
*/ |
442 |
*/ |
Lines 297-325
Link Here
|
297 |
if (getenv(envvar)) |
446 |
if (getenv(envvar)) |
298 |
extraCflags = getenv(envvar); |
447 |
extraCflags = getenv(envvar); |
299 |
} else { |
448 |
} else { |
300 |
extraCflags = ((Profile *)hashGet(data->selectionConf->selectionHash, data->ctarget))->cflags; |
449 |
extraCflags = ((Profile *)hashGet(data.selectionConf->selectionHash, data.ctarget))->cflags; |
301 |
} |
450 |
} |
302 |
|
451 |
|
303 |
if(extraCflags) { |
452 |
if(extraCflags) { |
304 |
data->argv = buildNewArgv(data->argv, extraCflags); |
453 |
data.argv = buildNewArgv(data.argv, extraCflags); |
305 |
if(data->argv == NULL) |
454 |
if(data.argv == NULL) |
306 |
die("Memory allocation failure."); |
455 |
die("Memory allocation failure."); |
307 |
} |
456 |
} |
308 |
|
457 |
|
309 |
/* Select the appropriate GCC specs file */ |
458 |
/* Convert env specs or config specs into arguments |
310 |
if(data->profile->specs && getenv("GCC_SPECS") == NULL) |
459 |
* Env GCC_SPECS is honoured for native compiler only |
311 |
setenv("GCC_SPECS", data->profile->specs, 1); |
460 |
*/ |
|
|
461 |
gcc_specs = getenv("GCC_SPECS"); |
462 |
if (gcc_specs && |
463 |
strcmp(data.ctarget, data.selectionConf->defaultCtarget) == 0) { |
464 |
data.argv = buildNewArgvSpecs(data.argv, gcc_specs); |
465 |
} else if (data.profile->specs) { |
466 |
data.argv = buildNewArgvSpecs(data.argv, data.profile->specs); |
467 |
} |
468 |
unsetenv("GCC_SPECS"); |
312 |
|
469 |
|
313 |
/* Set argv[0] to the correct binary (the full path |
470 |
/* Set argv[0] to the correct binary (the full path |
314 |
* of the binary we are executing), else gcc can't |
471 |
* of the binary we are executing), else gcc can't |
315 |
* find internal headers |
472 |
* find internal headers |
316 |
* http://bugs.gentoo.org/show_bug.cgi?id=8132 |
473 |
* http://bugs.gentoo.org/show_bug.cgi?id=8132 |
317 |
*/ |
474 |
*/ |
318 |
data->argv[0] = data->execBinary; |
475 |
data.argv[0] = data.execBinary; |
|
|
476 |
|
477 |
/* Prepend distcc, if enabled. |
478 |
* Set DISTCC_DIR to PORTAGE_TMPDIR/.distcc if not already set |
479 |
* Append DISTCC_DIR to SANDBOX_WRITE |
480 |
* Shuffle argv and set argv[0] to /usr/bin/distcc |
481 |
*/ |
482 |
if (distccRequired() && |
483 |
appendEnv("DISTCC_DIR", "PORTAGE_TMPDIR", "/.distcc") && |
484 |
addPathToEnv("SANDBOX_WRITE",getenv("DISTCC_DIR"))) { |
485 |
data.argv = prependArgv(data.argv, "/usr/bin/distcc"); |
486 |
} |
487 |
|
488 |
/* Prepend ccache, if enabled. |
489 |
* Set CCACHE_DIR to /var/tmp/ccache if not already set |
490 |
* Append CCACHE_DIR to SANDBOX_WRITE, SANDBOX_READ |
491 |
* Shuffle argv and set argv[0] to /usr/bin/ccache |
492 |
*/ |
493 |
if (ccacheRequired() && |
494 |
appendEnv("CCACHE_DIR", NULL, "/var/tmp/ccache") && |
495 |
addPathToEnv("SANDBOX_READ",getenv("CCACHE_DIR")) && |
496 |
addPathToEnv("SANDBOX_WRITE",getenv("CCACHE_DIR"))) { |
497 |
data.argv = prependArgv(data.argv, "/usr/bin/ccache"); |
498 |
} |
319 |
|
499 |
|
320 |
/* Ok, lets exec it. */ |
500 |
/* Ok, lets exec it. */ |
321 |
if (execv(data->execBinary, data->argv) < 0) |
501 |
if (execv(data.argv[0], data.argv) < 0) |
322 |
die("Could not run/locate \"%s\"", data->execBinary); |
502 |
die("Could not run/locate \"%s\"", data.argv[0]); |
323 |
|
503 |
|
324 |
return 0; |
504 |
return 0; |
325 |
} |
505 |
} |