diff mbox

support for multiarch systems

Message ID 4FA9BC73.3080009@ubuntu.com
State New
Headers show

Commit Message

Matthias Klose May 9, 2012, 12:38 a.m. UTC
On 08.05.2012 15:20, Joseph S. Myers wrote:
> On Tue, 8 May 2012, Matthias Klose wrote:
> 
>> On 20.08.2011 21:51, Matthias Klose wrote:
>>> Multiarch [1] is the term being used to refer to the capability of a system to
>>> install and run applications of multiple different binary targets on the same
>>> system.
>>
>> please find attached an updated for the trunk (2012-05-08). The multiarch
>> triplets are now defined in the Debian Wiki [1], and progress is made to get the
>> triplet definitions into Debian Policy [2].
> 
> This still seems to suffer in some cases the problem of previous versions 
> that it does not ensure triplets are never used for non-matching ABIs.  
> For example, a compiler for powerpc-linux-gnu can be configured 
> --with-float=soft but this patch will still use powerpc-linux-gnu as the 
> multiarch triplet.
> 
> For MIPS, I see you allowed for soft-float in setting the triplets - but 
> the specification you point to doesn't mention the soft-float triplets.  
> Likewise you allowed for powerpc-linux-gnuspe being e500v1 or e500v2 but 
> haven't documented the e500v1 triplet.  Likewise for big-endian ARM.
> 
> I again suggest starting with a patch that does just one architecture - 
> but makes sure to cover all the ABIs applicable to that architecture.  
> For example, you could start with a patch for x86 (indeed, just x86 
> GNU/Linux) - and assign a multiarch triplet for x32 even if you're not 
> building an x32 distribution with multiarch.  Then, once the generic 
> support has been reviewed by build system maintainers, and the x86 support 
> by x86 maintainers and people familiar with all the applicable x86 ABIs, 
> send patches for each other architecture (or architecture/OS combination), 
> and the relevant architecture experts can review them to make sure the 
> relevant ABIs are properly distinguished.

ok, the attached patch includes just the support for the x86 targets, including
the kfreebsd and the hurd systems. The x32 multiarch tuple isn't yet defined, so
I'd like to keep it out of the first version.

  Matthias
gcc/

2012-05-08  Matthias Klose  <doko@ubuntu.com>

	* doc/invoke.texi: Document -print-multiarch.
	* doc/install.texi: Document --enable-multiarch.
	* doc/fragments.texi: Document MULTILIB_OSDIRNAMES, MULTIARCH_DIRNAME.
	* configure.ac: Add --enable-multiarch option.
	* configure.in: Regenerate.
	* Makefile.in (s-mlib): Pass MULTIARCH_DIRNAME to genmultilib.
	enable_multiarch, with_float: New macros.
	if_multiarch: New macro, define in terms of enable_multiarch.
	* genmultilib: Add new argument for the multiarch name.
	* gcc.c (multiarch_dir): Define.
	(for_each_path): Search for multiarch suffixes.
	(driver_handle_option): Handle multiarch option.
	(do_spec_1): Pass -imultiarch if defined.
	(main): Print multiarch.
	(set_multilib_dir): Separate multilib and multiarch names
	from multilib_select.
	(print_multilib_info): Ignore multiarch names in multilib_select.
	* incpath.c (add_standard_paths): Search the multiarch include dirs.
	* cppdeault.h (default_include): Document multiarch in multilib
	member.
	* cppdefault.c: [LOCAL_INCLUDE_DIR, STANDARD_INCLUDE_DIR] Add an
        include directory for multiarch directories.
	* common.opt: New options --print-multiarch and -imultilib.
	* config.gcc: Add tmake fragments to tmake_file ( i386/t-kfreebsd
	for i[34567]86-*-kfreebsd*-gnu and x86_64-*-kfreebsd*-gnu, i386/t-gnu
	for i[34567]86-*-gnu*).
	* config/i386/t-kfreebsd: Add multiarch names in MULTILIB_OSDIRNAMES,
	Define MULTIARCH_DIRNAME.
	* config/i386/t-linux64: Likewise.
	* config/i386/t-gnu: Likewise:
	* config/i386/t-linux: Likewise.

Comments

