diff mbox

New configuration options to enable additional executable/startfile/shared library prefixes

Message ID 20121101211727.GA7077@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Nov. 1, 2012, 9:17 p.m. UTC
I may have submitted this shortly before the Caudren, and it got lost.

This patch adds 4 additional configuration switches, that allow the person
building the compiler to add additional prefixes to search for additional
executables and startfiles.

If the backend has the appropriate tweaks installed, it will also add
additional prefixes to search for the dynamic linker.  At the moment, only the
PowerPC Linux port has the modifications.  It is fairly easy to modify other
targets if desired.

The motivation for this comes from the IBM Advance Toolchain (AT), which runs
on PowerPC Linux 64-bit system running on IBM server class machines (power4
through power7).  AT provides its own version of the standard libraries and its
own dynamic linker.  Unlike a cross compiler environment where you want to use
--sysroot to not reference any of the host libraries, a release compiler like
this wants to be able to use the system libraries and include files if it
doesn't provide for them in the release.

The released version of the AT has the sources modified so that it uses the
pathnames for the release instead of the standard library and executable
pathnames.  When we are doing development, it would be convenient to have the
compilers that we build target the AT directly without having to use the
appropriate linker/include options to use the AT executables, libraries, and
dynamic linker.

I have built compilers without these patches, with the patches but not adding
the configuration options, and with these patches using the configuration
options.  The compilers all bootstrapped.  In running the regression suite
there are two differences when the option is used:

gcc.dg/cproj-fails-with-broken-glibc.c fails on SLES 11SP1, but works fine when
linked with the AT 6.0 libraries, which is expected, since the AT library is
based on a newer baseline thatn Sles 11SP1.

gfortran.dg/bessel_6.f90 fails when using the Advance Toolchain 6.0 libraries,
due to the bessel jn function returning slightly differenct values, which
causes the test to fail.  If I use the Advance Toolchain 5.0 library, it works
fine.  I have entered the bug into AT bugzilla.

Both of these errors show that when the options are used, it does in fact use
the alternative library instead of the system libraries.

I have broken these patches into 2 attachments.  The first attachment
(gcc-power7.patch369c) are the machine independent changes.  The second
attachment (gcc-power7.patch369d) are just the powerpc specific changes.

Are these patches ok to install?

2012-11-01  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* configure.ac (--with-extra-prefix=): Add configure time switches
	to add addition prefix directories for the compiler to search for
	extra executables, startfiles, and directories to add to the list
	of shared library locations.
	(--with-extra-exec-prefix=): Likewise.
	(--with-extra-startfile-prefix=): Likewise.
	(--with-extra-rpath-prefix=): Likewise.
	* configure: Regenerate.

	* doc/install.texi (--with-extra-prefix=): Document new configure
	switches.
	(--with-extra-exec-prefix=): Likewise.
	(--with-extra-startfile-prefix=): Likewise.
	(--with-extra-rpath-prefix=): Likewise.

	* gcc.c (LINK_RPATH_DIRS_SPEC): Add support for configuration time
	additional executable, startfile, and shared library location
	prefixes.  Add %find-dynamic-linker(), %extra-rpath-dirs(),
	%extra-cpu-dirs() as spec functions.
	(LINK_COMMAND_SPEC): Likewise.
	(CONFIGURE_STARTFILE_PREFIX): Likewise.
	(configure_startfile_prefix): Likewise.
	(configure_exec_prefix): Likewise.
	(static_spec_functions): Likewise.
	(IS_STD_DIR): Likewise.
	(config_rpath): Likewise.
	(build_rpath_or_cpu_dirs): Likewise.
	(extra_rpath_dirs_spec_function): Likewsie.
	(extra_cpu_dirs_spec_function): Likewise.
	(find_dynamic_linker_spec_function): Likewise.
	(add_multiple_prefix): New function that is like add_prefix, but
	splits the prefix at PATH_SEPARATOR.
	(process_command): Simplify processing COMPILER_PATH, LPATH, and
	LIBRARY_PATH_ENV environment variables by using the function
	add_multiple_prefix to do the splitting of the separate prefixes.
	Add support for the configuration switch to add new executable,
	startfile, and shared library prefixes.

	* gcc.h (extra_cpu_dirs_spec_function): Add declaration.

	* config.in (CONFIGURE_EXEC_PREFIX): Add defines for the configure
	switches to add executable, startfile, and shared library
	configuration directories.
	(CONFIGURE_STARTFILE_PREFIX): Likewise.
	(CONFIGURE_RPATH_PREFIX): Likewise.

	* config/rs6000/x-rs6000 (driver-rs6000.o): Add $(GCC_H)
	dependency.

	* config/rs6000/linux64.h (GLIBC_DYNAMIC_LINKER32): If
	--with-extra-startfile-prefix or --with-extra-prefix was used, use
	%find-dynamic-linker() to find the dynamic linker in the startfile
	prefixes.
	(GLIBC_DYNAMIC_LINKER64): Likewise.
	(LINUX_EXTRA_STATIC_LIBDIRS64): Likewise.
	(LINK_OS_LINUX_SPEC32): Likewise.
	(LINK_OS_LINUX_SPEC64): Likewise.
	* config/rs6000/rs6000.h (EXTRA_SPEC_FUNCTIONS): Likewise.
	(LOCAL_CPU_EXTR_SPEC_FUNCTIONS): Likewise.
	* config/rs6000/sysv4.h (GLIBC_DYNAMIC_LINKER): Likewise.
	(LINUX_EXTRA_STATIC_LIBDIRS32): Likewise.
	(LINK_OS_LINUX_SPEC): Likewise.
	(rs6000_extra_static_libdirs): Likewise.
	(SUBTARGET_EXTRA_SPEC_FUNCTIONS): Likewise.

	* config/rs6000/driver-rs6000.c (toplevel): Include gcc.h.
	(rs6000_extra_static_libdirs): If we have extra configure
	startfile prefixes, look for a machine specific file as a
	subdirectory in the startfile prefixes if the user used
	-mcpu=<xxx>.

