Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 128810 | Differences between
and this patch

Collapse All | Expand All

(-)compiler-wrapper.c (-24 / +205 lines)
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
167
	return retargv;
178
	return retargv;
168
}
179
}
169
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
226
	return retargv;
227
}
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
/** Put bin as argv[0], shuffling argv up one place */
250
static char **prependArgv(char **argv, char *bin) {
251
	int argc;
252
	char **newArgv;
253
	for (argc=0; argv[argc]; argc++);
254
	newArgv = (char**)calloc(argc + 1, sizeof(char*));
255
	if (newArgv == NULL)
256
		return argv;
257
	newArgv[0]=bin;
258
	memcpy(newArgv+1,argv,argc * sizeof(char *));
259
	return newArgv;
260
}
261
262
/** Return TRUE iff word is in COMPILER_FEATURES and -word is not (last wins) */
263
static int inFeatures(char *word) {
264
	char *features, *feature;
265
	char *state, *featuresTokenised;
266
	int on;
267
268
	features = getenv("COMPILER_FEATURES");
269
	if (features==NULL)
270
		return FALSE;
271
	featuresTokenised = strdup(features);
272
	if (featuresTokenised == NULL)
273
		return FALSE;
274
	on = FALSE;
275
	for (feature = strtok_r(featuresTokenised, " \t\n", &state);
276
		 feature != NULL;
277
		 feature = strtok_r(NULL, " \t\n", &state)) {
278
		if (strcmp(feature,word)==0) {
279
			on = TRUE;
280
		} else if (word[0]=='-' && strcmp(feature,word+1)==0) {
281
			on = FALSE;
282
		}
283
	}
284
	return on;
285
}
286
287
/** Return TRUE iff distcc is wanted */
288
static int distccRequired(void) {
289
	return inFeatures("distcc");
290
}
291
292
/** Return TRUE iff distcc is wanted */
293
static int ccacheRequired(void) {
294
	return inFeatures("ccache");
295
}
296
297
/** Set environment variable envVar to environment variable envDir
298
 * suffixed with , provided envVar is empty or not defined.
299
 * Returns TRUE if the envVar is already set, or if it is
300
 * successfully set. */