Paolo Bonzini May 9, 2012, 1:37 p.m. UTC | #1
Il 09/05/2012 02:38, Matthias Klose ha scritto:
> Index: gcc/doc/invoke.texi
> ===================================================================
> --- gcc/doc/invoke.texi	(revision 187271)
> +++ gcc/doc/invoke.texi	(working copy)
> @@ -6110,6 +6110,11 @@
>  @file{../lib32}, or if OS libraries are present in @file{lib/@var{subdir}}
>  subdirectories it prints e.g.@: @file{amd64}, @file{sparcv9} or @file{ev6}.
>  
> +@item -print-multiarch
> +@opindex print-multiarch
> +Print the path to OS libraries for the selected multiarch,
> +relative to some @file{lib} subdirectory.
> +
>  @item -print-prog-name=@var{program}
>  @opindex print-prog-name
>  Like @option{-print-file-name}, but searches for a program such as @samp{cpp}.

So -print-multiarch is like --print-multi-os-directory?  What is the
difference, and where is it docuemnted?  Should it fail if multiarch
support is not compiled in?

Paolo
Matthias Klose May 9, 2012, 3:34 p.m. UTC | #2
On 09.05.2012 15:37, Paolo Bonzini wrote:
> Il 09/05/2012 02:38, Matthias Klose ha scritto:
>> Index: gcc/doc/invoke.texi
>> ===================================================================
>> --- gcc/doc/invoke.texi	(revision 187271)
>> +++ gcc/doc/invoke.texi	(working copy)
>> @@ -6110,6 +6110,11 @@
>>  @file{../lib32}, or if OS libraries are present in @file{lib/@var{subdir}}
>>  subdirectories it prints e.g.@: @file{amd64}, @file{sparcv9} or @file{ev6}.
>>  
>> +@item -print-multiarch
>> +@opindex print-multiarch
>> +Print the path to OS libraries for the selected multiarch,
>> +relative to some @file{lib} subdirectory.
>> +
>>  @item -print-prog-name=@var{program}
>>  @opindex print-prog-name
>>  Like @option{-print-file-name}, but searches for a program such as @samp{cpp}.
> 
> So -print-multiarch is like --print-multi-os-directory?

the former prints the part before the `:' in the MULTILIB_OSDIRNAMES, the latter
the part after the `':', e.g. ../lib32 and i386-linux-gnu.

> What is the difference, and where is it documented?

Not sure how it should be further documented.

> Should it fail if multiarch support is not compiled in?

All the -print options always succeed. I would prefer if it just prints the
empty string if it is not configured (as it does now).

  Matthias
Paolo Bonzini May 9, 2012, 4:29 p.m. UTC | #3
Il 09/05/2012 17:34, Matthias Klose ha scritto:
>> > So -print-multiarch is like --print-multi-os-directory?
> the former prints the part before the `:' in the MULTILIB_OSDIRNAMES, the latter
> the part after the `':', e.g. ../lib32 and i386-linux-gnu.

Yes, of course.

>> > What is the difference, and where is it documented?
> Not sure how it should be further documented.

No idea, it is a new concept and people need to understand how it
relates to multilibbing for example, what shortcomings are addressed etc.

I went through the Debian pages (only cursorily, I admit) and I found
nothing of this.

Another question I have is related to usage of the option.  Are you
supposed to look for libraries in the multilib directories too if the
compiler is multiarch-enabled?  Or only in /lib/i386-linux-gnu?  Which
one takes priority, multiarch or multiosdir?

From the patch I can guess the intended search path is
/lib/MULTIARCH:/lib/MULTIOSDIR, but I'm not entirely sure about that and
it needs documentation.

>> > Should it fail if multiarch support is not compiled in?
> All the -print options always succeed. I would prefer if it just prints the
> empty string if it is not configured (as it does now).

Will the empty string be a valid output for a multiarch-enabled
compiler?  For example "gcc --print-multi-os-directory" and "gcc
--print-multi-directory" on a bi-arch x86-64 compiler will never print
the empty string.  Again, I guess the answer is no but I'm not sure.

If the answer is no, returning the empty string is fine.

If the answer is yes, and assuming the search path is
/lib/MULTIARCH:/lib/MULTIOSDIR, then programs need to know whether they
need to omit the /lib/MULTIARCH component of the search path.  A failure
status code is then required.

Paolo
Matthias Klose May 9, 2012, 5:19 p.m. UTC | #4
On 09.05.2012 18:29, Paolo Bonzini wrote:
> Il 09/05/2012 17:34, Matthias Klose ha scritto:
>>>> So -print-multiarch is like --print-multi-os-directory?
>> the former prints the part before the `:' in the MULTILIB_OSDIRNAMES, the latter
>> the part after the `':', e.g. ../lib32 and i386-linux-gnu.
> 
> Yes, of course.
> 
>>>> What is the difference, and where is it documented?
>> Not sure how it should be further documented.
> 
> No idea, it is a new concept and people need to understand how it
> relates to multilibbing for example, what shortcomings are addressed etc.
> 
> I went through the Debian pages (only cursorily, I admit) and I found
> nothing of this.