Comments

Gerald Pfeifer Nov. 1, 2012, 11:22 p.m. UTC | #1
On Thu, 1 Nov 2012, Michael Meissner wrote:
> 	* doc/install.texi (--with-extra-prefix=): Document new configure
> 	switches.
> 	(--with-extra-exec-prefix=): Likewise.
> 	(--with-extra-startfile-prefix=): Likewise.
> 	(--with-extra-rpath-prefix=): Likewise.

+On powerpc64-linux systems, the dynamic linker will be searched for in
+the directories specified by the prefixed, that is used instead of the
                                  ^^^^^^^^
+standard system dynamic linker.

Is the use of "prefixed" correct her, or would that be "prefixes"?

+In addition on powerpc64-linux systems, if the user used static

"the user used" comes across a bit oddly.  How about "requests"?

+linking, as well as the @option{-mcpu=} option, the linker will be

Do I understand this correctly that both must hold?  Perhaps say "plus"
to avoid any ambiguity?

+for that particular machine.  If dynamic linking is used, these cpu
+tuned libraries will not be searched, since the dynamic linker will
+load the appropriate cpu tuned library, based on the system that is
+executing the code.

CPU (uppercase) in two cases.

+@item --with-extra-rpath-prefix=@var{prefixes}
+Specify additional directories for finding shared libraries when
+the compiler is run.  Each prefix is separated by the standard path
+sepator (usually colon, @option{:}).  By default no extra prefixes are
+used.  If this option is used, each of the directories if they exist
+will be specified to the linker via the @option{-rpath=} option.

"each of the directories if they exist" is a bit confusing ("each"
versus "they").

Do you mean "each of the directories that exists on the build system
will be..." or something like that?

Gerald
Michael Meissner Nov. 2, 2012, 6 p.m. UTC | #2
On Fri, Nov 02, 2012 at 12:22:07AM +0100, Gerald Pfeifer wrote:
> On Thu, 1 Nov 2012, Michael Meissner wrote:
> > 	* doc/install.texi (--with-extra-prefix=): Document new configure
> > 	switches.
> > 	(--with-extra-exec-prefix=): Likewise.
> > 	(--with-extra-startfile-prefix=): Likewise.
> > 	(--with-extra-rpath-prefix=): Likewise.
> 
> +On powerpc64-linux systems, the dynamic linker will be searched for in
> +the directories specified by the prefixed, that is used instead of the
>                                   ^^^^^^^^
> +standard system dynamic linker.
> 
> Is the use of "prefixed" correct her, or would that be "prefixes"?

You are right that doesn't make sense.  The paragraph should read:

On powerpc64-linux systems, the dynamic linker will be searched for in
the directories specified by the prefixes before falling back to the
standard system dynamic linker which is used if an alternate dynamic
linker could not be found.

> +In addition on powerpc64-linux systems, if the user used static
> 
> "the user used" comes across a bit oddly.  How about "requests"?
> 
> +linking, as well as the @option{-mcpu=} option, the linker will be
> 
> Do I understand this correctly that both must hold?  Perhaps say "plus"
> to avoid any ambiguity?
> 
> +for that particular machine.  If dynamic linking is used, these cpu
> +tuned libraries will not be searched, since the dynamic linker will
> +load the appropriate cpu tuned library, based on the system that is
> +executing the code.

Yes.  The paragraph should read:

In addition on powerpc64-linux systems, if the user used static
linking and the @option{-mcpu=} option at the same time, the linker
will be told to search in appropriate directories for libraries that
are built for that particular machine.  If dynamic linking is used,
these cpu tuned libraries will not be searched, since the dynamic
linker will load the appropriate cpu tuned library, based on the
system that is executing the code.

> CPU (uppercase) in two cases.
> 
> +@item --with-extra-rpath-prefix=@var{prefixes}
> +Specify additional directories for finding shared libraries when
> +the compiler is run.  Each prefix is separated by the standard path
> +sepator (usually colon, @option{:}).  By default no extra prefixes are
> +used.  If this option is used, each of the directories if they exist
> +will be specified to the linker via the @option{-rpath=} option.
> 
> "each of the directories if they exist" is a bit confusing ("each"
> versus "they").
> 
> Do you mean "each of the directories that exists on the build system
> will be..." or something like that?

What the compiler does is search for the directories to exist when the compiler
is run (not when it is built).  If they exist, the linker on powerpc64-linux
will be told via -rpath to add these paths so that when the program is run, the
right libraries are loaded.

For example, if I have AT 6.0 installed on my Sles 11SP1 system, it is
installed in:

	/opt/at6.0

