aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Evans <dje@gnu.org>1994-06-15 08:04:07 +0000
committerDoug Evans <dje@gnu.org>1994-06-15 08:04:07 +0000
commit60103a34825ddfa2e18d3d01f67d6d162c5dfaf4 (patch)
tree2a87058d4d6392bdd250c97bac38d420eea7cd50
parentf6cdc7ea0f386764375769723f9693d8f9db9355 (diff)
downloadgcc-60103a34825ddfa2e18d3d01f67d6d162c5dfaf4.zip
gcc-60103a34825ddfa2e18d3d01f67d6d162c5dfaf4.tar.gz
gcc-60103a34825ddfa2e18d3d01f67d6d162c5dfaf4.tar.bz2
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
-rw-r--r--gcc/gcc.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 56b99ed..00ffa38 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -45,6 +45,9 @@ compilation is specified by a string called a "spec". */
#endif
#include <stdio.h>
+/* 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;
+ }
+}