these are referenced from the http://wiki.debian.org/Multiarch/Tuples
https://wiki.ubuntu.com/MultiarchSpec#Filesystem_layout
http://err.no/debian/amd64-multiarch-3

http://wiki.debian.org/Multiarch/TheCaseForMultiarch describes use cases for
multiarch, and why Debian thinks that the existing approaches are not sufficient
(having name collisions for different architectures or ad hoc names for new
architectures like libx32).  That may be contentious within the Linux community,
but I would like to avoid this kind of discussion here.

> Another question I have is related to usage of the option.  Are you
> supposed to look for libraries in the multilib directories too if the
> compiler is multiarch-enabled?

Debian/Ubuntu always use /lib for the default MULTIOSDIR, and this needs to be
looked up in the future too. The use of locations like ../lib32 will be faded
out over time, but I don't see any harm not to have looked up as well.

> Or only in /lib/i386-linux-gnu?  Which
> one takes priority, multiarch or multiosdir?
> 
> From the patch I can guess the intended search path is
> /lib/MULTIARCH:/lib/MULTIOSDIR, but I'm not entirely sure about that and
> it needs documentation.

yes, this is the intended search path. I assume such kind of documentation
shouldn't go into invoke.texi.

>>>> Should it fail if multiarch support is not compiled in?
>> All the -print options always succeed. I would prefer if it just prints the
>> empty string if it is not configured (as it does now).
> 
> Will the empty string be a valid output for a multiarch-enabled
> compiler?  For example "gcc --print-multi-os-directory" and "gcc
> --print-multi-directory" on a bi-arch x86-64 compiler will never print
> the empty string.  Again, I guess the answer is no but I'm not sure.
> 
> If the answer is no, returning the empty string is fine.

The answer is no. If multiarch is enabled, then the string is always non-empty
and should return a multiarch tuple as defined in
http://wiki.debian.org/Multiarch/Tuples. Anything else should be considered an
error.

> If the answer is yes, and assuming the search path is
> /lib/MULTIARCH:/lib/MULTIOSDIR, then programs need to know whether they
> need to omit the /lib/MULTIARCH component of the search path.

Unrelated, but why would programs hard code this path and not use something like
this?

gcc -v -E - </dev/null 2>&1 | grep ^LIBRARY_PATH

  Matthias
Paolo Bonzini May 10, 2012, 6:42 a.m. UTC | #5
Il 09/05/2012 19:19, Matthias Klose ha scritto:
> these are referenced from the http://wiki.debian.org/Multiarch/Tuples
> https://wiki.ubuntu.com/MultiarchSpec#Filesystem_layout
> http://err.no/debian/amd64-multiarch-3
> 
> http://wiki.debian.org/Multiarch/TheCaseForMultiarch describes use cases for
> multiarch, and why Debian thinks that the existing approaches are not sufficient
> (having name collisions for different architectures or ad hoc names for new
> architectures like libx32).  That may be contentious within the Linux community,
> but I would like to avoid this kind of discussion here.

I don't care about contentiousness, I just would like this to be
documented somewhere (for example in the internals manual where
MULTILIB_* is documented too).

Paolo
Thomas Schwinge May 19, 2012, 4:05 p.m. UTC | #6
Hi!

On Wed, 09 May 2012 02:38:11 +0200, Matthias Klose <doko@ubuntu.com> wrote:
> ok, the attached patch includes just the support for the x86 targets, including
> the kfreebsd and the hurd systems. The x32 multiarch tuple isn't yet defined, so
> I'd like to keep it out of the first version.

I will test this on/for GNU/Hurd next week (hopefully), but here are
already two comments.