301
static int appendEnv(char *envVar, char *envDir, char *suffix) {
302
	char *envVarVal;
303
	char *envDirVal;
304
	envVarVal = getenv (envVar);
305
	if (envVarVal == NULL || strlen(envVarVal)==0) {
306
		if (envDir == NULL) {
307
			setenv(envVar,suffix,TRUE);
308
		} else {
309
			envDirVal = getenv(envDir);
310
			if (envDirVal == NULL)
311
				return FALSE;
312
			envVarVal = (char *)malloc((strlen(envDirVal)+strlen(suffix)+1)*sizeof(char));
313
			if (envVarVal == NULL)
314
				return FALSE;
315
			if (snprintf(envVarVal, strlen(envDirVal)+strlen(suffix)+1,"%s%s",envDirVal,suffix) < 0)
316
				return FALSE;
317
			setenv(envVar,envVarVal,TRUE);
318
		}
319
	}
320
	return TRUE;
321
}
322
170
/** Set the ctarget and profile */
323
/** Set the ctarget and profile */
171
static void setCtargetAndProfile(WrapperData *data) {
324
static void setCtargetAndProfile(WrapperData *data) {
172
	char tmp[MAXPATHLEN + 1];
325
	char tmp[MAXPATHLEN + 1];
Lines 265-293 Link Here
265
}
418
}
266
419
267
int main(int argc, char *argv[]) {
420
int main(int argc, char *argv[]) {
268
	WrapperData *data;
421
	WrapperData data;
269
	char *extraCflags = NULL;
422
	char *extraCflags = NULL;
270
	
423
	char *gcc_specs;
271
	data = (WrapperData *)alloca(sizeof(WrapperData));
272
	if(data == NULL)
273
		die("Memory allocation failure.");
274
424
275
	/* Load the config file */
425
	/* Load the config file */
276
	data->selectionConf = loadSelectionConf(CONFIGURATION_DIR, 1);
426
	data.selectionConf = loadSelectionConf(CONFIGURATION_DIR, 1);
277
	if(data->selectionConf == NULL)
427
	if(data.selectionConf == NULL)
278
		die("Memory allocation failure.");
428
		die("Memory allocation failure.");
279
429
280
	/* The argv to pass to the forked process.  Defaults to be the same */
430
	/* The argv to pass to the forked process.  Defaults to be the same */
281
	data->argv = argv;
431
	data.argv = argv;
282
432
283
	/* Figure out out CTARGET and our Profile */
433
	/* Figure out out CTARGET and our Profile */
284
	setCtargetAndProfile(data);
434
	setCtargetAndProfile(&data);
285
435
286
	/* Determine what binary we will be executing */
436
	/* Determine what binary we will be executing */
287
	setExecBinary(data);
437
	setExecBinary(&data);
288
438
289
	/* Do we need to set any additional CFLAGS? */
439
	/* Do we need to set any additional CFLAGS? */
290
	if(data->selectionConf->useABI && getenv("ABI")) {
440
	if(data.selectionConf->useABI && getenv("ABI")) {
291
		/* This functionality is deprecated and subject to be removed
441
		/* This functionality is deprecated and subject to be removed
292
		 * once all profiles in portage nolonger depend on it.
442
		 * once all profiles in portage nolonger depend on it.
293
		 */
443
		 */
Lines 297-325 Link Here
297
		if (getenv(envvar))
447
		if (getenv(envvar))
298
			extraCflags = getenv(envvar);
448
			extraCflags = getenv(envvar);
299
	} else {
449
	} else {
300
		extraCflags = ((Profile *)hashGet(data->selectionConf->selectionHash, data->ctarget))->cflags;
450
		extraCflags = ((Profile *)hashGet(data.selectionConf->selectionHash, data.ctarget))->cflags;
301
	}
451
	}
302
452
303
	if(extraCflags) {
453
	if(extraCflags) {
304
		data->argv = buildNewArgv(data->argv, extraCflags);
454
		data.argv = buildNewArgv(data.argv, extraCflags);
305
		if(data->argv == NULL)
455
		if(data.argv == NULL)
306
			die("Memory allocation failure.");
456
			die("Memory allocation failure.");
307
	}
457
	}
308
458
309
	/* Select the appropriate GCC specs file */
459
	/* Convert env specs or config specs into arguments
310
	if(data->profile->specs && getenv("GCC_SPECS") == NULL)
460
	 * Env GCC_SPECS is honoured for native compiler only
311
		setenv("GCC_SPECS", data->profile->specs, 1);
461
	 */
462
	gcc_specs = getenv("GCC_SPECS");
463
	if (gcc_specs &&
464
		strcmp(data.ctarget, data.selectionConf->defaultCtarget) == 0) {
465
		data.argv = buildNewArgvSpecs(data.argv, gcc_specs);
466
	} else if (data.profile->specs) {
467
		data.argv = buildNewArgvSpecs(data.argv, data.profile->specs);
468
	}
469
	unsetenv("GCC_SPECS");
312
470
313
	/* Set argv[0] to the correct binary (the full path
471
	/* Set argv[0] to the correct binary (the full path
314
	 * of the binary we are executing), else gcc can't
472
	 * of the binary we are executing), else gcc can't
315
	 * find internal headers
473
	 * find internal headers
316
	 * http://bugs.gentoo.org/show_bug.cgi?id=8132
474
	 * http://bugs.gentoo.org/show_bug.cgi?id=8132
317
	 */
475
	 */
318
	data->argv[0] = data->execBinary;
476
	data.argv[0] = data.execBinary;
477
478
	/* Prepend distcc, if enabled.
479
	 * Set DISTCC_DIR to PORTAGE_TMPDIR/.distcc if not already set
480
	 * Append DISTCC_DIR to SANDBOX_WRITE
481
	 * Shuffle argv and set argv[0] to /usr/bin/distcc
482
	 */
483
	if (distccRequired() &&
484
		appendEnv("DISTCC_DIR", "PORTAGE_TMPDIR", "/.distcc") &&
485
		addPathToEnv("SANDBOX_WRITE",getenv("DISTCC_DIR"))) {
486
		data.argv = prependArgv(data.argv, "/usr/bin/distcc");
487
	}
488
489
	/* Prepend ccache, if enabled.
490
	 * Set CCACHE_DIR to /var/tmp/ccache if not already set
491
	 * Append CCACHE_DIR to SANDBOX_WRITE, SANDBOX_READ
492
	 * Shuffle argv and set argv[0] to /usr/bin/ccache
493
	 */
494
	if (ccacheRequired() &&
495
		appendEnv("CCACHE_DIR", NULL, "/var/tmp/ccache") &&
496
		addPathToEnv("SANDBOX_READ",getenv("CCACHE_DIR")) &&
497
		addPathToEnv("SANDBOX_WRITE",getenv("CCACHE_DIR"))) {
498
		data.argv = prependArgv(data.argv, "/usr/bin/ccache");
499
	}
319
500
320
	/* Ok, lets exec it. */
501
	/* Ok, lets exec it. */
321
	if (execv(data->execBinary, data->argv) < 0)
502
	if (execv(data.argv[0], data.argv) < 0)
322
		die("Could not run/locate \"%s\"", data->execBinary);
503
		die("Could not run/locate \"%s\"", data.argv[0]);
323
504
324
	return 0;
505
	return 0;
325
}
506
}

Return to bug 128810