Normally when you build the compiler using the host libraries, the linker gets
passed:

	-dynamic-linker /lib64/ld64.so.1

With the alternatate configuration support, the linker would get passed:

	-rpath=/home/meissner/fsf-install-ppc64/atdirs2/lib64
	-rpath=/opt/at6.0/lib64
	-dynamic-linker /opt/at6.0/lib64/ld64.so.1

where /home/meissner/fsf-install-ppc64/atdirs2/lib64 happens to be the install
directory for the compiler being built, so its libraries override the AT 6
libraries.
David Edelsohn Nov. 3, 2012, 11:01 p.m. UTC | #3
On Thu, Nov 1, 2012 at 5:17 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:

> This patch adds 4 additional configuration switches, that allow the person
> building the compiler to add additional prefixes to search for additional
> executables and startfiles.
>
> If the backend has the appropriate tweaks installed, it will also add
> additional prefixes to search for the dynamic linker.  At the moment, only the
> PowerPC Linux port has the modifications.  It is fairly easy to modify other
> targets if desired.

Why does the documentation refer to powerpc64-linux when the changes
affect all PowerPC Linux and affect the 32 bit dynamic linker search
path?

Thanks, David
Michael Meissner Nov. 5, 2012, 5:27 p.m. UTC | #4
On Sat, Nov 03, 2012 at 07:01:04PM -0400, David Edelsohn wrote:
> On Thu, Nov 1, 2012 at 5:17 PM, Michael Meissner
> <meissner@linux.vnet.ibm.com> wrote:
> 
> > This patch adds 4 additional configuration switches, that allow the person
> > building the compiler to add additional prefixes to search for additional
> > executables and startfiles.
> >
> > If the backend has the appropriate tweaks installed, it will also add
> > additional prefixes to search for the dynamic linker.  At the moment, only the
> > PowerPC Linux port has the modifications.  It is fairly easy to modify other
> > targets if desired.
> 
> Why does the documentation refer to powerpc64-linux when the changes
> affect all PowerPC Linux and affect the 32 bit dynamic linker search
> path?

Yes, obviously I should have included powerpc-linux as well as powerpc64-linux
in the documentation.  Thanks.  If it is approved, I will update the
documentation.
David Edelsohn Nov. 6, 2012, 2:59 p.m. UTC | #5
On Mon, Nov 5, 2012 at 12:27 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:

> Yes, obviously I should have included powerpc-linux as well as powerpc64-linux
> in the documentation.  Thanks.  If it is approved, I will update the
> documentation.

The rs6000 parts of the patch are okay with that change.

Thanks, David
Michael Meissner Dec. 5, 2012, 7:46 p.m. UTC | #6
Other than David approving of the powerpc stuff, and Gerald Pfeifer asking a
question, I didn't get any response for my patch to add new configuration
options to enable additional executable/startfile/shared library prefixes:

http://gcc.gnu.org/ml/gcc-patches/2012-11/msg00144.html

Can I get a global maintainer or driver maintainer to look at it?  Thanks in
advance.
diff mbox

Patch

Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 193063)
+++ gcc/doc/install.texi	(working copy)
@@ -762,6 +762,44 @@  from the full GCC manuals, which are pro
 are derived by an automatic conversion process from parts of the full
 manual.)
 
+@item --with-extra-prefix=@var{prefix}
+Specify an additional prefix for finding executables, libraries, and
+startfiles when the compiler is run.  By default no extra
+prefixes are used.  This option sets the options
+@option{--with-extra-exec-prefix=},
+@option{--with-extra-startfiles-prefix=},
+and @option{--with-extra-rpath-prefix=} if they are not specified.
+
+@item --with-extra-exec-prefix=@var{prefixes}
+Specify additional prefixes for finding executables when the compiler
+is run.  Each prefix is separated by the standard path sepator
+(usually colon, @option{:}).  By default no extra prefixes are used.
+
+@item --with-extra-startfile-prefix=@var{prefixes}
+Specify additional prefixes for finding libraries, and startfiles when
+the compiler is run.  Each prefix is separated by the standard path
+sepator (usually colon, @option{:}).  By default no extra prefixes are
+used.
+
+On powerpc64-linux systems, the dynamic linker will be searched for in
+the directories specified by the prefixed, that is used instead of the
+standard system dynamic linker.
+
+In addition on powerpc64-linux systems, if the user used static
+linking, as well as the @option{-mcpu=} option, the linker will be
+told to search in appropriate directories for libraries that are built
+for that particular machine.  If dynamic linking is used, these cpu
+tuned libraries will not be searched, since the dynamic linker will
+load the appropriate cpu tuned library, based on the system that is
+executing the code.
+
+@item --with-extra-rpath-prefix=@var{prefixes}
+Specify additional directories for finding shared libraries when
+the compiler is run.  Each prefix is separated by the standard path
+sepator (usually colon, @option{:}).  By default no extra prefixes are
+used.  If this option is used, each of the directories if they exist
+will be specified to the linker via the @option{-rpath=} option.
+
 @item --with-gxx-include-dir=@var{dirname}
 Specify
 the installation directory for G++ header files.  The default depends
Index: gcc/configure
===================================================================
--- gcc/configure	(revision 193063)
+++ gcc/configure	(working copy)
@@ -893,6 +893,10 @@  with_multilib_list
 enable_rpath
 with_libiconv_prefix
 enable_sjlj_exceptions