> Index: gcc/Makefile.in
> ===================================================================
> --- gcc/Makefile.in	(revision 187271)
> +++ gcc/Makefile.in	(working copy)
> @@ -350,6 +350,17 @@
>  
>  enable_plugin = @enable_plugin@
>  
> +# Multiarch support
> +enable_multiarch = @enable_multiarch@
> +with_float = @with_float@
> +ifeq ($(enable_multiarch),yes)
> +  if_multiarch = $(1)
> +else ifeq ($(enable_multiarch),auto-detect)
> +  if_multiarch = $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib/*/crti.o),$(1))
> +else
> +  if_multiarch =
> +endif

The auto-detection won't work for cases where native_system_header_dir
(as per config.gcc; or command-line argument) is not /usr/include.

> Index: gcc/config.gcc
> ===================================================================
> --- gcc/config.gcc	(revision 187271)
> +++ gcc/config.gcc	(working copy)
> @@ -3472,10 +3476,14 @@
>  
>  	i[34567]86-*-darwin* | x86_64-*-darwin*)
>  		;;
> -	i[34567]86-*-linux* | x86_64-*-linux* | \
> -	  i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu | \
> -	  i[34567]86-*-gnu*)
> +	i[34567]86-*-linux* | x86_64-*-linux*)
>  		;;
> +	i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
> +		tmake_file="${tmake_file} i386/t-linux i386/t-kfreebsd"
> +		;;
> +	i[34567]86-*-gnu*)
> +		tmake_file="${tmake_file} i386/t-linux i386/t-gnu"
> +		;;

> Index: gcc/config/i386/t-linux
> ===================================================================
> --- gcc/config/i386/t-linux	(revision 0)
> +++ gcc/config/i386/t-linux	(revision 0)
> @@ -0,0 +1 @@
> +MULTIARCH_DIRNAME = $(call if_multiarch,i386-linux-gnu)
> Index: gcc/config/i386/t-gnu
> ===================================================================
> --- gcc/config/i386/t-gnu	(revision 0)
> +++ gcc/config/i386/t-gnu	(revision 0)
> @@ -0,0 +1 @@
> +MULTIARCH_DIRNAME = $(call if_multiarch,i386-gnu)

> Index: gcc/config/i386/t-kfreebsd
> ===================================================================
> --- gcc/config/i386/t-kfreebsd	(revision 0)
> +++ gcc/config/i386/t-kfreebsd	(revision 0)
> @@ -0,0 +1,5 @@
> +MULTIARCH_DIRNAME = $(call if_multiarch,i386-kfreebsd-gnu)
> +
> +# MULTILIB_OSDIRNAMES are set in t-linux64.
> +KFREEBSD_OS = $(filter kfreebsd%, $(word 3, $(subst -, ,$(target))))
> +MULTILIB_OSDIRNAMES := $(subst linux,$(KFREEBSD_OS),$(MULTILIB_OSDIRNAMES))

As of 2011-11-02 (a997b0d8a7b720578f40c0f9f7767bac02022e0b, r180767)
there was no i386/t-linux anymore, and you're now re-introducing it, so
you'll need to re-add it for the *-linux* cases cited above, but also
remove it from the other *-gnu* cases.


Grüße,
 Thomas
diff mbox

Patch

Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 187271)
+++ gcc/common.opt	(working copy)
@@ -345,6 +345,9 @@ 
 -print-multi-os-directory
 Driver Alias(print-multi-os-directory)
 
+-print-multiarch
+Driver Alias(print-multiarch)
+
 -print-prog-name
 Driver Separate Alias(print-prog-name=)
 
@@ -2286,6 +2289,10 @@ 
 Common Joined Var(plugindir_string) Init(0)
 -iplugindir=<dir>	Set <dir> to be the default plugin directory
 
+imultiarch
+Common Joined Separate RejectDriver Var(imultiarch) Init(0)
+-imultiarch <dir>	Set <dir> to be the multiarch include subdirectory
+
 l
 Driver Joined Separate
 
@@ -2342,6 +2349,9 @@ 
 
 print-multi-os-directory
 Driver Var(print_multi_os_directory)
+ 
+print-multiarch
+Driver Var(print_multiarch)
 
 print-prog-name=
 Driver JoinedOrMissing Var(print_prog_name)
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 187271)
+++ gcc/Makefile.in	(working copy)
@@ -350,6 +350,17 @@ 
 
 enable_plugin = @enable_plugin@
 
+# Multiarch support
+enable_multiarch = @enable_multiarch@
+with_float = @with_float@
+ifeq ($(enable_multiarch),yes)
+  if_multiarch = $(1)
+else ifeq ($(enable_multiarch),auto-detect)
+  if_multiarch = $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib/*/crti.o),$(1))
+else
+  if_multiarch =
+endif
+
 CPPLIB = ../libcpp/libcpp.a
 CPPINC = -I$(srcdir)/../libcpp/include
 
@@ -1830,10 +1841,11 @@ 
 	    "$(MULTILIB_EXTRA_OPTS)" \
 	    "$(MULTILIB_EXCLUSIONS)" \
 	    "$(MULTILIB_OSDIRNAMES)" \
