| 1 |
/* APPLE LOCAL file driver driver */
|
| 2 |
|
| 3 |
/* Darwin driver program that handles -arch commands and invokes
|
| 4 |
appropriate compiler driver.
|
| 5 |
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
| 6 |
|
| 7 |
This file is part of GCC.
|
| 8 |
|
| 9 |
GCC is free software; you can redistribute it and/or modify it under
|
| 10 |
the terms of the GNU General Public License as published by the Free
|
| 11 |
Software Foundation; either version 2, or (at your option) any later
|
| 12 |
version.
|
| 13 |
|
| 14 |
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
| 15 |
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| 16 |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
| 17 |
for more details.
|
| 18 |
|
| 19 |
You should have received a copy of the GNU General Public License
|
| 20 |
along with GCC; see the file COPYING. If not, write to the Free
|
| 21 |
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
| 22 |
02111-1307, USA. */
|
| 23 |
|
| 24 |
|
| 25 |
#include <stdio.h>
|
| 26 |
#include <stdlib.h>
|
| 27 |
#include <string.h>
|
| 28 |
#include <unistd.h>
|
| 29 |
#include <errno.h>
|
| 30 |
#include <mach-o/arch.h>
|
| 31 |
#include <limits.h>
|
| 32 |
#include <sys/types.h>
|
| 33 |
#include <sys/stat.h>
|
| 34 |
#include <sys/wait.h>
|
| 35 |
#include <regex.h>
|
| 36 |
#include "libiberty.h"
|
| 37 |
#include "filenames.h"
|
| 38 |
#include "stdbool.h"
|
| 39 |
/* Hack!.
|
| 40 |
Pay the price for including darwin.h. */
|
| 41 |
typedef int tree;
|
| 42 |
typedef int rtx;
|
| 43 |
#define GTY(x) /* nothing */
|
| 44 |
#define USED_FOR_TARGET 1
|
| 45 |
/* Include darwin.h for SWITCH_TAKES_ARG and
|
| 46 |
WORD_SWIATCH_TAKES_ARG. */
|
| 47 |
|
| 48 |
#include "darwin.h"
|
| 49 |
|
| 50 |
/* Include gcc.h for DEFAULT_SWITCH_TAKES_ARG and
|
| 51 |
DEFAULT_WORD_SWIATCH_TAKES_ARG. */
|
| 52 |
|
| 53 |
#include "gcc.h"
|
| 54 |
|
| 55 |
/* This program name. */
|
| 56 |
const char *progname;
|
| 57 |
|
| 58 |
/* driver prefix. */
|
| 59 |
const char *driver_exec_prefix;
|
| 60 |
|
| 61 |
/* driver prefix length. */
|
| 62 |
int prefix_len;
|
| 63 |
|
| 64 |
/* current working directory. */
|
| 65 |
char *curr_dir;
|
| 66 |
|
| 67 |
/* Use if -o flag is absent. */
|
| 68 |
const char *final_output = "a.out";
|
| 69 |
|
| 70 |
/* Variabless to track presence and/or absence of important command
|
| 71 |
line options. */
|
| 72 |
int compile_only_request = 0;
|
| 73 |
int asm_output_request = 0;
|
| 74 |
int dash_capital_m_seen = 0;
|
| 75 |
int preprocessed_output_request = 0;
|
| 76 |
int ima_is_used = 0;
|
| 77 |
int dash_dynamiclib_seen = 0;
|
| 78 |
int verbose_flag = 0;
|
| 79 |
int save_temps_seen = 0;
|
| 80 |
int dash_m32_seen = 0;
|
| 81 |
int dash_m64_seen = 0;
|
| 82 |
|
| 83 |
/* Support at the max 10 arch. at a time. This is historical limit. */
|
| 84 |
#define MAX_ARCHES 10
|
| 85 |
|
| 86 |
/* Name of user supplied architectures. */
|
| 87 |
const char *arches[MAX_ARCHES];
|
| 88 |
|
| 89 |
/* -arch counter. */
|
| 90 |
static int num_arches;
|
| 91 |
|
| 92 |
/* Input filenames. */
|
| 93 |
struct input_filename
|
| 94 |
{
|
| 95 |
const char *name;
|
| 96 |
int index;
|
| 97 |
struct input_filename *next;
|
| 98 |
};
|
| 99 |
struct input_filename *in_files;
|
| 100 |
struct input_filename *last_infile;
|
| 101 |
|
| 102 |
static int num_infiles;
|
| 103 |
|
| 104 |
/* User specified output file name. */
|
| 105 |
const char *output_filename = NULL;
|
| 106 |
|
| 107 |
/* Output file names used for arch specific driver invocation. These
|
| 108 |
are input file names for 'lipo'. */
|
| 109 |
const char **out_files;
|
| 110 |
static int num_outfiles;
|
| 111 |
|
| 112 |
/* Architecture names used by config.guess does not match the names
|
| 113 |
used by NXGet... Use this hand coded mapping to connect them. */
|
| 114 |
struct arch_config_guess_map
|
| 115 |
{
|
| 116 |
const char *arch_name;
|
| 117 |
const char *config_string;
|
| 118 |
};
|
| 119 |
|
| 120 |
struct arch_config_guess_map arch_config_map [] =
|
| 121 |
{
|
| 122 |
{"i386", "i686"},
|
| 123 |
{"ppc", "powerpc"},
|
| 124 |
{"ppc64", "powerpc"},
|
| 125 |
{"x86_64", "i686"},
|
| 126 |
{"arm", "arm"},
|
| 127 |
{"armv4t", "arm"},
|
| 128 |
{"armv5", "arm"},
|
| 129 |
{"xscale", "arm"},
|
| 130 |
{"armv6", "arm"},
|
| 131 |
{"armv7", "arm"},
|
| 132 |
{NULL, NULL}
|
| 133 |
};
|
| 134 |
|
| 135 |
/* List of interpreted command line flags. Supply this to gcc driver. */
|
| 136 |
const char **new_argv;
|
| 137 |
int new_argc;
|
| 138 |
|
| 139 |
/* For each of the options in new_argv, specifies an architecture to
|
| 140 |
which the option applies (or if NULL, the option applies to all). */
|
| 141 |
const char **arch_conditional;
|
| 142 |
|
| 143 |
/* Argument list for 'lipo'. */
|
| 144 |
const char **lipo_argv;
|
| 145 |
|
| 146 |
/* Info about the sub process. Need one subprocess for each arch plus
|
| 147 |
additional one for 'lipo'. */
|
| 148 |
struct command
|
| 149 |
{
|
| 150 |
const char *prog;
|
| 151 |
const char **argv;
|
| 152 |
int pid;
|
| 153 |
} commands[MAX_ARCHES+1];
|
| 154 |
|
| 155 |
/* total number of argc. */
|
| 156 |
static int total_argc;
|
| 157 |
|
| 158 |
static int greatest_status = 0;
|
| 159 |
static int signal_count = 0;
|
| 160 |
|
| 161 |
#ifndef SWITCH_TAKES_ARG
|
| 162 |
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
|
| 163 |
#endif
|
| 164 |
|
| 165 |
#ifndef WORD_SWITCH_TAKES_ARG
|
| 166 |
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
|
| 167 |
#endif
|
| 168 |
|
| 169 |
|
| 170 |
/* Local function prototypes. */
|
| 171 |
static const char * get_arch_name (const char *);
|
| 172 |
static char * get_driver_name (const char *);
|
| 173 |
static void delete_out_files (void);
|
| 174 |
static char * strip_path_and_suffix (const char *, const char *);
|
| 175 |
static void initialize (void);
|
| 176 |
static void final_cleanup (void);
|
| 177 |
static int do_wait (int, const char *);
|
| 178 |
static void do_lipo (int, const char *);
|
| 179 |
static void do_compile (const char **, int);
|
| 180 |
static void do_compile_separately (void);
|
| 181 |
static void do_lipo_separately (void);
|
| 182 |
static int filter_args_for_arch (const char **, int, const char **,
|
| 183 |
const char *);
|
| 184 |
static int add_arch_options (int, const char **, int);
|
| 185 |
static int remove_arch_options (const char**, int);
|
| 186 |
static void add_arch (const char *);
|
| 187 |
static const char *resolve_symlink (const char *, char *, int, int);
|
| 188 |
static const char *resolve_path_to_executable (const char *filename);
|
| 189 |
static int get_prog_name_len (const char *prog);
|
| 190 |
|
| 191 |
/* Find arch name for the given input string. If input name is NULL then local
|
| 192 |
arch name is used. */
|
| 193 |
|
| 194 |
static const char *
|
| 195 |
get_arch_name (const char *name)
|
| 196 |
{
|
| 197 |
NXArchInfo * a_info;
|
| 198 |
const NXArchInfo * all_info;
|
| 199 |
cpu_type_t cputype;
|
| 200 |
struct arch_config_guess_map *map;
|
| 201 |
const char *aname;
|
| 202 |
|
| 203 |
if (name) {
|
| 204 |
/* Find config name based on arch name. */
|
| 205 |
aname = NULL;
|
| 206 |
map = arch_config_map;
|
| 207 |
while (map->arch_name) {
|
| 208 |
if (!strcmp (map->arch_name, name))
|
| 209 |
return name;
|
| 210 |
else map++;
|
| 211 |
}
|
| 212 |
a_info = (NXArchInfo *) NXGetArchInfoFromName (name);
|
| 213 |
} else {
|
| 214 |
a_info = (NXArchInfo *) NXGetLocalArchInfo();
|
| 215 |
if (a_info) {
|
| 216 |
if (dash_m32_seen) {
|
| 217 |
/* If -m32 is seen then do not change cpu type. */
|
| 218 |
} else if (dash_m64_seen) {
|
| 219 |
/* If -m64 is seen then enable CPU_ARCH_ABI64. */
|
| 220 |
a_info->cputype |= CPU_ARCH_ABI64;
|
| 221 |
} else if (sizeof (long) == 8)
|
| 222 |
/* On x86, by default (name is NULL here) enable 64 bit code. */
|
| 223 |
a_info->cputype |= CPU_ARCH_ABI64;
|
| 224 |
}
|
| 225 |
}
|
| 226 |
|
| 227 |
if (!a_info)
|
| 228 |
fatal ("Invalid arch name : %s", name);
|
| 229 |
|
| 230 |
all_info = NXGetAllArchInfos();
|
| 231 |
|
| 232 |
if (!all_info)
|
| 233 |
fatal ("Unable to get architecture information");
|
| 234 |
|
| 235 |
/* Find first arch. that matches cputype. */
|
| 236 |
cputype = a_info->cputype;
|
| 237 |
|
| 238 |
while (all_info->name)
|
| 239 |
{
|
| 240 |
if (all_info->cputype == cputype)
|
| 241 |
break;
|
| 242 |
else
|
| 243 |
all_info++;
|
| 244 |
}
|
| 245 |
|
| 246 |
return all_info->name;
|
| 247 |
}
|
| 248 |
|
| 249 |
/* Find driver name based on input arch name. */
|
| 250 |
|
| 251 |
static char *
|
| 252 |
get_driver_name (const char *arch_name)
|
| 253 |
{
|
| 254 |
char *driver_name;
|
| 255 |
const char *config_name;
|
| 256 |
int len;
|
| 257 |
int index;
|
| 258 |
struct arch_config_guess_map *map;
|
| 259 |
|
| 260 |
/* find config name based on arch name. */
|
| 261 |
config_name = NULL;
|
| 262 |
map = arch_config_map;
|
| 263 |
while (map->arch_name)
|
| 264 |
{
|
| 265 |
if (!strcmp (map->arch_name, arch_name))
|
| 266 |
{
|
| 267 |
config_name = map->config_string;
|
| 268 |
break;
|
| 269 |
}
|
| 270 |
else map++;
|
| 271 |
}
|
| 272 |
|
| 273 |
if (!config_name)
|
| 274 |
fatal ("Unable to guess config name for arch %s", arch_name);
|
| 275 |
|
| 276 |
len = strlen (config_name) + strlen (PDN) + prefix_len + 1;
|
| 277 |
driver_name = (char *) malloc (sizeof (char) * len);
|
| 278 |
driver_name[0] = '\0';
|
| 279 |
|
| 280 |
if (driver_exec_prefix)
|
| 281 |
strcpy (driver_name, driver_exec_prefix);
|
| 282 |
strcat (driver_name, config_name);
|
| 283 |
strcat (driver_name, PDN);
|
| 284 |
|
| 285 |
return driver_name;
|
| 286 |
}
|
| 287 |
|
| 288 |
/* Delete out_files. */
|
| 289 |
|
| 290 |
static void
|
| 291 |
delete_out_files (void)
|
| 292 |
{
|
| 293 |
const char *temp;
|
| 294 |
struct stat st;
|
| 295 |
int i = 0;
|
| 296 |
|
| 297 |
for (i = 0, temp = out_files[i];
|
| 298 |
temp && i < total_argc * MAX_ARCHES;
|
| 299 |
temp = out_files[++i])
|
| 300 |
if (stat (temp, &st) >= 0 && S_ISREG (st.st_mode))
|
| 301 |
unlink (temp);
|
| 302 |
|
| 303 |
}
|
| 304 |
|
| 305 |
/* Put fatal error message on stderr and exit. */
|
| 306 |
|
| 307 |
void
|
| 308 |
fatal (const char *msgid, ...)
|
| 309 |
{
|
| 310 |
va_list ap;
|
| 311 |
|
| 312 |
va_start (ap, msgid);
|
| 313 |
|
| 314 |
fprintf (stderr, "%s: ", progname);
|
| 315 |
vfprintf (stderr, msgid, ap);
|
| 316 |
va_end (ap);
|
| 317 |
fprintf (stderr, "\n");
|
| 318 |
delete_out_files ();
|
| 319 |
exit (1);
|
| 320 |
}
|
| 321 |
|
| 322 |
/* Print error message and exit. */
|
| 323 |
|
| 324 |
static void
|
| 325 |
pfatal_pexecute (const char *errmsg_fmt, const char *errmsg_arg)
|
| 326 |
{
|
| 327 |
if (errmsg_arg)
|
| 328 |
{
|
| 329 |
int save_errno = errno;
|
| 330 |
|
| 331 |
/* Space for trailing '\0' is in %s. */
|
| 332 |
char *msg = (char *) malloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
|
| 333 |
sprintf (msg, errmsg_fmt, errmsg_arg);
|
| 334 |
errmsg_fmt = msg;
|
| 335 |
|
| 336 |
errno = save_errno;
|
| 337 |
}
|
| 338 |
|
| 339 |
fprintf (stderr,"%s: %s: %s\n", progname, errmsg_fmt, xstrerror (errno));
|
| 340 |
delete_out_files ();
|
| 341 |
exit (1);
|
| 342 |
}
|
| 343 |
|
| 344 |
#ifdef DEBUG
|
| 345 |
static void
|
| 346 |
debug_command_line (const char **debug_argv, int debug_argc)
|
| 347 |
{
|
| 348 |
int i;
|
| 349 |
|
| 350 |
fprintf (stderr,"%s: debug_command_line\n", progname);
|
| 351 |
fprintf (stderr,"%s: arg count = %d\n", progname, debug_argc);
|
| 352 |
|
| 353 |
for (i = 0; debug_argv[i]; i++)
|
| 354 |
fprintf (stderr,"%s: arg [%d] %s\n", progname, i, debug_argv[i]);
|
| 355 |
}
|
| 356 |
#endif
|
| 357 |
|
| 358 |
/* Strip directory name from the input file name and replace file name
|
| 359 |
suffix with new. */
|
| 360 |
|
| 361 |
static char *
|
| 362 |
strip_path_and_suffix (const char *full_name, const char *new_suffix)
|
| 363 |
{
|
| 364 |
char *name;
|
| 365 |
char *p;
|
| 366 |
|
| 367 |
if (!full_name || !new_suffix)
|
| 368 |
return NULL;
|
| 369 |
|
| 370 |
/* Strip path name. */
|
| 371 |
p = (char *)full_name + strlen (full_name);
|
| 372 |
while (p != full_name && !IS_DIR_SEPARATOR (p[-1]))
|
| 373 |
--p;
|
| 374 |
|
| 375 |
/* Now 'p' is a file name with suffix. */
|
| 376 |
name = (char *) malloc (strlen (p) + 1 + strlen (new_suffix));
|
| 377 |
|
| 378 |
strcpy (name, p);
|
| 379 |
|
| 380 |
p = name + strlen (name);
|
| 381 |
while (p != name && *p != '.')
|
| 382 |
--p;
|
| 383 |
|
| 384 |
/* If did not reach at the beginning of name then '.' is found.
|
| 385 |
Replace '.' with NULL. */
|
| 386 |
if (p != name)
|
| 387 |
*p = '\0';
|
| 388 |
|
| 389 |
strcat (name, new_suffix);
|
| 390 |
return name;
|
| 391 |
}
|
| 392 |
|
| 393 |
/* Initialization */
|
| 394 |
|
| 395 |
static void
|
| 396 |
initialize (void)
|
| 397 |
{
|
| 398 |
|
| 399 |
int i;
|
| 400 |
|
| 401 |
/* Let's count, how many additional arguments driver driver will supply
|
| 402 |
to compiler driver:
|
| 403 |
|
| 404 |
Each "-arch" "<blah>" is replaced by approriate "-mcpu=<blah>".
|
| 405 |
That leaves one additional arg space available.
|
| 406 |
|
| 407 |
Note that only one -m* is supplied to each compiler driver. Which
|
| 408 |
means, extra "-arch" "<blah>" are removed from the original command
|
| 409 |
line. But lets not count how many additional slots are available.
|
| 410 |
|
| 411 |
Driver driver may need to specify temp. output file name, say
|
| 412 |
"-o" "foobar". That needs two extra argments.
|
| 413 |
|
| 414 |
Sometimes linker wants one additional "-Wl,-arch_multiple".
|
| 415 |
|
| 416 |
Sometimes linker wants to see "-final_output" "outputname".
|
| 417 |
|
| 418 |
In the end, we may need five extra arguments, plus one extra
|
| 419 |
space for the NULL terminator. */
|
| 420 |
|
| 421 |
new_argv = (const char **) malloc ((total_argc + 6) * sizeof (const char *));
|
| 422 |
if (!new_argv)
|
| 423 |
abort ();
|
| 424 |
|
| 425 |
arch_conditional = (const char **) malloc ((total_argc + 6) * sizeof (const char *));
|
| 426 |
if (!arch_conditional)
|
| 427 |
abort ();
|
| 428 |
|
| 429 |
for (i = 0; i < total_argc + 6; i++)
|
| 430 |
arch_conditional[i] = NULL;
|
| 431 |
|
| 432 |
/* First slot, new_argv[0] is reserved for the driver name. */
|
| 433 |
new_argc = 1;
|
| 434 |
|
| 435 |
/* For each -arch, three arguments are needed.
|
| 436 |
For example, "-arch" "ppc" "file". Additional slots are for
|
| 437 |
"lipo" "-create" "-o" "outputfilename" and the NULL. */
|
| 438 |
lipo_argv = (const char **) malloc ((total_argc * 3 + 5) * sizeof (const char *));
|
| 439 |
if (!lipo_argv)
|
| 440 |
abort ();
|
| 441 |
|
| 442 |
/* Need separate out_files for each arch, max is MAX_ARCHES.
|
| 443 |
Need separate out_files for each input file. */
|
| 444 |
|
| 445 |
out_files = (const char **) malloc ((total_argc * MAX_ARCHES) * sizeof (const char *));
|
| 446 |
if (!out_files)
|
| 447 |
abort ();
|
| 448 |
|
| 449 |
num_arches = 0;
|
| 450 |
num_infiles = 0;
|
| 451 |
|
| 452 |
in_files = NULL;
|
| 453 |
last_infile = NULL;
|
| 454 |
|
| 455 |
for (i = 0; i < (MAX_ARCHES + 1); i++)
|
| 456 |
{
|
| 457 |
commands[i].prog = NULL;
|
| 458 |
commands[i].argv = NULL;
|
| 459 |
commands[i].pid = 0;
|
| 460 |
}
|
| 461 |
}
|
| 462 |
|
| 463 |
/* Cleanup. */
|
| 464 |
|
| 465 |
static void
|
| 466 |
final_cleanup (void)
|
| 467 |
{
|
| 468 |
int i;
|
| 469 |
struct input_filename *next;
|
| 470 |
delete_out_files ();
|
| 471 |
free (new_argv);
|
| 472 |
free (lipo_argv);
|
| 473 |
free (out_files);
|
| 474 |
|
| 475 |
for (i = 0, next = in_files;
|
| 476 |
i < num_infiles && next;
|
| 477 |
i++)
|
| 478 |
{
|
| 479 |
next = in_files->next;
|
| 480 |
free (in_files);
|
| 481 |
in_files = next;
|
| 482 |
}
|
| 483 |
}
|
| 484 |
|
| 485 |
/* Wait for the process pid and return appropriate code. */
|
| 486 |
|
| 487 |
static int
|
| 488 |
do_wait (int pid, const char *prog)
|
| 489 |
{
|
| 490 |
int status = 0;
|
| 491 |
int ret = 0;
|
| 492 |
|
| 493 |
pid = pwait (pid, &status, 0);
|
| 494 |
|
| 495 |
if (WIFSIGNALED (status))
|
| 496 |
{
|
| 497 |
if (!signal_count &&
|
| 498 |
WEXITSTATUS (status) > greatest_status)
|
| 499 |
greatest_status = WEXITSTATUS (status);
|
| 500 |
ret = -1;
|
| 501 |
}
|
| 502 |
else if (WIFEXITED (status)
|
| 503 |
&& WEXITSTATUS (status) >= 1)
|
| 504 |
{
|
| 505 |
if (WEXITSTATUS (status) > greatest_status)
|
| 506 |
greatest_status = WEXITSTATUS (status);
|
| 507 |
signal_count++;
|
| 508 |
ret = -1;
|
| 509 |
}
|
| 510 |
return ret;
|
| 511 |
}
|
| 512 |
|
| 513 |
/* Invoke 'lipo' and combine and all output files. */
|
| 514 |
|
| 515 |
static void
|
| 516 |
do_lipo (int start_outfile_index, const char *out_file)
|
| 517 |
{
|
| 518 |
int i, j, pid;
|
| 519 |
char *errmsg_fmt, *errmsg_arg;
|
| 520 |
|
| 521 |
/* Populate lipo arguments. */
|
| 522 |
lipo_argv[0] = "lipo";
|
| 523 |
lipo_argv[1] = "-create";
|
| 524 |
lipo_argv[2] = "-o";
|
| 525 |
lipo_argv[3] = out_file;
|
| 526 |
|
| 527 |
/* Already 4 lipo arguments are set. Now add all lipo inputs. */
|
| 528 |
j = 4;
|
| 529 |
for (i = 0; i < num_arches; i++)
|
| 530 |
lipo_argv[j++] = out_files[start_outfile_index + i];
|
| 531 |
|
| 532 |
/* Add the NULL at the end. */
|
| 533 |
lipo_argv[j++] = NULL;
|
| 534 |
|
| 535 |
#ifdef DEBUG
|
| 536 |
debug_command_line (lipo_argv, j);
|
| 537 |
#endif
|
| 538 |
|
| 539 |
if (verbose_flag)
|
| 540 |
{
|
| 541 |
for (i = 0; lipo_argv[i]; i++)
|
| 542 |
fprintf (stderr, "%s ", lipo_argv[i]);
|
| 543 |
fprintf (stderr, "\n");
|
| 544 |
}
|
| 545 |
pid = pexecute (lipo_argv[0], (char *const *)lipo_argv, progname, NULL, &errmsg_fmt,
|
| 546 |
&errmsg_arg, PEXECUTE_SEARCH | PEXECUTE_ONE);
|
| 547 |
|
| 548 |
if (pid == -1)
|
| 549 |
pfatal_pexecute (errmsg_fmt, errmsg_arg);
|
| 550 |
|
| 551 |
do_wait (pid, lipo_argv[0]);
|
| 552 |
}
|
| 553 |
|
| 554 |
/* Invoke compiler for all architectures. */
|
| 555 |
|
| 556 |
static void
|
| 557 |
do_compile (const char **current_argv, int current_argc)
|
| 558 |
{
|
| 559 |
char *errmsg_fmt, *errmsg_arg;
|
| 560 |
int index = 0;
|
| 561 |
|
| 562 |
int dash_o_index = current_argc;
|
| 563 |
int of_index = current_argc + 1;
|
| 564 |
int argc_count = current_argc + 2;
|
| 565 |
|
| 566 |
const char **arch_specific_argv;
|
| 567 |
|
| 568 |
int arch_specific_argc;
|
| 569 |
|
| 570 |
while (index < num_arches)
|
| 571 |
{
|
| 572 |
int additional_arch_options = 0;
|
| 573 |
|
| 574 |
current_argv[0] = get_driver_name (get_arch_name (arches[index]));
|
| 575 |
|
| 576 |
/* setup output file. */
|
| 577 |
out_files[num_outfiles] = make_temp_file (".out");
|
| 578 |
current_argv[dash_o_index] = "-o";
|
| 579 |
current_argv[of_index] = out_files [num_outfiles];
|
| 580 |
num_outfiles++;
|
| 581 |
|
| 582 |
/* Add arch option as the last option. Do not add any other option
|
| 583 |
before removing this option. */
|
| 584 |
additional_arch_options = add_arch_options (index, current_argv, argc_count);
|
| 585 |
argc_count += additional_arch_options;
|
| 586 |
|
| 587 |
current_argv[argc_count] = NULL;
|
| 588 |
|
| 589 |
arch_specific_argv =
|
| 590 |
(const char **) malloc ((argc_count + 1) * sizeof (const char *));
|
| 591 |
|
| 592 |
arch_specific_argc = filter_args_for_arch (current_argv,
|
| 593 |
argc_count,
|
| 594 |
arch_specific_argv,
|
| 595 |
get_arch_name (arches[index]));
|
| 596 |
|
| 597 |
commands[index].prog = arch_specific_argv[0];
|
| 598 |
commands[index].argv = arch_specific_argv;
|
| 599 |
|
| 600 |
#ifdef DEBUG
|
| 601 |
debug_command_line (arch_specific_argv, arch_specific_argc);
|
| 602 |
#endif
|
| 603 |
commands[index].pid = pexecute (arch_specific_argv[0],
|
| 604 |
(char *const *)arch_specific_argv,
|
| 605 |
progname, NULL,
|
| 606 |
&errmsg_fmt,
|
| 607 |
&errmsg_arg,
|
| 608 |
PEXECUTE_SEARCH | PEXECUTE_ONE);
|
| 609 |
|
| 610 |
if (commands[index].pid == -1)
|
| 611 |
pfatal_pexecute (errmsg_fmt, errmsg_arg);
|
| 612 |
|
| 613 |
do_wait (commands[index].pid, commands[index].prog);
|
| 614 |
fflush (stdout);
|
| 615 |
|
| 616 |
/* Remove the last arch option added in the current_argv list. */
|
| 617 |
if (additional_arch_options)
|
| 618 |
argc_count -= remove_arch_options (current_argv, argc_count);
|
| 619 |
index++;
|
| 620 |
free (arch_specific_argv);
|
| 621 |
}
|
| 622 |
}
|
| 623 |
|
| 624 |
/* Invoke compiler for each input file separately.
|
| 625 |
Construct command line for each invocation with one input file. */
|
| 626 |
|
| 627 |
static void
|
| 628 |
do_compile_separately (void)
|
| 629 |
{
|
| 630 |
const char **new_new_argv;
|
| 631 |
int i, new_new_argc;
|
| 632 |
struct input_filename *current_ifn;
|
| 633 |
|
| 634 |
if (num_infiles == 1 || ima_is_used)
|
| 635 |
abort ();
|
| 636 |
|
| 637 |
/* Total number of arguments in separate compiler invocation is :
|
| 638 |
total number of original arguments - total no input files + one input
|
| 639 |
file + "-o" + output file + arch specific options + NULL . */
|
| 640 |
new_new_argv = (const char **) malloc ((new_argc - num_infiles + 5) * sizeof (const char *));
|
| 641 |
if (!new_new_argv)
|
| 642 |
abort ();
|
| 643 |
|
| 644 |
for (current_ifn = in_files; current_ifn && current_ifn->name;
|
| 645 |
current_ifn = current_ifn->next)
|
| 646 |
{
|
| 647 |
struct input_filename *ifn = in_files;
|
| 648 |
int go_back = 0;
|
| 649 |
new_new_argc = 1;
|
| 650 |
bool ifn_found = false;
|
| 651 |
|
| 652 |
for (i = 1; i < new_argc; i++)
|
| 653 |
{
|
| 654 |
if (ifn && ifn->name && !strcmp (new_argv[i], ifn->name))
|
| 655 |
{
|
| 656 |
/* This argument is one of the input file. */
|
| 657 |
|
| 658 |
if (!strcmp (new_argv[i], current_ifn->name))
|
| 659 |
{
|
| 660 |
if (ifn_found)
|
| 661 |
fatal ("file %s specified more than once on the command line", current_ifn->name);
|
| 662 |
|
| 663 |
/* If it is current input file name then add it in the new
|
| 664 |
list. */
|
| 665 |
new_new_argv[new_new_argc] = new_argv[i];
|
| 666 |
arch_conditional[new_new_argc] = arch_conditional[i];
|
| 667 |
new_new_argc++;
|
| 668 |
ifn_found = true;
|
| 669 |
}
|
| 670 |
/* This input file can not appear in
|
| 671 |
again on the command line so next time look for next input
|
| 672 |
file. */
|
| 673 |
ifn = ifn->next;
|
| 674 |
}
|
| 675 |
else
|
| 676 |
{
|
| 677 |
/* This argument is not a input file name. Add it into new
|
| 678 |
list. */
|
| 679 |
new_new_argv[new_new_argc] = new_argv[i];
|
| 680 |
arch_conditional[new_new_argc] = arch_conditional[i];
|
| 681 |
new_new_argc++;
|
| 682 |
}
|
| 683 |
}
|
| 684 |
|
| 685 |
/* OK now we have only one input file and all other arguments. */
|
| 686 |
do_compile (new_new_argv, new_new_argc);
|
| 687 |
}
|
| 688 |
}
|
| 689 |
|
| 690 |
/* Invoke 'lipo' on set of output files and create multile FAT binaries. */
|
| 691 |
|
| 692 |
static void
|
| 693 |
do_lipo_separately (void)
|
| 694 |
{
|
| 695 |
int ifn_index;
|
| 696 |
struct input_filename *ifn;
|
| 697 |
for (ifn_index = 0, ifn = in_files;
|
| 698 |
ifn_index < num_infiles && ifn && ifn->name;
|
| 699 |
ifn_index++, ifn = ifn->next)
|
| 700 |
do_lipo (ifn_index * num_arches,
|
| 701 |
strip_path_and_suffix (ifn->name, ".o"));
|
| 702 |
}
|
| 703 |
|
| 704 |
/* Remove all options which are architecture-specific and are not for the
|
| 705 |
current architecture (arch). */
|
| 706 |
static int
|
| 707 |
filter_args_for_arch (const char **orig_argv, int orig_argc,
|
| 708 |
const char **new_argv, const char *arch)
|
| 709 |
{
|
| 710 |
int new_argc = 0;
|
| 711 |
int i;
|
| 712 |
|
| 713 |
for (i = 0; i < orig_argc; i++)
|
| 714 |
if (arch_conditional[i] == NULL
|
| 715 |
|| *arch_conditional[i] == '\0'
|
| 716 |
|| ! strcmp (arch_conditional[i], arch))
|
| 717 |
new_argv[new_argc++] = orig_argv[i];
|
| 718 |
|
| 719 |
new_argv[new_argc] = NULL;
|
| 720 |
|
| 721 |
return new_argc;
|
| 722 |
}
|
| 723 |
|
| 724 |
/* Replace -arch <blah> options with appropriate "-mcpu=<blah>" OR
|
| 725 |
"-march=<blah>". INDEX is the index in arches[] table. We cannot
|
| 726 |
return more than 1 as do_compile_separately only allocated one
|
| 727 |
extra slot for us. */
|
| 728 |
|
| 729 |
static int
|
| 730 |
add_arch_options (int index, const char **current_argv, int arch_index)
|
| 731 |
{
|
| 732 |
int count;
|
| 733 |
|
| 734 |
/* We are adding 1 argument for selected arches. */
|
| 735 |
count = 1;
|
| 736 |
|
| 737 |
#ifdef DEBUG
|
| 738 |
fprintf (stderr, "%s: add_arch_options: %s\n", progname, arches[index]);
|
| 739 |
#endif
|
| 740 |
|
| 741 |
if (!strcmp (arches[index], "ppc601"))
|
| 742 |
current_argv[arch_index] = "-mcpu=601";
|
| 743 |
else if (!strcmp (arches[index], "ppc603"))
|
| 744 |
current_argv[arch_index] = "-mcpu=603";
|
| 745 |
else if (!strcmp (arches[index], "ppc604"))
|
| 746 |
current_argv[arch_index] = "-mcpu=604";
|
| 747 |
else if (!strcmp (arches[index], "ppc604e"))
|
| 748 |
current_argv[arch_index] = "-mcpu=604e";
|
| 749 |
else if (!strcmp (arches[index], "ppc750"))
|
| 750 |
current_argv[arch_index] = "-mcpu=750";
|
| 751 |
else if (!strcmp (arches[index], "ppc7400"))
|
| 752 |
current_argv[arch_index] = "-mcpu=7400";
|
| 753 |
else if (!strcmp (arches[index], "ppc7450"))
|
| 754 |
current_argv[arch_index] = "-mcpu=7450";
|
| 755 |
else if (!strcmp (arches[index], "ppc970"))
|
| 756 |
current_argv[arch_index] = "-mcpu=970";
|
| 757 |
else if (!strcmp (arches[index], "ppc64"))
|
| 758 |
current_argv[arch_index] = "-m64";
|
| 759 |
else if (!strcmp (arches[index], "i486"))
|
| 760 |
current_argv[arch_index] = "-march=i486";
|
| 761 |
else if (!strcmp (arches[index], "i586"))
|
| 762 |
current_argv[arch_index] = "-march=i586";
|
| 763 |
else if (!strcmp (arches[index], "i686"))
|
| 764 |
current_argv[arch_index] = "-march=i686";
|
| 765 |
else if (!strcmp (arches[index], "pentium"))
|
| 766 |
current_argv[arch_index] = "-march=pentium";
|
| 767 |
else if (!strcmp (arches[index], "pentium2"))
|
| 768 |
current_argv[arch_index] = "-march=pentium2";
|
| 769 |
else if (!strcmp (arches[index], "pentpro"))
|
| 770 |
current_argv[arch_index] = "-march=pentiumpro";
|
| 771 |
else if (!strcmp (arches[index], "pentIIm3"))
|
| 772 |
current_argv[arch_index] = "-march=pentium2";
|
| 773 |
else if (!strcmp (arches[index], "x86_64"))
|
| 774 |
current_argv[arch_index] = "-m64";
|
| 775 |
else if (!strcmp (arches[index], "arm"))
|
| 776 |
current_argv[arch_index] = "-march=armv4t";
|
| 777 |
else if (!strcmp (arches[index], "armv4t"))
|
| 778 |
current_argv[arch_index] = "-march=armv4t";
|
| 779 |
else if (!strcmp (arches[index], "armv5"))
|
| 780 |
current_argv[arch_index] = "-march=armv5tej";
|
| 781 |
else if (!strcmp (arches[index], "xscale"))
|
| 782 |
current_argv[arch_index] = "-march=xscale";
|
| 783 |
else if (!strcmp (arches[index], "armv6"))
|
| 784 |
current_argv[arch_index] = "-march=armv6k";
|
| 785 |
else if (!strcmp (arches[index], "armv7"))
|
| 786 |
current_argv[arch_index] = "-march=armv7a";
|
| 787 |
else
|
| 788 |
count = 0;
|
| 789 |
|
| 790 |
return count;
|
| 791 |
}
|
| 792 |
|
| 793 |
/* Remove the last option, which is arch option, added by
|
| 794 |
add_arch_options. Return how count of arguments removed. */
|
| 795 |
static int
|
| 796 |
remove_arch_options (const char **current_argv, int arch_index)
|
| 797 |
{
|
| 798 |
#ifdef DEBUG
|
| 799 |
fprintf (stderr, "%s: Removing argument no %d\n", progname, arch_index);
|
| 800 |
#endif
|
| 801 |
|
| 802 |
current_argv[arch_index] = '\0';
|
| 803 |
|
| 804 |
#ifdef DEBUG
|
| 805 |
debug_command_line (current_argv, arch_index);
|
| 806 |
#endif
|
| 807 |
|
| 808 |
return 1;
|
| 809 |
}
|
| 810 |
|
| 811 |
/* Add new arch request. */
|
| 812 |
void
|
| 813 |
add_arch (const char *new_arch)
|
| 814 |
{
|
| 815 |
int i;
|
| 816 |
|
| 817 |
/* User can say cc -arch ppc -arch ppc foo.c
|
| 818 |
Do not invoke ppc compiler twice in this case. */
|
| 819 |
for (i = 0; i < num_arches; i++)
|
| 820 |
{
|
| 821 |
if (!strcmp (arches[i], new_arch))
|
| 822 |
return;
|
| 823 |
}
|
| 824 |
|
| 825 |
arches[num_arches] = new_arch;
|
| 826 |
num_arches++;
|
| 827 |
}
|
| 828 |
|
| 829 |
/* Rewrite the command line as requested in the QA_OVERRIDE_GCC3_OPTIONS
|
| 830 |
environment variable -- used for testing the compiler, working around bugs
|
| 831 |
in the Apple build environment, etc.
|
| 832 |
|
| 833 |
The override string is made up of a set of space-separated clauses. The
|
| 834 |
first letter of each clause describes what's to be done:
|
| 835 |
+string Add string as a new argument (at the end of the command line).
|
| 836 |
Multi-word command lines can be added with +x +y
|
| 837 |
s/x/y/ substitute x for y in the command line. X must be an entire
|
| 838 |
argument, and can be a regular expression as accepted by the
|
| 839 |
POSIX regexp code. Y will be substituted as a single argument,
|
| 840 |
and will not have regexp replacements added in.
|
| 841 |
xoption Removes argument matching option
|
| 842 |
Xoption Removes argument matching option and following word
|
| 843 |
Ox Removes any optimization flags in command line and replaces
|
| 844 |
with -Ox.
|
| 845 |
|
| 846 |
|
| 847 |
Here's some examples:
|
| 848 |
O2
|
| 849 |
s/precomp-trustfile=foo//
|
| 850 |
+-fexplore-antartica
|
| 851 |
+-fast
|
| 852 |
s/-fsetvalue=* //
|
| 853 |
x-fwritable-strings
|
| 854 |
s/-O[0-2]/-Osize/
|
| 855 |
x-v
|
| 856 |
X-o +-o +foo.o
|
| 857 |
|
| 858 |
Option substitutions are processed from left to right; matches and changes
|
| 859 |
are cumulative. An error in processing one element (such as trying to
|
| 860 |
remove an element and successor when the match is at the end) cause the
|
| 861 |
particular change to stop, but additional changes in the environment
|
| 862 |
variable to be applied.
|
| 863 |
|
| 864 |
Key details:
|
| 865 |
* we always want to be able to adjust optimization levels for testing
|
| 866 |
* adding options is a common task
|
| 867 |
* substitution and deletion are less common.
|
| 868 |
|
| 869 |
If the first character of the environment variable is #, changes are
|
| 870 |
silent. If not, diagnostics are written to stderr explaining what
|
| 871 |
changes are being performed.
|
| 872 |
|
| 873 |
*/
|
| 874 |
|
| 875 |
char **arg_array;
|
| 876 |
int arg_array_size=0;
|
| 877 |
int arg_count = 0;
|
| 878 |
int confirm_changes = 1;
|
| 879 |
const int ARG_ARRAY_INCREMENT_SIZE = 8;
|
| 880 |
#define FALSE 0
|
| 881 |
|
| 882 |
/* Routines for the argument array. The argument array routines are
|
| 883 |
responsible for allocation and deallocation of all objects in the
|
| 884 |
array */
|
| 885 |
|
| 886 |
void read_args (int argc, char **argv)
|
| 887 |
{
|
| 888 |
int i;
|
| 889 |
|
| 890 |
arg_array_size = argc+10;
|
| 891 |
arg_count = argc;
|
| 892 |
arg_array = (char**) malloc(sizeof(char*)*arg_array_size);
|
| 893 |
|
| 894 |
for (i=0;i<argc;i++) {
|
| 895 |
arg_array[i] = malloc (strlen (argv[i])+1);
|
| 896 |
strcpy (arg_array[i], argv[i]);
|
| 897 |
}
|
| 898 |
}
|
| 899 |
|
| 900 |
/* Insert the argument before pos. */
|
| 901 |
void insert_arg(int pos, char *arg_to_insert)
|
| 902 |
{
|
| 903 |
int i;
|
| 904 |
char *newArg = malloc (strlen (arg_to_insert)+1);
|
| 905 |
strcpy(newArg, arg_to_insert);
|
| 906 |
|
| 907 |
if (arg_count == arg_array_size) {
|
| 908 |
/* expand array */
|
| 909 |
arg_array_size = arg_count + ARG_ARRAY_INCREMENT_SIZE;
|
| 910 |
arg_array = (char**) realloc (arg_array, arg_array_size);
|
| 911 |
}
|
| 912 |
|
| 913 |
for (i = arg_count; i > pos; i--) {
|
| 914 |
arg_array[i+1] = arg_array[i];
|
| 915 |
}
|
| 916 |
|
| 917 |
arg_array[pos] = newArg;
|
| 918 |
arg_count++;
|
| 919 |
|
| 920 |
if (confirm_changes)
|
| 921 |
fprintf(stderr,"### Adding argument %s at position %d\n",arg_to_insert, pos);
|
| 922 |
}
|
| 923 |
|
| 924 |
|
| 925 |
void replace_arg (char *str, int pos) {
|
| 926 |
char *newArg = malloc(strlen(str)+1);
|
| 927 |
strcpy(newArg,str);
|
| 928 |
|
| 929 |
if (confirm_changes)
|
| 930 |
fprintf (stderr,"### Replacing %s with %s\n",arg_array[pos], str);
|
| 931 |
|
| 932 |
free (arg_array[pos]);
|
| 933 |
arg_array[pos] = newArg;
|
| 934 |
}
|
| 935 |
|
| 936 |
void append_arg (char *str)
|
| 937 |
{
|
| 938 |
char *new_arg = malloc (strlen (str)+1);
|
| 939 |
strcpy (new_arg, str);
|
| 940 |
if (confirm_changes)
|
| 941 |
fprintf(stderr,"### Adding argument %s at end\n", str);
|
| 942 |
|
| 943 |
if (arg_count == arg_array_size) {
|
| 944 |
/* expand array */
|
| 945 |
arg_array_size = arg_count + ARG_ARRAY_INCREMENT_SIZE;
|
| 946 |
arg_array = (char**) realloc (arg_array, arg_array_size);
|
| 947 |
}
|
| 948 |
|
| 949 |
arg_array[arg_count++] = new_arg;
|
| 950 |
}
|
| 951 |
|
| 952 |
void delete_arg(int pos) {
|
| 953 |
int i;
|
| 954 |
|
| 955 |
if (confirm_changes)
|
| 956 |
fprintf(stderr,"### Deleting argument %s\n",arg_array[pos]);
|
| 957 |
|
| 958 |
free (arg_array[pos]);
|
| 959 |
|
| 960 |
for (i=pos; i < arg_count; i++)
|
| 961 |
arg_array[i] = arg_array[i+1];
|
| 962 |
|
| 963 |
arg_count--;
|
| 964 |
}
|
| 965 |
|
| 966 |
/* Changing optimization levels is a common testing pattern --
|
| 967 |
we've got a special option that searches for and replaces anything
|
| 968 |
beginning with -O */
|
| 969 |
void replace_optimization_level (char *new_level) {
|
| 970 |
int i;
|
| 971 |
int optionFound = 0;
|
| 972 |
char *new_opt = malloc(strlen(new_opt)+3);
|
| 973 |
sprintf(new_opt, "-O%s",new_level);
|
| 974 |
|
| 975 |
|
| 976 |
for (i=0;i<arg_count;i++) {
|
| 977 |
if (strncmp(arg_array[i],"-O",2) == 0) {
|
| 978 |
replace_arg (new_opt, i);
|
| 979 |
optionFound = 1;
|
| 980 |
break;
|
| 981 |
}
|
| 982 |
}
|
| 983 |
|
| 984 |
if (optionFound == 0)
|
| 985 |
/* No optimization level? Add it! */
|
| 986 |
append_arg (new_opt);
|
| 987 |
|
| 988 |
free (new_opt);
|
| 989 |
}
|
| 990 |
|
| 991 |
/* Returns a NULL terminated string holding whatever was in the original
|
| 992 |
string at that point. This must be freed by the caller. */
|
| 993 |
|
| 994 |
char *arg_string(char *str, int begin, int len) {
|
| 995 |
char *new_str = malloc(len+1);
|
| 996 |
strncpy(new_str,&str[begin],len);
|
| 997 |
new_str[len] = '\0';
|
| 998 |
return new_str;
|
| 999 |
}
|
| 1000 |
|
| 1001 |
/* Given a search-and-replace string of the form
|
| 1002 |
s/x/y/
|
| 1003 |
|
| 1004 |
do search and replace on the arg list. Make sure to check that the
|
| 1005 |
string is sane -- that it has all the proper slashes that are necessary.
|
| 1006 |
The search string can be a regular expression, but the replace string
|
| 1007 |
must be a literal; the search must also be for a full argument, not for
|
| 1008 |
a chain of arguments. The result will be treated as a single argument.
|
| 1009 |
|
| 1010 |
Return true if success, false if bad failure.
|
| 1011 |
*/
|
| 1012 |
|
| 1013 |
bool search_and_replace (char *str) {
|
| 1014 |
regex_t regexp_search_struct;
|
| 1015 |
int searchLen;
|
| 1016 |
int replaceLen;
|
| 1017 |
int i;
|
| 1018 |
int err;
|
| 1019 |
|
| 1020 |
char *searchStr;
|
| 1021 |
char *replaceStr;
|
| 1022 |
char *replacedStr;
|
| 1023 |
const int ERRSIZ = 512;
|
| 1024 |
char errbuf[ERRSIZ];
|
| 1025 |
|
| 1026 |
|
| 1027 |
if (str[0] != '/') {
|
| 1028 |
return false;
|
| 1029 |
}
|
| 1030 |
|
| 1031 |
searchLen = strcspn (str + 1, "/\0");
|
| 1032 |
|
| 1033 |
if (str[1 + searchLen] != '/')
|
| 1034 |
return false;
|
| 1035 |
|
| 1036 |
replaceLen = strcspn(str+1+searchLen+1, "/\0");
|
| 1037 |
|
| 1038 |
if (str[1 + searchLen + 1 +replaceLen] != '/')
|
| 1039 |
return false;
|
| 1040 |
|
| 1041 |
searchStr = arg_string(str, 1, searchLen);
|
| 1042 |
replaceStr = arg_string (str, 1 + searchLen + 1, replaceLen);
|
| 1043 |
|
| 1044 |
if ((err = regcomp(®exp_search_struct, searchStr, REG_EXTENDED)) != 0) {
|
| 1045 |
regerror(err, ®exp_search_struct, errbuf, ERRSIZ);
|
| 1046 |
fprintf(stderr,"%s",errbuf);
|
| 1047 |
return false;
|
| 1048 |
}
|
| 1049 |
|
| 1050 |
for (i=0;i<arg_count;i++) {
|
| 1051 |
regmatch_t matches[5];
|
| 1052 |
if (regexec (®exp_search_struct, arg_array[i],
|
| 1053 |
5, matches, 0) == 0) {
|
| 1054 |
if ((matches[0].rm_eo - matches[0].rm_so) == strlen (arg_array[i])) {
|
| 1055 |
/* Success! Change the string. */
|
| 1056 |
replace_arg(replaceStr,i);
|
| 1057 |
break;
|
| 1058 |
}
|
| 1059 |
}
|
| 1060 |
}
|
| 1061 |
|
| 1062 |
regfree (®exp_search_struct);
|
| 1063 |
free (searchStr);
|
| 1064 |
free (replaceStr);
|
| 1065 |
|
| 1066 |
return true;
|
| 1067 |
}
|
| 1068 |
|
| 1069 |
|
| 1070 |
/* Given a string, return the argument number where the first match occurs. */
|
| 1071 |
int find_arg (char *str) {
|
| 1072 |
int i;
|
| 1073 |
int matchIndex = -1;
|
| 1074 |
|
| 1075 |
for (i=0;i<arg_count;i++) {
|
| 1076 |
if (strcmp(arg_array[i],str) == 0) {
|
| 1077 |
matchIndex = i;
|
| 1078 |
break;
|
| 1079 |
}
|
| 1080 |
}
|
| 1081 |
|
| 1082 |
return matchIndex;
|
| 1083 |
}
|
| 1084 |
|
| 1085 |
void rewrite_command_line (char *override_options_line, int *argc, char ***argv){
|
| 1086 |
int line_pos = 0;
|
| 1087 |
|
| 1088 |
read_args (*argc, *argv);
|
| 1089 |
|
| 1090 |
if (override_options_line[0] == '#')
|
| 1091 |
{
|
| 1092 |
confirm_changes = 0;
|
| 1093 |
line_pos++;
|
| 1094 |
}
|
| 1095 |
|
| 1096 |
|
| 1097 |
if (confirm_changes)
|
| 1098 |
fprintf (stderr, "### QA_OVERRIDE_GCC3_OPTIONS: %s\n",
|
| 1099 |
override_options_line);
|
| 1100 |
|
| 1101 |
/* Loop through all commands in the file */
|
| 1102 |
|
| 1103 |
while (override_options_line[line_pos] != '\0')
|
| 1104 |
{
|
| 1105 |
char first_char;
|
| 1106 |
char *searchStr;
|
| 1107 |
char *arg;
|
| 1108 |
int search_index;
|
| 1109 |
int arg_len;
|
| 1110 |
|
| 1111 |
/* Any spaces in between options don't count. */
|
| 1112 |
if (override_options_line[line_pos] == ' ')
|
| 1113 |
{
|
| 1114 |
line_pos++;
|
| 1115 |
continue;
|
| 1116 |
}
|
| 1117 |
|
| 1118 |
/* The first non-space character is the command. */
|
| 1119 |
first_char = override_options_line[line_pos];
|
| 1120 |
line_pos++;
|
| 1121 |
arg_len = strcspn(override_options_line+line_pos, " ");
|
| 1122 |
|
| 1123 |
switch (first_char) {
|
| 1124 |
case '+':
|
| 1125 |
/* Add an argument to the end of the arg list */
|
| 1126 |
arg = arg_string (override_options_line,
|
| 1127 |
line_pos,
|
| 1128 |
arg_len);
|
| 1129 |
append_arg (arg);
|
| 1130 |
free (arg);
|
| 1131 |
break;
|
| 1132 |
|
| 1133 |
case 'x':
|
| 1134 |
/* Delete a matching argument */
|
| 1135 |
searchStr = arg_string(override_options_line, line_pos, arg_len);
|
| 1136 |
if ((search_index = find_arg(searchStr)) != -1) {
|
| 1137 |
delete_arg(search_index);
|
| 1138 |
}
|
| 1139 |
free (searchStr);
|
| 1140 |
break;
|
| 1141 |
|
| 1142 |
case 'X':
|
| 1143 |
/* Delete a matching argument and the argument following. */
|
| 1144 |
searchStr = arg_string(override_options_line, line_pos, arg_len);
|
| 1145 |
if ((search_index = find_arg(searchStr)) != -1) {
|
| 1146 |
if (search_index >= arg_count -1) {
|
| 1147 |
if (confirm_changes)
|
| 1148 |
fprintf(stderr,"Not enough arguments to do X\n");
|
| 1149 |
} else {
|
| 1150 |
delete_arg(search_index); /* Delete the matching argument */
|
| 1151 |
delete_arg(search_index); /* Delete the following argument */
|
| 1152 |
}
|
| 1153 |
}
|
| 1154 |
free (searchStr);
|
| 1155 |
break;
|
| 1156 |
|
| 1157 |
case 'O':
|
| 1158 |
/* Change the optimization level to the specified value, and
|
| 1159 |
remove any optimization arguments. This is a separate command
|
| 1160 |
because we often want is to substitute our favorite
|
| 1161 |
optimization level for whatever the project normally wants.
|
| 1162 |
As we probably care about this a lot (for things like
|
| 1163 |
testing file sizes at different optimization levels) we
|
| 1164 |
make a special rewrite clause. */
|
| 1165 |
arg = arg_string (override_options_line, line_pos, arg_len);
|
| 1166 |
replace_optimization_level(arg);
|
| 1167 |
free (arg);
|
| 1168 |
break;
|
| 1169 |
case 's':
|
| 1170 |
/* Search for the regexp passed in, and replace a matching argument
|
| 1171 |
with the provided replacement string */
|
| 1172 |
searchStr = arg_string (override_options_line, line_pos, arg_len);
|
| 1173 |
search_and_replace (searchStr);
|
| 1174 |
free (searchStr);
|
| 1175 |
break;
|
| 1176 |
|
| 1177 |
default:
|
| 1178 |
fprintf(stderr,"### QA_OVERRIDE_GCC3_OPTIONS: invalid string (pos %d)\n",
|
| 1179 |
line_pos);
|
| 1180 |
break;
|
| 1181 |
}
|
| 1182 |
line_pos += arg_len;
|
| 1183 |
}
|
| 1184 |
*argc = arg_count;
|
| 1185 |
*argv = arg_array;
|
| 1186 |
}
|
| 1187 |
|
| 1188 |
/* Given a path to a file, potentially containing a directory name, return the
|
| 1189 |
number of characters at the end of the path that make up the filename part of
|
| 1190 |
the path. */
|
| 1191 |
|
| 1192 |
static int
|
| 1193 |
get_prog_name_len (const char *prog)
|
| 1194 |
{
|
| 1195 |
int result = 0;
|
| 1196 |
const char *progend = prog + strlen(prog);
|
| 1197 |
const char *progname = progend;
|
| 1198 |
while (progname != prog && !IS_DIR_SEPARATOR (progname[-1]))
|
| 1199 |
--progname;
|
| 1200 |
return progend-progname;
|
| 1201 |
}
|
| 1202 |
|
| 1203 |
/* Return true iff the path is an executable file and not a directory. */
|
| 1204 |
|
| 1205 |
static bool
|
| 1206 |
is_x_file (const char *path)
|
| 1207 |
{
|
| 1208 |
struct stat st;
|
| 1209 |
if (access (path, X_OK))
|
| 1210 |
return false;
|
| 1211 |
if (stat (path, &st) == -1)
|
| 1212 |
return false;
|
| 1213 |
if (S_ISDIR (st.st_mode))
|
| 1214 |
return false;
|
| 1215 |
return true;
|
| 1216 |
}
|
| 1217 |
|
| 1218 |
/* Given a FILENAME of an executable (for example "gcc") search the PATH
|
| 1219 |
environment variable to find out which directory it is in and return a fully
|
| 1220 |
qualified path to the executable.
|
| 1221 |
*/
|
| 1222 |
|
| 1223 |
static const char *
|
| 1224 |
resolve_path_to_executable (const char *filename)
|
| 1225 |
{
|
| 1226 |
char path_buffer[2*PATH_MAX+1];
|
| 1227 |
char *PATH = getenv ("PATH");
|
| 1228 |
if (PATH == 0) return filename; /* PATH not set */
|
| 1229 |
|
| 1230 |
do {
|
| 1231 |
unsigned prefix_size;
|
| 1232 |
struct stat st;
|
| 1233 |
char *colon = strchr (PATH, ':');
|
| 1234 |
|
| 1235 |
/* If we didn't find a :, use the whole last chunk. */
|
| 1236 |
prefix_size = colon ? colon-PATH : strlen (PATH);
|
| 1237 |
|
| 1238 |
/* Form the full path. */
|
| 1239 |
memcpy (path_buffer, PATH, prefix_size);
|
| 1240 |
path_buffer[prefix_size] = '/';
|
| 1241 |
strcpy (path_buffer+prefix_size+1, filename);
|
| 1242 |
|
| 1243 |
/* Check to see if this file is executable, if so, return it. */
|
| 1244 |
if (is_x_file (path_buffer))
|
| 1245 |
return strdup (path_buffer);
|
| 1246 |
PATH = colon ? colon+1 : PATH+prefix_size;
|
| 1247 |
} while (PATH[0]);
|
| 1248 |
|
| 1249 |
return filename;
|
| 1250 |
}
|
| 1251 |
|
| 1252 |
/* If prog is a symlink, we want to rewrite prog to an absolute location,
|
| 1253 |
symlink_buffer contains the destination of the symlink. Glue these pieces
|
| 1254 |
together to form an absolute path. */
|
| 1255 |
|
| 1256 |
static const char *
|
| 1257 |
resolve_symlink (const char *prog, char *symlink_buffer,
|
| 1258 |
int argv_0_len, int prog_len)
|
| 1259 |
{
|
| 1260 |
/* If the link isn't to an absolute path, prefix it with the argv[0]
|
| 1261 |
directory. */
|
| 1262 |
if (!IS_ABSOLUTE_PATH (symlink_buffer))
|
| 1263 |
{
|
| 1264 |
int prefix_len = argv_0_len - prog_len;
|
| 1265 |
memmove (symlink_buffer+prefix_len, symlink_buffer,
|
| 1266 |
PATH_MAX-prefix_len+1);
|
| 1267 |
memcpy (symlink_buffer, prog, prefix_len);
|
| 1268 |
}
|
| 1269 |
return strdup(symlink_buffer);
|
| 1270 |
}
|
| 1271 |
|
| 1272 |
/* Main entry point. This is gcc driver driver!
|
| 1273 |
Interpret -arch flag from the list of input arguments. Invoke appropriate
|
| 1274 |
compiler driver. 'lipo' the results if more than one -arch is supplied. */
|
| 1275 |
int
|
| 1276 |
main (int argc, const char **argv)
|
| 1277 |
{
|
| 1278 |
size_t i;
|
| 1279 |
int l, pid, argv_0_len, prog_len;
|
| 1280 |
char *errmsg_fmt, *errmsg_arg;
|
| 1281 |
char *override_option_str = NULL;
|
| 1282 |
char path_buffer[2*PATH_MAX+1];
|
| 1283 |
int linklen;
|
| 1284 |
|
| 1285 |
total_argc = argc;
|
| 1286 |
prog_len = 0;
|
| 1287 |
|
| 1288 |
argv_0_len = strlen (argv[0]);
|
| 1289 |
|
| 1290 |
/* Get the progname, required by pexecute () and program location. */
|
| 1291 |
prog_len = get_prog_name_len (argv[0]);
|
| 1292 |
|
| 1293 |
/* If argv[0] is all program name (no slashes), search the PATH environment
|
| 1294 |
variable to get the fully resolved path to the executable. */
|
| 1295 |
if (prog_len == argv_0_len)
|
| 1296 |
{
|
| 1297 |
#ifdef DEBUG
|
| 1298 |
progname = argv[0] + argv_0_len - prog_len;
|
| 1299 |
fprintf (stderr,"%s: before PATH resolution, full progname = %s\n",
|
| 1300 |
argv[0]+argv_0_len-prog_len, argv[0]);
|
| 1301 |
#endif
|
| 1302 |
argv[0] = resolve_path_to_executable (argv[0]);
|
| 1303 |
prog_len = get_prog_name_len (argv[0]);
|
| 1304 |
argv_0_len = strlen(argv[0]);
|
| 1305 |
}
|
| 1306 |
|
| 1307 |
/* If argv[0] is a symbolic link, use the directory of the pointed-to file
|
| 1308 |
to find compiler components. */
|
| 1309 |
/* LLVM LOCAL: loop to follow multiple levels of links */
|
| 1310 |
while ((linklen = readlink (argv[0], path_buffer, PATH_MAX)) != -1)
|
| 1311 |
{
|
| 1312 |
/* readlink succeeds if argv[0] is a symlink. path_buffer now contains
|
| 1313 |
the file referenced. */
|
| 1314 |
path_buffer[linklen] = '\0';
|
| 1315 |
#ifdef DEBUG
|
| 1316 |
progname = argv[0] + argv_0_len - prog_len;
|
| 1317 |
fprintf (stderr, "%s: before symlink, full prog = %s target = %s\n",
|
| 1318 |
progname, argv[0], path_buffer);
|
| 1319 |
#endif
|
| 1320 |
argv[0] = resolve_symlink(argv[0], path_buffer, argv_0_len, prog_len);
|
| 1321 |
argv_0_len = strlen(argv[0]);
|
| 1322 |
|
| 1323 |
/* Get the progname, required by pexecute () and program location. */
|
| 1324 |
prog_len = get_prog_name_len (argv[0]);
|
| 1325 |
|
| 1326 |
#ifdef DEBUG
|
| 1327 |
progname = argv[0] + argv_0_len - prog_len;
|
| 1328 |
printf("%s: ARGV[0] after symlink = %s\n", progname, argv[0]);
|
| 1329 |
#endif
|
| 1330 |
}
|
| 1331 |
|
| 1332 |
progname = argv[0] + argv_0_len - prog_len;
|
| 1333 |
|
| 1334 |
/* Setup driver prefix. */
|
| 1335 |
prefix_len = argv_0_len - prog_len;
|
| 1336 |
curr_dir = (char *) malloc (sizeof (char) * (prefix_len + 1));
|
| 1337 |
strncpy (curr_dir, argv[0], prefix_len);
|
| 1338 |
curr_dir[prefix_len] = '\0';
|
| 1339 |
driver_exec_prefix = (argv[0], "/usr/bin", curr_dir);
|
| 1340 |
|
| 1341 |
#ifdef DEBUG
|
| 1342 |
fprintf (stderr,"%s: full progname = %s\n", progname, argv[0]);
|
| 1343 |
fprintf (stderr,"%s: progname = %s\n", progname, progname);
|
| 1344 |
fprintf (stderr,"%s: driver_exec_prefix = %s\n", progname, driver_exec_prefix);
|
| 1345 |
#endif
|
| 1346 |
|
| 1347 |
/* Before we get too far, rewrite the command line with any requested overrides */
|
| 1348 |
if ((override_option_str = getenv ("QA_OVERRIDE_GCC3_OPTIONS")) != NULL)
|
| 1349 |
rewrite_command_line(override_option_str, &argc, (char***)&argv);
|
| 1350 |
|
| 1351 |
|
| 1352 |
|
| 1353 |
initialize ();
|
| 1354 |
|
| 1355 |
/* Process arguments. Take appropriate actions when
|
| 1356 |
-arch, -c, -S, -E, -o is encountered. Find input file name. */
|
| 1357 |
for (i = 1; i < argc; i++)
|
| 1358 |
{
|
| 1359 |
if (!strcmp (argv[i], "-arch"))
|
| 1360 |
{
|
| 1361 |
if (i + 1 >= argc)
|
| 1362 |
abort ();
|
| 1363 |
|
| 1364 |
add_arch (argv[i+1]);
|
| 1365 |
i++;
|
| 1366 |
}
|
| 1367 |
else if (!strcmp (argv[i], "-c"))
|
| 1368 |
{
|
| 1369 |
new_argv[new_argc++] = argv[i];
|
| 1370 |
compile_only_request = 1;
|
| 1371 |
}
|
| 1372 |
else if (!strcmp (argv[i], "-S"))
|
| 1373 |
{
|
| 1374 |
new_argv[new_argc++] = argv[i];
|
| 1375 |
asm_output_request = 1;
|
| 1376 |
}
|
| 1377 |
else if (!strcmp (argv[i], "-E"))
|
| 1378 |
{
|
| 1379 |
new_argv[new_argc++] = argv[i];
|
| 1380 |
preprocessed_output_request = 1;
|
| 1381 |
}
|
| 1382 |
else if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
|
| 1383 |
{
|
| 1384 |
new_argv[new_argc++] = argv[i];
|
| 1385 |
dash_capital_m_seen = 1;
|
| 1386 |
}
|
| 1387 |
else if (!strcmp (argv[i], "-m32"))
|
| 1388 |
{
|
| 1389 |
new_argv[new_argc++] = argv[i];
|
| 1390 |
dash_m32_seen = 1;
|
| 1391 |
}
|
| 1392 |
else if (!strcmp (argv[i], "-m64"))
|
| 1393 |
{
|
| 1394 |
new_argv[new_argc++] = argv[i];
|
| 1395 |
dash_m64_seen = 1;
|
| 1396 |
}
|
| 1397 |
else if (!strcmp (argv[i], "-dynamiclib"))
|
| 1398 |
{
|
| 1399 |
new_argv[new_argc++] = argv[i];
|
| 1400 |
dash_dynamiclib_seen = 1;
|
| 1401 |
}
|
| 1402 |
else if (!strcmp (argv[i], "-v"))
|
| 1403 |
{
|
| 1404 |
new_argv[new_argc++] = argv[i];
|
| 1405 |
verbose_flag = 1;
|
| 1406 |
}
|
| 1407 |
else if (!strcmp (argv[i], "-o"))
|
| 1408 |
{
|
| 1409 |
if (i + 1 >= argc)
|
| 1410 |
fatal ("argument to '-o' is missing");
|
| 1411 |
|
| 1412 |
output_filename = argv[i+1];
|
| 1413 |
i++;
|
| 1414 |
}
|
| 1415 |
else if ((! strcmp (argv[i], "-pass-exit-codes"))
|
| 1416 |
|| (! strcmp (argv[i], "-print-search-dirs"))
|
| 1417 |
|| (! strcmp (argv[i], "-print-libgcc-file-name"))
|
| 1418 |
|| (! strncmp (argv[i], "-print-file-name=", 17))
|
| 1419 |
|| (! strncmp (argv[i], "-print-prog-name=", 17))
|
| 1420 |
|| (! strcmp (argv[i], "-print-multi-lib"))
|
| 1421 |
|| (! strcmp (argv[i], "-print-multi-directory"))
|
| 1422 |
|| (! strcmp (argv[i], "-print-multi-os-directory"))
|
| 1423 |
|| (! strcmp (argv[i], "-ftarget-help"))
|
| 1424 |
|| (! strcmp (argv[i], "-fhelp"))
|
| 1425 |
|| (! strcmp (argv[i], "+e"))
|
| 1426 |
|| (! strncmp (argv[i], "-Wa,",4))
|
| 1427 |
|| (! strncmp (argv[i], "-Wp,",4))
|
| 1428 |
|| (! strncmp (argv[i], "-Wl,",4))
|
| 1429 |
|| (! strncmp (argv[i], "-l", 2))
|
| 1430 |
|| (! strncmp (argv[i], "-weak-l", 7))
|
| 1431 |
|| (! strncmp (argv[i], "-specs=", 7))
|
| 1432 |
|| (! strcmp (argv[i], "-ObjC"))
|
| 1433 |
|| (! strcmp (argv[i], "-fobjC"))
|
| 1434 |
|| (! strcmp (argv[i], "-ObjC++"))
|
| 1435 |
|| (! strcmp (argv[i], "-time"))
|
| 1436 |
|| (! strcmp (argv[i], "-###"))
|
| 1437 |
|| (! strcmp (argv[i], "-fconstant-cfstrings"))
|
| 1438 |
|| (! strcmp (argv[i], "-fno-constant-cfstrings"))
|
| 1439 |
|| (! strcmp (argv[i], "-static-libgcc"))
|
| 1440 |
|| (! strcmp (argv[i], "-shared-libgcc"))
|
| 1441 |
|| (! strcmp (argv[i], "-pipe"))
|
| 1442 |
)
|
| 1443 |
{
|
| 1444 |
new_argv[new_argc++] = argv[i];
|
| 1445 |
}
|
| 1446 |
else if (! strcmp (argv[i], "-save-temps")
|
| 1447 |
|| ! strcmp (argv[i], "--save-temps"))
|
| 1448 |
{
|
| 1449 |
new_argv[new_argc++] = argv[i];
|
| 1450 |
save_temps_seen = 1;
|
| 1451 |
}
|
| 1452 |
else if ((! strcmp (argv[i], "-Xlinker"))
|
| 1453 |
|| (! strcmp (argv[i], "-Xassembler"))
|
| 1454 |
|| (! strcmp (argv[i], "-Xpreprocessor"))
|
| 1455 |
|| (! strcmp (argv[i], "-l"))
|
| 1456 |
|| (! strcmp (argv[i], "-weak_library"))
|
| 1457 |
|| (! strcmp (argv[i], "-weak_framework"))
|
| 1458 |
|| (! strcmp (argv[i], "-specs"))
|
| 1459 |
|| (! strcmp (argv[i], "-framework"))
|
| 1460 |
)
|
| 1461 |
{
|
| 1462 |
new_argv[new_argc++] = argv[i];
|
| 1463 |
i++;
|
| 1464 |
new_argv[new_argc++] = argv[i];
|
| 1465 |
}
|
| 1466 |
else if (! strncmp (argv[i], "-Xarch_", 7))
|
| 1467 |
{
|
| 1468 |
arch_conditional[new_argc] = get_arch_name (argv[i] + 7);
|
| 1469 |
i++;
|
| 1470 |
new_argv[new_argc++] = argv[i];
|
| 1471 |
}
|
| 1472 |
else if (argv[i][0] == '-' && argv[i][1] != 0)
|
| 1473 |
{
|
| 1474 |
const char *p = &argv[i][1];
|
| 1475 |
int c = *p;
|
| 1476 |
|
| 1477 |
/* First copy this flag itself. */
|
| 1478 |
new_argv[new_argc++] = argv[i];
|
| 1479 |
|
| 1480 |
if (argv[i][1] == 'M')
|
| 1481 |
dash_capital_m_seen = 1;
|
| 1482 |
|
| 1483 |
/* Now copy this flag's arguments, if any, appropriately. */
|
| 1484 |
if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
|
| 1485 |
|| WORD_SWITCH_TAKES_ARG (p))
|
| 1486 |
{
|
| 1487 |
int j = 0;
|
| 1488 |
int n_args = WORD_SWITCH_TAKES_ARG (p);
|
| 1489 |
if (n_args == 0)
|
| 1490 |
{
|
| 1491 |
/* Count only the option arguments in separate argv elements. */
|
| 1492 |
n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
|
| 1493 |
}
|
| 1494 |
if (i + n_args >= argc)
|
| 1495 |
fatal ("argument to `-%s' is missing", p);
|
| 1496 |
|
| 1497 |
|
| 1498 |
while ( j < n_args)
|
| 1499 |
{
|
| 1500 |
i++;
|
| 1501 |
new_argv[new_argc++] = argv[i];
|
| 1502 |
j++;
|
| 1503 |
}
|
| 1504 |
}
|
| 1505 |
|
| 1506 |
}
|
| 1507 |
else
|
| 1508 |
{
|
| 1509 |
struct input_filename *ifn;
|
| 1510 |
new_argv[new_argc++] = argv[i];
|
| 1511 |
ifn = (struct input_filename *) malloc (sizeof (struct input_filename));
|
| 1512 |
ifn->name = argv[i];
|
| 1513 |
ifn->index = i;
|
| 1514 |
ifn->next = NULL;
|
| 1515 |
num_infiles++;
|
| 1516 |
|
| 1517 |
if (last_infile)
|
| 1518 |
last_infile->next = ifn;
|
| 1519 |
else
|
| 1520 |
in_files = ifn;
|
| 1521 |
|
| 1522 |
last_infile = ifn;
|
| 1523 |
}
|
| 1524 |
}
|
| 1525 |
|
| 1526 |
#if 0
|
| 1527 |
if (num_infiles == 0)
|
| 1528 |
fatal ("no input files");
|
| 1529 |
#endif
|
| 1530 |
|
| 1531 |
if (num_arches == 0)
|
| 1532 |
add_arch(get_arch_name(NULL));
|
| 1533 |
|
| 1534 |
if (num_arches > 1)
|
| 1535 |
{
|
| 1536 |
if (preprocessed_output_request
|
| 1537 |
|| save_temps_seen
|
| 1538 |
|| asm_output_request
|
| 1539 |
|| dash_capital_m_seen)
|
| 1540 |
fatal ("-E, -S, -save-temps and -M options are not allowed with multiple -arch flags");
|
| 1541 |
}
|
| 1542 |
/* If -arch is not present OR Only one -arch <blah> is specified.
|
| 1543 |
Invoke appropriate compiler driver. FAT build is not required in this
|
| 1544 |
case. */
|
| 1545 |
|
| 1546 |
if (num_arches == 1)
|
| 1547 |
{
|
| 1548 |
int arch_specific_argc;
|
| 1549 |
const char **arch_specific_argv;
|
| 1550 |
|
| 1551 |
/* Find compiler driver based on -arch <foo> and add approriate
|
| 1552 |
-m* argument. */
|
| 1553 |
new_argv[0] = get_driver_name (get_arch_name (arches[0]));
|
| 1554 |
new_argc = new_argc + add_arch_options (0, new_argv, new_argc);
|
| 1555 |
|
| 1556 |
#ifdef DEBUG
|
| 1557 |
printf ("%s: invoking single driver name = %s\n", progname, new_argv[0]);
|
| 1558 |
#endif
|
| 1559 |
|
| 1560 |
/* Re insert output file name. */
|
| 1561 |
if (output_filename)
|
| 1562 |
{
|
| 1563 |
new_argv[new_argc++] = "-o";
|
| 1564 |
new_argv[new_argc++] = output_filename;
|
| 1565 |
}
|
| 1566 |
|
| 1567 |
/* Add the NULL. */
|
| 1568 |
new_argv[new_argc] = NULL;
|
| 1569 |
|
| 1570 |
arch_specific_argv =
|
| 1571 |
(const char **) malloc ((new_argc + 1) * sizeof (const char *));
|
| 1572 |
arch_specific_argc = filter_args_for_arch (new_argv,
|
| 1573 |
new_argc,
|
| 1574 |
arch_specific_argv,
|
| 1575 |
get_arch_name (arches[0]));
|
| 1576 |
|
| 1577 |
#ifdef DEBUG
|
| 1578 |
debug_command_line (arch_specific_argv, arch_specific_argc);
|
| 1579 |
#endif
|
| 1580 |
|
| 1581 |
pid = pexecute (arch_specific_argv[0], (char *const *)arch_specific_argv,
|
| 1582 |
progname, NULL, &errmsg_fmt, &errmsg_arg,
|
| 1583 |
PEXECUTE_SEARCH | PEXECUTE_ONE);
|
| 1584 |
|
| 1585 |
if (pid == -1)
|
| 1586 |
pfatal_pexecute (errmsg_fmt, errmsg_arg);
|
| 1587 |
|
| 1588 |
do_wait (pid, arch_specific_argv[0]);
|
| 1589 |
}
|
| 1590 |
else
|
| 1591 |
{
|
| 1592 |
/* Handle multiple -arch <blah>. */
|
| 1593 |
|
| 1594 |
/* If more than one input files are supplied but only one output filename
|
| 1595 |
is present then IMA will be used. */
|
| 1596 |
if (num_infiles > 1 && !compile_only_request)
|
| 1597 |
ima_is_used = 1;
|
| 1598 |
|
| 1599 |
/* The compiler and linker both want to know if we have multiple archs.
|
| 1600 |
The compiler for debug info emission and the linker for augmenting
|
| 1601 |
error and warning messages. */
|
| 1602 |
new_argv[new_argc++] = "-arch_multiple";
|
| 1603 |
|
| 1604 |
|
| 1605 |
/* If only one input file is specified OR IMA is used then expected output
|
| 1606 |
is one FAT binary. */
|
| 1607 |
if (num_infiles == 1 || ima_is_used)
|
| 1608 |
{
|
| 1609 |
const char *out_file;
|
| 1610 |
|
| 1611 |
/* Create output file name based on
|
| 1612 |
input filename, if required. */
|
| 1613 |
if (compile_only_request && !output_filename && num_infiles == 1)
|
| 1614 |
out_file = strip_path_and_suffix (in_files->name, ".o");
|
| 1615 |
else
|
| 1616 |
out_file = (output_filename ? output_filename : final_output);
|
| 1617 |
|
| 1618 |
|
| 1619 |
/* Linker wants to know name of output file using one extra arg. */
|
| 1620 |
if (!compile_only_request)
|
| 1621 |
{
|
| 1622 |
char *oname = (char *)(output_filename ? output_filename : final_output);
|
| 1623 |
char *n = malloc (sizeof (char) * (strlen (oname) + 5));
|
| 1624 |
strcpy (n, "-Wl,");
|
| 1625 |
strcat (n, oname);
|
| 1626 |
new_argv[new_argc++] = "-Wl,-final_output";
|
| 1627 |
new_argv[new_argc++] = n;
|
| 1628 |
}
|
| 1629 |
|
| 1630 |
/* Compile file(s) for each arch and lipo 'em together. */
|
| 1631 |
do_compile (new_argv, new_argc);
|
| 1632 |
|
| 1633 |
/* Make FAT binary by combining individual output files for each
|
| 1634 |
architecture, using 'lipo'. */
|
| 1635 |
do_lipo (0, out_file);
|
| 1636 |
}
|
| 1637 |
else
|
| 1638 |
{
|
| 1639 |
/* Multiple input files are present and IMA is not used.
|
| 1640 |
Which means need to generate multiple FAT files. */
|
| 1641 |
do_compile_separately ();
|
| 1642 |
do_lipo_separately ();
|
| 1643 |
}
|
| 1644 |
}
|
| 1645 |
|
| 1646 |
final_cleanup ();
|
| 1647 |
free (curr_dir);
|
| 1648 |
return greatest_status;
|
| 1649 |
}
|