+with_extra_prefix
+with_extra_exec_prefix
+with_extra_startfile_prefix
+with_extra_rpath_prefix
 enable_secureplt
 enable_leading_mingw64_underscores
 enable_cld
@@ -1659,6 +1663,18 @@  Optional Packages:
   --with-gnu-ld           assume the C compiler uses GNU ld default=no
   --with-libiconv-prefix[=DIR]  search for libiconv in DIR/include and DIR/lib
   --without-libiconv-prefix     don't search for libiconv in includedir and libdir
+  --with-extra-prefix={prefixes}
+                          Add extra prefixes to the list of locations to
+                          search for all files
+  --with-extra-exec-prefix={prefixes}
+                          Add extra prefixes to the list of locations to
+                          search for executables
+  --with-extra-startfile-prefix={prefix}
+                          Add extra prefixes to the list of locations to
+                          search for startfiles
+  --with-extra-rpath-prefix={prefixes}
+                          Specify prefixes to pass to the linker via
+                          -rpath=dir to locate shared libraries
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
@@ -11322,6 +11338,78 @@  case "$LIBINTL" in *$LIBICONV*)
 	LIBICONV= ;;
 esac
 
+
+# Check whether --with-extra-prefix was given.
+if test "${with_extra_prefix+set}" = set; then :
+  withval=$with_extra_prefix; EXTRA_PREFIX="$withval"
+else
+  EXTRA_PREFIX=''
+fi
+
+
+
+# Check whether --with-extra-exec-prefix was given.
+if test "${with_extra_exec_prefix+set}" = set; then :
+  withval=$with_extra_exec_prefix; EXTRA_EXEC_PREFIX="$withval"
+else
+  if test x"${EXTRA_PREFIX}" != x; then
+    EXTRA_EXEC_PREFIX="`echo ${EXTRA_PREFIX} | sed 's/:/\\/bin:/g'`/bin"
+  else
+    EXTRA_EXEC_PREFIX=""
+  fi
+fi
+
+
+if test x"${EXTRA_EXEC_PREFIX}" != x; then
+
+cat >>confdefs.h <<_ACEOF
+#define CONFIGURE_EXEC_PREFIX "$EXTRA_EXEC_PREFIX"
+_ACEOF
+
+fi
+
+
+# Check whether --with-extra-startfile-prefix was given.
+if test "${with_extra_startfile_prefix+set}" = set; then :
+  withval=$with_extra_startfile_prefix; EXTRA_STARTFILE_PREFIX="$withval"
+else
+  if test x"${EXTRA_PREFIX}" != x; then
+    EXTRA_STARTFILE_PREFIX="`echo ${EXTRA_PREFIX} | sed 's/:/\\/lib:/g'`/lib"
+  else
+    EXTRA_STARTFILE_PREFIX=""
+  fi
+fi
+
+
+if test x"${EXTRA_STARTFILE_PREFIX}" != x; then
+
+cat >>confdefs.h <<_ACEOF
+#define CONFIGURE_STARTFILE_PREFIX "$EXTRA_STARTFILE_PREFIX"
+_ACEOF
+
+fi
+
+
+# Check whether --with-extra-rpath-prefix was given.
+if test "${with_extra_rpath_prefix+set}" = set; then :
+  withval=$with_extra_rpath_prefix; EXTRA_RPATH_PREFIX="$withval"
+else
+  if test x"${EXTRA_PREFIX}" != x; then
+    EXTRA_RPATH_PREFIX="${prefix}/lib:`echo ${EXTRA_PREFIX} | sed 's/:/\\/lib:/g'`/lib"
+  else
+    EXTRA_RPATH_PREFIX=""
+  fi
+fi
+
+
+if test x"${EXTRA_RPATH_PREFIX}" != x; then
+
+cat >>confdefs.h <<_ACEOF
+#define CONFIGURE_RPATH_PREFIX "$EXTRA_RPATH_PREFIX"
+_ACEOF
+
+fi
+
 # Check whether --enable-secureplt was given.
 if test "${enable_secureplt+set}" = set; then :
   enableval=$enable_secureplt;
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 193063)
+++ gcc/gcc.c	(working copy)
@@ -202,6 +202,8 @@  static int access_check (const char *, i
 static char *find_a_file (const struct path_prefix *, const char *, int, bool);
 static void add_prefix (struct path_prefix *, const char *, const char *,
 			int, int, int);
+static void add_multiple_prefix (struct path_prefix *, const char *,
+				 const char *, int, int, int);
 static void add_sysrooted_prefix (struct path_prefix *, const char *,
 				  const char *, int, int, int);
 static char *skip_whitespace (char *);
@@ -261,12 +263,15 @@  static const char *remove_outfile_spec_f
 static const char *version_compare_spec_function (int, const char **);
 static const char *include_spec_function (int, const char **);
 static const char *find_file_spec_function (int, const char **);
+static const char *find_dynamic_linker_spec_function (int, const char **);
 static const char *find_plugindir_spec_function (int, const char **);
 static const char *print_asm_header_spec_function (int, const char **);
 static const char *compare_debug_dump_opt_spec_function (int, const char **);
 static const char *compare_debug_self_opt_spec_function (int, const char **);
 static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
 static const char *pass_through_libs_spec_func (int, const char **);
+static const char *extra_rpath_dirs_spec_function (int, const char **);
+const char *extra_cpu_dirs_spec_function (int, const char **);
 
 /* The Specs Language
 
@@ -656,6 +661,16 @@  proper position among the other output f
 #endif
 
 
+#ifndef LINK_RPATH_DIRS_SPEC
+#ifdef CONFIGURE_RPATH_PREFIX
+/* Add extra -rpath= options if configured.  */
+#define LINK_RPATH_DIRS_SPEC \
+  "%{!nostdlib:%{!nodefaultlibs:%{!static: %:extra-rpath-dirs()}}}"
+#else
+#define LINK_RPATH_DIRS_SPEC
+#endif
+#endif
+
 /* -u* was put back because both BSD and SysV seem to support it.  */
 /* %{static:} simply prevents an error message if the target machine
    doesn't handle -static.  */
@@ -669,6 +684,7 @@  proper position among the other output f
 #define LINK_COMMAND_SPEC "\
 %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
     %(linker) " \
+    LINK_RPATH_DIRS_SPEC \
     LINK_PLUGIN_SPEC \
     "%{flto|flto=*:%<fcompare-debug*} \
     %{flto} %{flto=*} %l " LINK_PIE_SPEC \
@@ -1102,6 +1118,14 @@  static const char *gcc_libexec_prefix;
 #define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
 #endif
 
+/* Additional directories added at configure time.  */
+#ifndef CONFIGURE_STARTFILE_PREFIX
+#define CONFIGURE_STARTFILE_PREFIX ""
+#endif
+#ifndef CONFIGURE_EXEC_PREFIX
+#define CONFIGURE_EXEC_PREFIX ""
+#endif
+
 #ifdef CROSS_DIRECTORY_STRUCTURE  /* Don't use these prefixes for a cross compiler.  */
 #undef MD_EXEC_PREFIX
 #undef MD_STARTFILE_PREFIX
@@ -1140,6 +1164,10 @@  static const char *const standard_startf
   = STANDARD_STARTFILE_PREFIX_1;
 static const char *const standard_startfile_prefix_2
   = STANDARD_STARTFILE_PREFIX_2;
+static const char *const configure_startfile_prefix
+  = CONFIGURE_STARTFILE_PREFIX;
+static const char *const configure_exec_prefix
+  = CONFIGURE_EXEC_PREFIX;
 
 /* A relative path to be used in finding the location of tools
    relative to the driver.  */
@@ -1256,12 +1284,15 @@  static const struct spec_function static
   { "version-compare",		version_compare_spec_function },
   { "include",			include_spec_function },
   { "find-file",		find_file_spec_function },
+  { "find-dynamic-linker",	find_dynamic_linker_spec_function },
   { "find-plugindir",		find_plugindir_spec_function },
   { "print-asm-header",		print_asm_header_spec_function },
   { "compare-debug-dump-opt",	compare_debug_dump_opt_spec_function },
   { "compare-debug-self-opt",	compare_debug_self_opt_spec_function },
   { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
   { "pass-through-libs",	pass_through_libs_spec_func },
+  { "extra-rpath-dirs",		extra_rpath_dirs_spec_function },
+  { "extra-cpu-dirs",		extra_cpu_dirs_spec_function },
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -2444,6 +2475,44 @@  add_prefix (struct path_prefix *pprefix,
   (*prev) = pl;
 }
 
+/* Same as add_prefix, but split the prefix at each PATH_SEPARATOR.  */
+static void
+add_multiple_prefix (struct path_prefix *pprefix, const char *prefix,
+		     const char *component,
+		     /* enum prefix_priority */ int priority,
+		     int require_machine_suffix, int os_multilib)
+{
+  const char *startp, *endp;
+  char *nstore = (char *) alloca (strlen (prefix) + 3);
+
+  startp = endp = prefix;
+  while (1)
+    {
+      if (*endp == PATH_SEPARATOR || *endp == 0)
+	{
+	  strncpy (nstore, startp, endp - startp);
+	  if (endp == startp)
+	    strcpy (nstore, concat (".", dir_separator_str, NULL));
+	  else if (!IS_DIR_SEPARATOR (endp[-1]))
+	    {
+	      nstore[endp - startp] = DIR_SEPARATOR;
+	      nstore[endp - startp + 1] = 0;
+	    }
+	  else
+	    nstore[endp - startp] = 0;
+	  add_prefix (pprefix, nstore, component, priority,
+		      require_machine_suffix, os_multilib);
+	  if (*endp == 0)
+	    break;
+	  endp = startp = endp + 1;
+	}
+      else
+	endp++;
+    }
+
+  return;
+}
+
 /* Same as add_prefix, but prepending target_system_root to prefix.  */
 /* The target_system_root prefix has been relocated by gcc_exec_prefix.  */
 static void
@@ -3691,101 +3760,22 @@  process_command (unsigned int decoded_op
   temp = getenv ("COMPILER_PATH");
   if (temp)
     {
-      const char *startp, *endp;
-      char *nstore = (char *) alloca (strlen (temp) + 3);
-
-      startp = endp = temp;
-      while (1)
-	{
-	  if (*endp == PATH_SEPARATOR || *endp == 0)
-	    {
-	      strncpy (nstore, startp, endp - startp);
-	      if (endp == startp)
-		strcpy (nstore, concat (".", dir_separator_str, NULL));
-	      else if (!IS_DIR_SEPARATOR (endp[-1]))
-		{
-		  nstore[endp - startp] = DIR_SEPARATOR;
-		  nstore[endp - startp + 1] = 0;
-		}
-	      else
-		nstore[endp - startp] = 0;
-	      add_prefix (&exec_prefixes, nstore, 0,
-			  PREFIX_PRIORITY_LAST, 0, 0);
-	      add_prefix (&include_prefixes, nstore, 0,
-			  PREFIX_PRIORITY_LAST, 0, 0);
-	      if (*endp == 0)
-		break;
-	      endp = startp = endp + 1;
-	    }
-	  else
-	    endp++;
-	}
+      add_multiple_prefix (&exec_prefixes, temp, 0,
+			   PREFIX_PRIORITY_LAST, 0, 0);
+      add_multiple_prefix (&include_prefixes, temp, 0,
+			   PREFIX_PRIORITY_LAST, 0, 0);
     }
 
   temp = getenv (LIBRARY_PATH_ENV);
   if (temp && *cross_compile == '0')
-    {
-      const char *startp, *endp;
-      char *nstore = (char *) alloca (strlen (temp) + 3);
-
-      startp = endp = temp;
-      while (1)
-	{
-	  if (*endp == PATH_SEPARATOR || *endp == 0)
-	    {
-	      strncpy (nstore, startp, endp - startp);
-	      if (endp == startp)
-		strcpy (nstore, concat (".", dir_separator_str, NULL));
-	      else if (!IS_DIR_SEPARATOR (endp[-1]))
-		{
-		  nstore[endp - startp] = DIR_SEPARATOR;
-		  nstore[endp - startp + 1] = 0;
-		}
-	      else
-		nstore[endp - startp] = 0;
-	      add_prefix (&startfile_prefixes, nstore, NULL,
-			  PREFIX_PRIORITY_LAST, 0, 1);
-	      if (*endp == 0)
-		break;
-	      endp = startp = endp + 1;
-	    }
-	  else
-	    endp++;
-	}
-    }
+    add_multiple_prefix (&startfile_prefixes, temp, NULL,
+			 PREFIX_PRIORITY_LAST, 0, 1);
 
   /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
   temp = getenv ("LPATH");
   if (temp && *cross_compile == '0')
-    {
-      const char *startp, *endp;
-      char *nstore = (char *) alloca (strlen (temp) + 3);
-
-      startp = endp = temp;
-      while (1)
-	{
-	  if (*endp == PATH_SEPARATOR || *endp == 0)
-	    {
-	      strncpy (nstore, startp, endp - startp);
-	      if (endp == startp)
-		strcpy (nstore, concat (".", dir_separator_str, NULL));
-	      else if (!IS_DIR_SEPARATOR (endp[-1]))
-		{
-		  nstore[endp - startp] = DIR_SEPARATOR;
-		  nstore[endp - startp + 1] = 0;
-		}
-	      else
-		nstore[endp - startp] = 0;
-	      add_prefix (&startfile_prefixes, nstore, NULL,
-			  PREFIX_PRIORITY_LAST, 0, 1);
-	      if (*endp == 0)
-		break;
-	      endp = startp = endp + 1;
-	    }
-	  else
-	    endp++;
-	}
-    }
+    add_multiple_prefix (&startfile_prefixes, temp, NULL,
+			 PREFIX_PRIORITY_LAST, 0, 1);
 
   /* Process the options and store input files and switches in their
      vectors.  */
@@ -3963,6 +3953,16 @@  process_command (unsigned int decoded_op
     }
 #endif
 
+  /* Add prefixes specified by configure's --with-prefix.  */
+  if (*configure_exec_prefix)
+    add_multiple_prefix (&exec_prefixes, configure_exec_prefix, "GCC",
+			 PREFIX_PRIORITY_LAST, 0, 0);
+
+
+  if (*configure_startfile_prefix)
+    add_multiple_prefix (&startfile_prefixes, configure_startfile_prefix,
+			 "GCC", PREFIX_PRIORITY_LAST, 0, 1);
+
   /* More prefixes are enabled in main, after we read the specs file
      and determine whether this is cross-compilation or not.  */
 
@@ -8121,7 +8121,6 @@  find_file_spec_function (int argc, const
   return file;
 }
 
-
 /* %:find-plugindir spec function.  This function replaces its argument
     by the -iplugindir=<dir> option.  `dir' is found through find_file, that
     is the -print-file-name gcc program option. */
@@ -8380,3 +8379,208 @@  pass_through_libs_spec_func (int argc, c
     }
   return prepended;
 }
+
+#define IS_STD_DIR(PATH,STD) (strncmp (PATH, STD, sizeof (STD)-1) == 0)
+
+#ifdef CONFIGURE_RPATH_PREFIX
+
+static const char config_rpath[] = CONFIGURE_RPATH_PREFIX;
+
+/* Common code for extra_rpath_dirs_spec_function and
+   extra_cpu_dirs_spec_function to build up a list of -rpath=<dir> or -L<dir>
+   options, based on the extra rpath directories that were configured in.  */
+
+static char *
+build_rpath_or_cpu_dirs (const char *rpath_dirs,
+			 const char *prefix,
+			 const char *subdir)
+{
+  char *ret = NULL;
+  char *tmpstr, *endp, *prev_dir;
+  size_t rpath_len = strlen (rpath_dirs);
+  size_t subdir_len = (subdir) ? strlen (subdir) : 0;
+  size_t mlib_len = (multilib_os_dir) ? strlen (multilib_os_dir) : 0;
+  bool mlib_updir;
+  size_t i;
+
+  mlib_updir = (DIR_SEPARATOR == '/'
+		&& mlib_len > sizeof ("../") - 1
+		&& multilib_os_dir[0] == '.'
+		&& multilib_os_dir[1] == '.'
+		&& multilib_os_dir[2] == '/');
+
+  endp = tmpstr = XALLOCAVEC (char, rpath_len + subdir_len + mlib_len + 4);
+  prev_dir = NULL;
+  for (i = 0; i <= rpath_len; i++)
+    {
+      int ch = rpath_dirs[i];
+      if (ch != PATH_SEPARATOR && ch != '\0')
+	{
+	  *endp++ = ch;
+	  if (ch == DIR_SEPARATOR)
+	    prev_dir = endp;
+	}
+      else if (endp > tmpstr)
+	{
+	  /* Add current multlib directory.  Convert <stuff>/lib/../lib64 into
+	     <stuff>/lib64.  */
+	  if (mlib_len > 0)
+	    {
+	      if (mlib_updir && prev_dir)
+		{
+		  memcpy (prev_dir, multilib_os_dir + 3, mlib_len - 3);
+		  endp = prev_dir + mlib_len - 3;
+		}
+	      else
+		{
+		  *endp = DIR_SEPARATOR;
+		  memcpy (endp+1, multilib_os_dir, mlib_len);
+		  endp += mlib_len + 1;
+		}
+	    }
+
+	  /* Look for machine specific subdir?  */
+	  if (subdir)
+	    {
+	      *endp = DIR_SEPARATOR;
+	      memcpy (endp+1, subdir, subdir_len);
+	      endp += subdir_len + 1;
+	    }
+
+	  endp[0] = DIR_SEPARATOR;
+	  endp[1] = '.';
+	  endp[2] = '\0';
+
+	  if (is_directory (tmpstr, false))
+	    {
+	      *endp = '\0';
+	      if (ret)
+		ret = reconcat (ret, ret, " ", prefix, tmpstr, NULL);
+	      else
+		ret = concat (prefix, tmpstr, NULL);
+	    }
+
+	  endp = tmpstr;
+	}
+    }
+
+  return ret;
+}
+
+/* %:extra-rpath-dirs spec function.  If we have alternate rpath directories
+    (install lib directory + alternate startfile prefix directories), build a
+    string with all of the directories that are found with appropriate -rpath
+    options for the linker.  If the LD_RUN_PATH environment variable is
+    specified, include this into the -rpath arguments, since LD_RUN_PATH is
+    only used if -rpath is not specified.  */
+
+static const char *
+extra_rpath_dirs_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED)
+{
+  static const char path_sep[2] = { PATH_SEPARATOR, '\0' };
+  const char *ld_run_path = getenv ("LD_RUN_PATH");
+  const char *ret;
+
+  if (argc != 0)
+    abort ();
+
+  if (ld_run_path)
+    {
+      char *new_rpath = concat (config_rpath, path_sep, ld_run_path, NULL);
+      ret = build_rpath_or_cpu_dirs (new_rpath, "-rpath=", NULL);
+      free (new_rpath);
+    }
+  else
+    ret = build_rpath_or_cpu_dirs (config_rpath, "-rpath=", NULL);
+
+  return ret;
+}
+
+/* %:extra-cpu-dirs spec function.  If we have alternate rpath directories,
+    search them to see if there are subdirectories that hold the static
+    libraries built for a particular machines, and return appropriate -L<dir>
+    to those directories.  */
+
+const char *
+extra_cpu_dirs_spec_function (int argc, const char **argv)
+{
+  if (argc != 1)
+    abort ();
+
+  return build_rpath_or_cpu_dirs (config_rpath, "-L", argv[0]);
+}
+
+/* %:find-dynamic-linker spec function.  Find the dynamic linker if we have
+    extra search paths configured.  */
+
+static const char *
+find_dynamic_linker_spec_function (int argc, const char **argv)
+{
+  const char *file;
+  char *tmpstr;
+  char *endp;
+  char *prev_dir;
+  size_t len;
+  size_t i;
+  int ch;
+
+  if (argc < 1)
+    abort ();
+
+  file = argv[0];
+  len = strlen (file);
+  gcc_assert (file[0] == DIR_SEPARATOR);
+
+  endp = tmpstr = XALLOCAVEC (char, ARRAY_SIZE (config_rpath) + len + 1);
+  prev_dir = NULL;
+  for (i = 0; i <= ARRAY_SIZE (config_rpath); i++)
+    {
+      ch = config_rpath[i];
+      if (ch != PATH_SEPARATOR && ch != '\0')
+	{
+	  if (ch == DIR_SEPARATOR)
+	    prev_dir = endp;
+
+	  *endp++ = ch;
+	}
+      else if (endp > tmpstr)
+	{
+	  *endp = '\0';
+	  if (prev_dir && strncmp (prev_dir, "/lib", sizeof ("/lib")-1) == 0)
+	    endp = prev_dir;
+	  memcpy (endp, file, len);
+	  endp[len] = '\0';
+	  if (access (tmpstr, X_OK) == 0)
+	    return xstrdup (tmpstr);
+
+	  endp = tmpstr;
+	}
+    }
+
+  return xstrdup (file);
+}
+
+#else
+const char *
+extra_rpath_dirs_spec_function (int argc ATTRIBUTE_UNUSED,
+				const char **argv ATTRIBUTE_UNUSED)
+{
+  return NULL;
+}
+
+const char *
+extra_cpu_dirs_spec_function (int argc ATTRIBUTE_UNUSED,
+			      const char **argv ATTRIBUTE_UNUSED)
+{
+  return NULL;
+}
+
+static const char *
+find_dynamic_linker_spec_function (int argc, const char **argv)
+{
+  if (argc != 1)
+    abort ();
+
+  return xstrdup (argv[0]);
+}
+#endif
Index: gcc/gcc.h
===================================================================
--- gcc/gcc.h	(revision 193063)
+++ gcc/gcc.h	(working copy)
@@ -37,6 +37,7 @@  extern int do_spec (const char *);
 extern void record_temp_file (const char *, int, int);
 extern void pfatal_with_name (const char *) ATTRIBUTE_NORETURN;
 extern void set_input (const char *);
+extern const char *extra_cpu_dirs_spec_function (int, const char **);
 
 /* Spec files linked with gcc.c must provide definitions for these.  */
 
Index: gcc/config.in
===================================================================
--- gcc/config.in	(revision 193063)
+++ gcc/config.in	(working copy)
@@ -2035,3 +2035,20 @@ 
 #undef vfork
 #endif
 
+
+/* Define extra executable prefixes at configure time.  */
+#ifndef USED_FOR_TARGET
+#undef CONFIGURE_EXEC_PREFIX
+#endif
+
+
+/* Define extra startfile prefixes at configure time.  */
+#ifndef USED_FOR_TARGET
+#undef CONFIGURE_STARTFILE_PREFIX
+#endif
+
+
+/* Define extra rpath prefixes at configure time.  */
+#ifndef USED_FOR_TARGET
+#undef CONFIGURE_RPATH_PREFIX
+#endif
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 193063)
+++ gcc/configure.ac	(working copy)
@@ -1584,6 +1584,57 @@  case "$LIBINTL" in *$LIBICONV*)
 	LIBICONV= ;;
 esac
 