+	    "$(MULTIARCH_DIRNAME)" \
 	    "@enable_multilib@" \
 	    > tmp-mlib.h; \
 	else \
-	  $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' no \
+	  $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' "$(MULTIARCH_DIRNAME)" no \
 	    > tmp-mlib.h; \
 	fi
 	$(SHELL) $(srcdir)/../move-if-change tmp-mlib.h multilib.h
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 187271)
+++ gcc/config.gcc	(working copy)
@@ -3472,10 +3476,14 @@ 
 
 	i[34567]86-*-darwin* | x86_64-*-darwin*)
 		;;
-	i[34567]86-*-linux* | x86_64-*-linux* | \
-	  i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu | \
-	  i[34567]86-*-gnu*)
+	i[34567]86-*-linux* | x86_64-*-linux*)
 		;;
+	i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
+		tmake_file="${tmake_file} i386/t-linux i386/t-kfreebsd"
+		;;
+	i[34567]86-*-gnu*)
+		tmake_file="${tmake_file} i386/t-linux i386/t-gnu"
+		;;
 	i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
 		;;
 	i[34567]86-*-cygwin* | i[34567]86-*-mingw* | x86_64-*-mingw*)
Index: gcc/config/i386/t-linux
===================================================================
--- gcc/config/i386/t-linux	(revision 0)
+++ gcc/config/i386/t-linux	(revision 0)
@@ -0,0 +1 @@ 
+MULTIARCH_DIRNAME = $(call if_multiarch,i386-linux-gnu)
Index: gcc/config/i386/t-gnu
===================================================================
--- gcc/config/i386/t-gnu	(revision 0)
+++ gcc/config/i386/t-gnu	(revision 0)
@@ -0,0 +1 @@ 
+MULTIARCH_DIRNAME = $(call if_multiarch,i386-gnu)
Index: gcc/config/i386/t-linux64
===================================================================
--- gcc/config/i386/t-linux64	(revision 187271)
+++ gcc/config/i386/t-linux64	(working copy)
@@ -34,6 +34,6 @@ 
 comma=,
 MULTILIB_OPTIONS    = $(subst $(comma),/,$(TM_MULTILIB_CONFIG))
 MULTILIB_DIRNAMES   = $(patsubst m%, %, $(subst /, ,$(MULTILIB_OPTIONS)))
-MULTILIB_OSDIRNAMES = m64=../lib64
-MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)
+MULTILIB_OSDIRNAMES = m64=../lib64$(call if_multiarch,:x86_64-linux-gnu)
+MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:i386-linux-gnu)
 MULTILIB_OSDIRNAMES+= mx32=../libx32
Index: gcc/config/i386/t-kfreebsd
===================================================================
--- gcc/config/i386/t-kfreebsd	(revision 0)
+++ gcc/config/i386/t-kfreebsd	(revision 0)
@@ -0,0 +1,5 @@ 
+MULTIARCH_DIRNAME = $(call if_multiarch,i386-kfreebsd-gnu)
+
+# MULTILIB_OSDIRNAMES are set in t-linux64.
+KFREEBSD_OS = $(filter kfreebsd%, $(word 3, $(subst -, ,$(target))))
+MULTILIB_OSDIRNAMES := $(subst linux,$(KFREEBSD_OS),$(MULTILIB_OSDIRNAMES))
Index: gcc/incpath.c
===================================================================
--- gcc/incpath.c	(revision 187271)
+++ gcc/incpath.c	(working copy)
@@ -150,8 +150,14 @@ 
 	      if (!filename_ncmp (p->fname, cpp_GCC_INCLUDE_DIR, len))
 		{
 		  char *str = concat (iprefix, p->fname + len, NULL);
-		  if (p->multilib && imultilib)
+		  if (p->multilib == 1 && imultilib)
 		    str = concat (str, dir_separator_str, imultilib, NULL);
+		  else if (p->multilib == 2)
+		    {
+		      if (!imultiarch)
+			continue;
+		      str = concat (str, dir_separator_str, imultiarch, NULL);
+		    }
 		  add_path (str, SYSTEM, p->cxx_aware, false);
 		}
 	    }
@@ -203,8 +209,14 @@ 
 	  else
 	    str = update_path (p->fname, p->component);
 
-	  if (p->multilib && imultilib)
+	  if (p->multilib == 1 && imultilib)
 	    str = concat (str, dir_separator_str, imultilib, NULL);
