From: Doug Evans Date: Wed, 15 Jun 1994 08:04:07 +0000 (+0000) Subject: gcc.c: Include multilib.h. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=60103a34825ddfa2e18d3d01f67d6d162c5dfaf4;p=gcc.git gcc.c: Include multilib.h. * gcc.c: Include multilib.h. (print_multi_lib, print_multi_directory, multilib_select, multilib_dir): New static variables. (option_map): Added --print-multi-lib and --print-multi-directory. (set_spec): Get multilib_select from specs file. (process_command): Dump multilib_select into specs file. Handle -print-multi-lib and -print-multi-directory. (do_spec_1): Try multilib_dir for %D case. (find_file): Try multilib_dir. (main): Call set_multilib_dir. Handle print_multi_lib and print_multi_directory. (used_arg, set_multilib_dir, print_multilib_info): New functions. From-SVN: r7491 --- diff --git a/gcc/gcc.c b/gcc/gcc.c index 56b99edd9cf..00ffa389ddb 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -45,6 +45,9 @@ compilation is specified by a string called a "spec". */ #endif #include +/* Include multi-lib information. */ +#include "multilib.h" + #ifndef R_OK #define R_OK 4 #define W_OK 2 @@ -151,6 +154,16 @@ static char *print_file_name = NULL; static char *print_prog_name = NULL; +/* Flag saying to print the relative path we'd use to + find libgcc.a given the current compiler flags. */ + +static int print_multi_directory; + +/* Flag saying to print the list of subdirectories and + compiler flags used to select them in a standard form. */ + +static int print_multi_lib; + /* Flag indicating whether we should print the command and arguments */ static int verbose_flag; @@ -224,6 +237,9 @@ static int is_directory PROTO((char *, char *, int)); static void validate_switches PROTO((char *)); static void validate_all_switches PROTO((void)); static void give_switch PROTO((int, int)); +static int used_arg PROTO((char *, int)); +static void set_multilib_dir PROTO((void)); +static void print_multilib_info PROTO((void)); static void pfatal_with_name PROTO((char *)); static void perror_with_name PROTO((char *)); static void perror_exec PROTO((char *)); @@ -304,6 +320,7 @@ or with constant text in a single argument. used here. This can be used to run a post-processor after the assembler has done it's job. %D Dump out a -L option for each directory in startfile_prefix. + If multilib_dir is set, extra entries are generated with it affixed. %l process LINK_SPEC as a spec. %L process LIB_SPEC as a spec. %S process STARTFILE_SPEC as a spec. A capital S is actually used here. @@ -433,6 +450,13 @@ proper position among the other output files. */ #endif #endif +/* MULTILIB_SELECT comes from multilib.h. It gives a + string interpreted by set_multilib_dir to select a library + subdirectory based on the compiler options. */ +#ifndef MULTILIB_SELECT +#define MULTILIB_SELECT ". ;" +#endif + static char *cpp_spec = CPP_SPEC; static char *cpp_predefines = CPP_PREDEFINES; static char *cc1_spec = CC1_SPEC; @@ -445,6 +469,7 @@ static char *lib_spec = LIB_SPEC; static char *endfile_spec = ENDFILE_SPEC; static char *startfile_spec = STARTFILE_SPEC; static char *switches_need_spaces = SWITCHES_NEED_SPACES; +static char *multilib_select = MULTILIB_SELECT; /* This defines which switch letters take arguments. */ @@ -789,6 +814,8 @@ struct option_map option_map[] = {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, {"--print-file-name", "-print-file-name=", "aj"}, {"--print-prog-name", "-print-prog-name=", "aj"}, + {"--print-multi-lib", "-print-multi-lib", 0}, + {"--print-multi-directory", "-print-multi-directory", 0}, {"--static", "-static", 0}, {"--shared", "-shared", 0}, {"--symbolic", "-symbolic", 0}, @@ -1144,6 +1171,8 @@ set_spec (name, spec) switches_need_spaces = sl->spec; else if (! strcmp (name, "cross_compile")) cross_compile = atoi (sl->spec); + else if (! strcmp (name, "multilib")) + multilib_select = sl->spec; /* Free the old spec */ if (old_spec) free (old_spec); @@ -1269,6 +1298,11 @@ static char *standard_startfile_prefix_2 = "/usr/lib/"; static char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX; static char *tooldir_prefix; +/* Subdirectory to use for locating libraries. Set by + set_multilib_dir based on the compilation options. */ + +static char *multilib_dir; + /* Clear out the vector of arguments (after a command is executed). */ static void @@ -2340,6 +2374,7 @@ process_command (argc, argv) printf ("*signed_char:\n%s\n\n", signed_char_spec); printf ("*predefines:\n%s\n\n", cpp_predefines); printf ("*cross_compile:\n%d\n\n", cross_compile); + printf ("*multilib:\n%s\n\n", multilib_select); exit (0); } @@ -2354,6 +2389,10 @@ process_command (argc, argv) print_file_name = argv[i] + 17; else if (! strncmp (argv[i], "-print-prog-name=", 17)) print_prog_name = argv[i] + 17; + else if (! strcmp (argv[i], "-print-multi-lib")) + print_multi_lib = 1; + else if (! strcmp (argv[i], "-print-multi-directory")) + print_multi_directory = 1; else if (! strcmp (argv[i], "-Xlinker")) { /* Pass the argument of this option to the linker when we link. */ @@ -2597,6 +2636,10 @@ process_command (argc, argv) ; else if (! strncmp (argv[i], "-print-prog-name=", 17)) ; + else if (! strcmp (argv[i], "-print-multi-lib")) + ; + else if (! strcmp (argv[i], "-print-multi-directory")) + ; else if (argv[i][0] == '+' && argv[i][1] == 'e') { /* Compensate for the +e options to the C++ front-end; @@ -2941,6 +2984,45 @@ do_spec_1 (spec, inswitch, soft_matched_part) if (pl->prefix[0] != '/') continue; #endif + /* Try subdirectory if there is one. */ + if (multilib_dir != NULL) + { + if (machine_suffix) + { + if (strlen (pl->prefix) + strlen (machine_suffix) + >= bufsize) + bufsize = (strlen (pl->prefix) + + strlen (machine_suffix)) * 2 + 1; + buffer = (char *) xrealloc (buffer, bufsize); + strcpy (buffer, pl->prefix); + strcat (buffer, machine_suffix); + if (is_directory (buffer, multilib_dir, 1)) + { + do_spec_1 ("-L", 0, NULL_PTR); +#ifdef SPACE_AFTER_L_OPTION + do_spec_1 (" ", 0, NULL_PTR); +#endif + do_spec_1 (buffer, 1, NULL_PTR); + do_spec_1 (multilib_dir, 1, NULL_PTR); + /* Make this a separate argument. */ + do_spec_1 (" ", 0, NULL_PTR); + } + } + if (!pl->require_machine_suffix) + { + if (is_directory (pl->prefix, multilib_dir, 1)) + { + do_spec_1 ("-L", 0, NULL_PTR); +#ifdef SPACE_AFTER_L_OPTION + do_spec_1 (" ", 0, NULL_PTR); +#endif + do_spec_1 (pl->prefix, 1, NULL_PTR); + do_spec_1 (multilib_dir, 1, NULL_PTR); + /* Make this a separate argument. */ + do_spec_1 (" ", 0, NULL_PTR); + } + } + } if (machine_suffix) { if (is_directory (pl->prefix, machine_suffix, 1)) @@ -3836,6 +3918,24 @@ find_file (name) { char *newname; + /* Try multilib_dir if it is defined. */ + if (multilib_dir != NULL) + { + char *try; + + try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2); + strcpy (try, multilib_dir); + strcat (try, "/"); + strcat (try, name); + + newname = find_a_file (&startfile_prefix, try, R_OK); + + /* If we don't find it in the multi library dir, then fall + through and look for it in the normal places. */ + if (newname != NULL) + return newname; + } + newname = find_a_file (&startfile_prefix, name, R_OK); return newname ? newname : name; } @@ -4022,6 +4122,10 @@ main (argc, argv) validate_all_switches (); + /* Now that we have the switches and the specs, set + the subdirectory based on the options. */ + set_multilib_dir (); + /* Warn about any switches that no pass was interested in. */ for (i = 0; i < n_switches; i++) @@ -4043,6 +4147,21 @@ main (argc, argv) exit (0); } + if (print_multi_lib) + { + print_multilib_info (); + exit (0); + } + + if (print_multi_directory) + { + if (multilib_dir == NULL) + printf (".\n"); + else + printf ("%s\n", multilib_dir); + exit (0); + } + if (verbose_flag) { fprintf (stderr, "gcc version %s\n", version_string); @@ -4585,3 +4704,190 @@ validate_switches (start) } } } + +/* Check whether a particular argument was used. */ + +static int +used_arg (p, len) + char *p; + int len; +{ + int i; + + for (i = 0; i < n_switches; i++) + if (! strncmp (switches[i].part1, p, len) + && strlen (switches[i].part1) == len) + return 1; + return 0; +} + +/* Work out the subdirectory to use based on the + options. The format of multilib_select is a list of elements. + Each element is a subdirectory name followed by a list of options + followed by a semicolon. gcc will consider each line in turn. If + none of the options beginning with an exclamation point are + present, and all of the other options are present, that + subdirectory will be used. */ + +static void +set_multilib_dir () +{ + char *p = multilib_select; + int this_path_len; + char *this_path, *this_arg; + int failed; + + while (*p != '\0') + { + /* Ignore newlines. */ + if (*p == '\n') + { + ++p; + continue; + } + + /* Get the initial path. */ + this_path = p; + while (*p != ' ') + { + if (*p == '\0') + abort (); + ++p; + } + this_path_len = p - this_path; + + /* Check the arguments. */ + failed = 0; + ++p; + while (*p != ';') + { + if (*p == '\0') + abort (); + + if (failed) + { + ++p; + continue; + } + + this_arg = p; + while (*p != ' ' && *p != ';') + { + if (*p == '\0') + abort (); + ++p; + } + + if (*this_arg == '!') + failed = used_arg (this_arg + 1, p - (this_arg + 1)); + else + failed = ! used_arg (this_arg, p - this_arg); + + if (*p == ' ') + ++p; + } + + if (! failed) + { + if (this_path_len != 1 + || this_path[0] != '.') + { + multilib_dir = xmalloc (this_path_len + 1); + strncpy (multilib_dir, this_path, this_path_len); + multilib_dir[this_path_len] = '\0'; + } + break; + } + + ++p; + } +} + +/* Print out the multiple library subdirectory selection + information. This prints out a series of lines. Each line looks + like SUBDIRECTORY;@OPTION@OPTION, with as many options as is + required. Only the desired options are printed out, the negative + matches. The options are print without a leading dash. There are + no spaces to make it easy to use the information in the shell. + Each subdirectory is printed only once. This assumes the ordering + generated by the genmultilib script. */ + +static void +print_multilib_info () +{ + char *p = multilib_select; + char *last_path, *this_path; + int last_path_len, skip, use_arg; + + while (*p != '\0') + { + /* Ignore newlines. */ + if (*p == '\n') + { + ++p; + continue; + } + + /* Get the initial path. */ + this_path = p; + while (*p != ' ') + { + if (*p == '\0') + abort (); + ++p; + } + + /* If this is a duplicate, skip it. */ + skip = (p - this_path == last_path_len + && ! strncmp (last_path, this_path, last_path_len)); + + last_path = this_path; + last_path_len = p - this_path; + + if (! skip) + { + char *p1; + + for (p1 = last_path; p1 < p; p1++) + putchar (*p1); + putchar (';'); + } + + ++p; + while (*p != ';') + { + int use_arg; + + if (*p == '\0') + abort (); + + if (skip) + { + ++p; + continue; + } + + use_arg = *p != '!'; + + if (use_arg) + putchar ('@'); + + while (*p != ' ' && *p != ';') + { + if (*p == '\0') + abort (); + if (use_arg) + putchar (*p); + ++p; + } + + if (*p == ' ') + ++p; + } + + if (! skip) + putchar ('\n'); + + ++p; + } +}