+AC_ARG_WITH([extra-prefix],
+[AC_HELP_STRING([--with-extra-prefix={prefixes}],
+ [Add extra prefixes to the list of locations to search for all files])],
+ [EXTRA_PREFIX="$withval"],
+ [EXTRA_PREFIX=''])
+
+AC_ARG_WITH([extra-exec-prefix],
+[AC_HELP_STRING([--with-extra-exec-prefix={prefixes}],
+ [Add extra prefixes to the list of locations to search for executables])],
+ [EXTRA_EXEC_PREFIX="$withval"],
+ [if test x"${EXTRA_PREFIX}" != x; then
+    EXTRA_EXEC_PREFIX="`echo ${EXTRA_PREFIX} | sed 's/:/\\/bin:/g'`/bin"
+  else
+    EXTRA_EXEC_PREFIX=""
+  fi])
+
+if test x"${EXTRA_EXEC_PREFIX}" != x; then
+  AC_DEFINE_UNQUOTED(CONFIGURE_EXEC_PREFIX, "$EXTRA_EXEC_PREFIX",
+		     [Extra executable prefixes])
+fi
+
+AC_ARG_WITH([extra-startfile-prefix],
+[AC_HELP_STRING([--with-extra-startfile-prefix={prefix}],
+ [Add extra prefixes to the list of locations to search for startfiles])],
+ [EXTRA_STARTFILE_PREFIX="$withval"],
+ [if test x"${EXTRA_PREFIX}" != x; then
+    EXTRA_STARTFILE_PREFIX="`echo ${EXTRA_PREFIX} | sed 's/:/\\/lib:/g'`/lib"
+  else
+    EXTRA_STARTFILE_PREFIX=""
+  fi])
+
+if test x"${EXTRA_STARTFILE_PREFIX}" != x; then
+  AC_DEFINE_UNQUOTED(CONFIGURE_STARTFILE_PREFIX, "$EXTRA_STARTFILE_PREFIX",
+		     [Extra startfile prefix])
+fi
+
+AC_ARG_WITH([extra-rpath-prefix],
+[AC_HELP_STRING([--with-extra-rpath-prefix={prefixes}],
+ [Specify prefixes to pass to the linker via -rpath=dir to locate shared libraries])],
+ [EXTRA_RPATH_PREFIX="$withval"],
+ [if test x"${EXTRA_PREFIX}" != x; then
+    EXTRA_RPATH_PREFIX="${prefix}/lib:`echo ${EXTRA_PREFIX} | sed 's/:/\\/lib:/g'`/lib"
+  else
+    EXTRA_RPATH_PREFIX=""
+  fi])
+
+if test x"${EXTRA_RPATH_PREFIX}" != x; then
+  AC_DEFINE_UNQUOTED(CONFIGURE_RPATH_PREFIX, "$EXTRA_RPATH_PREFIX",
+		     [Extra rpath prefix])
+fi
+
 AC_ARG_ENABLE(secureplt,
 [AS_HELP_STRING([--enable-secureplt],
 		[enable -msecure-plt by default for PowerPC])],