+	  else if (p->multilib == 2)
+	    {
+	      if (!imultiarch)
+		continue;
+	      str = concat (str, dir_separator_str, imultiarch, NULL);
+	    }
 
 	  add_path (str, SYSTEM, p->cxx_aware, false);
 	}
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 187271)
+++ gcc/doc/invoke.texi	(working copy)
@@ -6110,6 +6110,11 @@ 
 @file{../lib32}, or if OS libraries are present in @file{lib/@var{subdir}}
 subdirectories it prints e.g.@: @file{amd64}, @file{sparcv9} or @file{ev6}.
 
+@item -print-multiarch
+@opindex print-multiarch
+Print the path to OS libraries for the selected multiarch,
+relative to some @file{lib} subdirectory.
+
 @item -print-prog-name=@var{program}
 @opindex print-prog-name
 Like @option{-print-file-name}, but searches for a program such as @samp{cpp}.
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 187271)
+++ gcc/doc/install.texi	(working copy)
@@ -1038,6 +1038,11 @@ 
 conventions, etc.@: should not be built.  The default is to build a
 predefined set of them.
 
+@item --enable-multiarch
+Specify wether to enable or disable multiarch support.  The default is
+to detect for glibc start files in a multiarch location, and enable it
+if the files are found.
+
 Some targets provide finer-grained control over which multilibs are built
 (e.g., @option{--disable-softfloat}):
 @table @code
Index: gcc/doc/fragments.texi
===================================================================
--- gcc/doc/fragments.texi	(revision 187271)
+++ gcc/doc/fragments.texi	(working copy)
@@ -129,6 +129,36 @@ 
 of options to be used for all builds.  If you set this, you should
 probably set @code{CRTSTUFF_T_CFLAGS} to a dash followed by it.
 
+@findex MULTILIB_OSDIRNAMES
+@item MULTILIB_OSDIRNAMES
+If @code{MULTILIB_OPTIONS} is used, this variable specifies the list
+of OS subdirectory names.  The format is either the same as of
+@code{MULTILIB_DIRNAMES}, or a set of mappings.  When it is the same
+as @code{MULTILIB_DIRNAMES}, it describes the multilib directories
+using OS conventions, rather than GCC conventions.  When it is a set
+of mappings of the form @var{gccdir}=@var{osdir}, the left side gives
+the GCC convention and the right gives the equivalent OS defined
+location.  If the @var{osdir} part begins with a @samp{!}, the os
+directory names are used exclusively.  Use the mapping when there is
+no one-to-one equivalence between GCC levels and the OS.
+
+For multilib enabled configurations (see @code{MULTIARCH_DIRNAME})
+below), the multilib name is appended to each directory name, separated
+by a colon (e.g. @samp{../lib:x86_64-linux-gnu}).
+
+@findex MULTIARCH_DIRNAME
+@item MULTIARCH_DIRNAME
+If @code{MULTIARCH_DIRNAME} is used, this variable specifies the
+multiarch name for this configuration.  For multiarch enabled
+configurations it is used to search libraries and crt files in
+@file{/lib/@var{multiarch}} and @file{/usr/lib/@var{multiarch}}, and
+system header files in @file{/usr/include/@var{multiarch}}.
+@code{MULTIARCH_DIRNAME} is not used for multilib enabled
+configurations, but encoded in @code{MULTILIB_OSDIRNAMES} instead.
+
+The multiarch tuples are defined
+in @uref{http://wiki.debian.org/Multiarch/Tuples}.
+
 @findex SPECS
 @item SPECS
 Unfortunately, setting @code{MULTILIB_EXTRA_OPTS} is not enough, since
Index: gcc/genmultilib
===================================================================
--- gcc/genmultilib	(revision 187271)
+++ gcc/genmultilib	(working copy)
@@ -73,6 +73,8 @@ 
 # the os directory names are used exclusively.  Use the mapping when
 # there is no one-to-one equivalence between GCC levels and the OS.
 
+# The optional eight argument is the multiarch name.
+
 # The last option should be "yes" if multilibs are enabled.  If it is not
 # "yes", all GCC multilib dir names will be ".".
 
@@ -121,7 +123,8 @@ 
 extra=$5
 exclusions=$6
 osdirnames=$7
-enable_multilib=$8
+multiarch=$8
+enable_multilib=$9
 
 echo "static const char *const multilib_raw[] = {"
 
@@ -222,6 +225,9 @@ 
 # names.
 toosdirnames=
 defaultosdirname=
+if [ -n "${multiarch}" ]; then
+  defaultosdirname=::${multiarch}
+fi
 if [ -n "${osdirnames}" ]; then
   set x ${osdirnames}
   shift
@@ -229,6 +235,9 @@ 
     case "$1" in
       .=*)
         defaultosdirname=`echo $1 | sed 's|^.=|:|'`
+	if [ -n "${multiarch}" ]; then
+	  defaultosdirname=${defaultosdirname}:${multiarch}
+	fi
 	shift
 	;;
       *=*)
@@ -314,13 +323,13 @@ 
     dirout=`echo ${combo} | sed -e 's/=/-/g'`
   fi
   # Remove the leading and trailing slashes.
-  dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/$||g'`
+  dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'`
 
   # Use the OS directory names rather than the option names.
   if [ -n "${toosdirnames}" ]; then
     osdirout=`echo ${combo} | sed ${toosdirnames}`
     # Remove the leading and trailing slashes.
-    osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/$||g'`
+    osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'`
     if [ "x${enable_multilib}" != xyes ]; then
       dirout=".:${osdirout}"
       disable_multilib=yes
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 187271)
+++ gcc/gcc.c	(working copy)
@@ -1153,6 +1153,11 @@ 
    set_multilib_dir based on the compilation options.  */
 
 static const char *multilib_os_dir;
+
+/* Subdirectory to use for locating libraries in multiarch conventions.  Set by
+   set_multilib_dir based on the compilation options.  */
+
+static const char *multiarch_dir;
 
 /* Structure to keep track of the specs that have been defined so far.
    These are accessed using %(specname) in a compiler or link
@@ -2078,6 +2083,7 @@ 
   struct prefix_list *pl;
   const char *multi_dir = NULL;
   const char *multi_os_dir = NULL;
+  const char *multiarch_suffix = NULL;
   const char *multi_suffix;
   const char *just_multi_suffix;
   char *path = NULL;
@@ -2095,11 +2101,14 @@ 
     }
   if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
     multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+  if (multiarch_dir)
+    multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
 
   while (1)
     {
       size_t multi_dir_len = 0;
       size_t multi_os_dir_len = 0;
+      size_t multiarch_len = 0;
       size_t suffix_len;
       size_t just_suffix_len;
       size_t len;
@@ -2108,16 +2117,15 @@ 
 	multi_dir_len = strlen (multi_dir);
       if (multi_os_dir)
 	multi_os_dir_len = strlen (multi_os_dir);
+      if (multiarch_suffix)
+	multiarch_len = strlen (multiarch_suffix);
       suffix_len = strlen (multi_suffix);
       just_suffix_len = strlen (just_multi_suffix);
 
       if (path == NULL)
 	{
 	  len = paths->max_len + extra_space + 1;
-	  if (suffix_len > multi_os_dir_len)
-	    len += suffix_len;
-	  else
-	    len += multi_os_dir_len;
+	  len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
 	  path = XNEWVEC (char, len);
 	}
 
@@ -2146,6 +2154,16 @@ 
 		break;
 	    }
 
+	  /* Now try the multiarch path.  */
+	  if (!skip_multi_dir
+	      && !pl->require_machine_suffix && multiarch_dir)
+	    {
+	      memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+	      ret = callback (path, callback_info);
+	      if (ret)
+		break;
+	    }
+
 	  /* Now try the base path.  */
 	  if (!pl->require_machine_suffix
 	      && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
@@ -2970,6 +2988,9 @@ 
   fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
   fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
   fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
+  fputs (_("\
+  -print-multiarch         Display the target's normalized GNU triplet, used as\n\
+                           a component in the library path\n"), stdout);
   fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
   fputs (_("\
   -print-multi-lib         Display the mapping between command line options and\n\
@@ -3244,6 +3265,7 @@ 
     case OPT_print_multi_directory:
     case OPT_print_sysroot:
     case OPT_print_multi_os_directory:
+    case OPT_print_multiarch:
     case OPT_print_sysroot_headers_suffix:
     case OPT_time:
     case OPT_wrapper:
@@ -4896,6 +4918,15 @@ 
 		  do_spec_1 (" ", 0, NULL);
 		}
 
+	      if (multiarch_dir)
+		{
+		  do_spec_1 ("-imultiarch", 1, NULL);
+		  /* Make this a separate argument.  */
+		  do_spec_1 (" ", 0, NULL);
+		  do_spec_1 (multiarch_dir, 1, NULL);
+		  do_spec_1 (" ", 0, NULL);
+		}
+
 	      if (gcc_exec_prefix)
 		{
 		  do_spec_1 ("-iprefix", 1, NULL);
@@ -6545,6 +6576,15 @@ 
       return (0);
     }
 
+  if (print_multiarch)
+    {
+      if (multiarch_dir == NULL)
+	printf ("\n");
+      else
+	printf ("%s\n", multiarch_dir);
+      return (0);
+    }
+
   if (print_sysroot)
     {
       if (target_system_root)
@@ -7527,10 +7567,26 @@ 
 	    q++;
 	  if (q < end)
 	    {
-	      char *new_multilib_os_dir = XNEWVEC (char, end - q);
+	      const char *q2 = q + 1;
+	      char *new_multilib_os_dir;
+
+	      while (q2 < end && *q2 != ':')
+		q2++;
+	      if (*q2 == ':')
+		end = q2;
+	      new_multilib_os_dir = XNEWVEC (char, end - q);
 	      memcpy (new_multilib_os_dir, q + 1, end - q - 1);
 	      new_multilib_os_dir[end - q - 1] = '\0';
-	      multilib_os_dir = new_multilib_os_dir;
+	      multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+
+	      end = this_path + this_path_len;
+	      if (q2 < end && *q2 == ':')
+		{
+		  char *new_multiarch_dir = XNEWVEC (char, end - q2);
+		  memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+		  new_multiarch_dir[end - q2 - 1] = '\0';
+		  multiarch_dir = new_multiarch_dir;
+		}
 	      break;
 	    }
 	}
@@ -7592,7 +7648,7 @@ 
       /* When --disable-multilib was used but target defines
 	 MULTILIB_OSDIRNAMES, entries starting with .: are there just
 	 to find multilib_os_dir, so skip them from output.  */
-      if (this_path[0] == '.' && this_path[1] == ':')
+      if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
 	skip = 1;
 
       /* Check for matches with the multilib_exclusions. We don't bother
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 187271)
+++ gcc/configure.ac	(working copy)
@@ -629,6 +629,21 @@ 
 [], [enable_multilib=yes])
 AC_SUBST(enable_multilib)
 
+# Determine whether or not multiarch is enabled.
+AC_ARG_ENABLE(multiarch,
+[AS_HELP_STRING([--enable-multiarch],
+		[enable support for multiarch paths])],
+[case "${withval}" in
+yes|no|auto-detect) enable_multiarch=$withval;;
+*) AC_MSG_ERROR(bad value ${withval} given for --enable-multiarch option) ;;
+esac], [enable_multiarch=auto-detect])
+AC_MSG_CHECKING(for multiarch configuration)
+AC_SUBST(enable_multiarch)
+AC_MSG_RESULT($enable_multiarch)
+
+# needed for setting the multiarch name on ARM
+AC_SUBST(with_float)
+
 # Enable __cxa_atexit for C++.
 AC_ARG_ENABLE(__cxa_atexit,
 [AS_HELP_STRING([--enable-__cxa_atexit], [enable __cxa_atexit for C++])],
Index: gcc/cppdefault.c
===================================================================
--- gcc/cppdefault.c	(revision 187271)
+++ gcc/cppdefault.c	(working copy)
@@ -63,6 +63,7 @@ 
 #endif
 #ifdef LOCAL_INCLUDE_DIR
     /* /usr/local/include comes before the fixincluded header files.  */
+    { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 2 },
     { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 },
 #endif
 #ifdef PREFIX_INCLUDE_DIR
@@ -90,6 +91,7 @@ 
 #endif
 #ifdef NATIVE_SYSTEM_HEADER_DIR
     /* /usr/include comes dead last.  */
+    { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0, 1, 2 },
     { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0, 1, 0 },
 #endif
     { 0, 0, 0, 0, 0, 0 }
Index: gcc/cppdefault.h
===================================================================
--- gcc/cppdefault.h	(revision 187271)
+++ gcc/cppdefault.h	(working copy)
@@ -43,9 +43,11 @@ 
 				   C++.  */
   const char add_sysroot;	/* FNAME should be prefixed by
 				   cpp_SYSROOT.  */
-  const char multilib;		/* FNAME should have the multilib path
-				   specified with -imultilib
-				   appended.  */
+  const char multilib;		/* FNAME should have appended
+				   - the multilib path specified with -imultilib
+				     when 1 is passed,
+				   - the multiarch path specified with
+				     -imultiarch, when 2 is passed.  */
 };
 
 extern const struct default_include cpp_include_defaults[];