8015377: Support using compiler devkits on Linux
authorerikj
Tue, 18 Jun 2013 11:30:36 +0200
changeset 18021 680b9b43e2d6
parent 18020 eade0d9836bf
child 18022 0229eabb2693
8015377: Support using compiler devkits on Linux Reviewed-by: tbell, dholmes
common/autoconf/basics.m4
common/autoconf/build-performance.m4
common/autoconf/generated-configure.sh
common/autoconf/libraries.m4
common/makefiles/devkit/Makefile
common/makefiles/devkit/Tools.gmk
--- a/common/autoconf/basics.m4	Tue Jun 18 11:29:34 2013 +0200
+++ b/common/autoconf/basics.m4	Tue Jun 18 11:30:36 2013 +0200
@@ -363,7 +363,11 @@
       AC_MSG_ERROR([Cannot specify both --with-devkit and --with-tools-dir at the same time])
     fi
     TOOLS_DIR=$with_devkit/bin
-    SYS_ROOT=$with_devkit/$host_alias/libc
+    if test -d "$with_devkit/$host_alias/libc"; then
+      SYS_ROOT=$with_devkit/$host_alias/libc
+    elif test -d "$with_devkit/$host/sys-root"; then
+      SYS_ROOT=$with_devkit/$host/sys-root
+    fi
   ])
 
 ])
--- a/common/autoconf/build-performance.m4	Tue Jun 18 11:29:34 2013 +0200
+++ b/common/autoconf/build-performance.m4	Tue Jun 18 11:30:36 2013 +0200
@@ -162,7 +162,12 @@
 	      		      [disable using ccache to speed up recompilations @<:@enabled@:>@])],
               [ENABLE_CCACHE=${enable_ccache}], [ENABLE_CCACHE=yes])
     if test "x$ENABLE_CCACHE" = xyes; then
+        OLD_PATH="$PATH"
+        if test "x$TOOLS_DIR" != x; then
+          PATH=$TOOLS_DIR:$PATH
+        fi
         AC_PATH_PROG(CCACHE, ccache)
+        PATH="$OLD_PATH"
     else
         AC_MSG_CHECKING([for ccache])
         AC_MSG_RESULT([explicitly disabled])    
--- a/common/autoconf/generated-configure.sh	Tue Jun 18 11:29:34 2013 +0200
+++ b/common/autoconf/generated-configure.sh	Tue Jun 18 11:30:36 2013 +0200
@@ -3782,7 +3782,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1371547755
+DATE_WHEN_GENERATED=1371547824
 
 ###############################################################################
 #
@@ -7471,7 +7471,11 @@
       as_fn_error $? "Cannot specify both --with-devkit and --with-tools-dir at the same time" "$LINENO" 5
     fi
     TOOLS_DIR=$with_devkit/bin
-    SYS_ROOT=$with_devkit/$host_alias/libc
+    if test -d "$with_devkit/$host_alias/libc"; then
+      SYS_ROOT=$with_devkit/$host_alias/libc
+    elif test -d "$with_devkit/$host/sys-root"; then
+      SYS_ROOT=$with_devkit/$host/sys-root
+    fi
 
 fi
 
@@ -29910,11 +29914,17 @@
   if test "x$x_includes" = xNONE; then
     if test -f "$SYS_ROOT/usr/X11R6/include/X11/Xlib.h"; then
       x_includes="$SYS_ROOT/usr/X11R6/include"
+    elif test -f "$SYS_ROOT/usr/include/X11/Xlib.h"; then
+      x_includes="$SYS_ROOT/usr/include"
     fi
   fi
   if test "x$x_libraries" = xNONE; then
     if test -f "$SYS_ROOT/usr/X11R6/lib/libX11.so"; then
       x_libraries="$SYS_ROOT/usr/X11R6/lib"
+    elif test "$SYS_ROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+      x_libraries="$SYS_ROOT/usr/lib64"
+    elif test -f "$SYS_ROOT/usr/lib/libX11.so"; then
+      x_libraries="$SYS_ROOT/usr/lib"
     fi
   fi
 fi
@@ -30645,8 +30655,7 @@
 if test "x$OPENJDK_TARGET_OS" = xlinux; then
     if test -d "$SYS_ROOT/usr/X11R6"; then
         OPENWIN_HOME="$SYS_ROOT/usr/X11R6"
-    fi
-    if test -d "$SYS_ROOT/usr/include/X11"; then
+    elif test -d "$SYS_ROOT/usr/include/X11"; then
         OPENWIN_HOME="$SYS_ROOT/usr"
     fi
 fi
@@ -31539,12 +31548,12 @@
 	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype in some standard locations" >&5
 $as_echo_n "checking for freetype in some standard locations... " >&6; }
 
-	    if test -s /usr/X11/include/ft2build.h && test -d /usr/X11/include/freetype2/freetype; then
-	        DEFAULT_FREETYPE_CFLAGS="-I/usr/X11/include/freetype2 -I/usr/X11/include"
-	        DEFAULT_FREETYPE_LIBS="-L/usr/X11/lib -lfreetype"
+	    if test -s $SYS_ROOT/usr/X11/include/ft2build.h && test -d $SYS_ROOT/usr/X11/include/freetype2/freetype; then
+	        DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/X11/include/freetype2 -I$SYS_ROOT/usr/X11/include"
+	        DEFAULT_FREETYPE_LIBS="-L$SYS_ROOT/usr/X11/lib -lfreetype"
 	    fi
-	    if test -s /usr/include/ft2build.h && test -d /usr/include/freetype2/freetype; then
-	        DEFAULT_FREETYPE_CFLAGS="-I/usr/include/freetype2"
+	    if test -s $SYS_ROOT/usr/include/ft2build.h && test -d $SYS_ROOT/usr/include/freetype2/freetype; then
+	        DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/include/freetype2"
 	        DEFAULT_FREETYPE_LIBS="-lfreetype"
 	    fi
 
@@ -33220,6 +33229,10 @@
 fi
 
     if test "x$ENABLE_CCACHE" = xyes; then
+        OLD_PATH="$PATH"
+        if test "x$TOOLS_DIR" != x; then
+          PATH=$TOOLS_DIR:$PATH
+        fi
         # Extract the first word of "ccache", so it can be a program name with args.
 set dummy ccache; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -33260,6 +33273,7 @@
 fi
 
 
+        PATH="$OLD_PATH"
     else
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ccache" >&5
 $as_echo_n "checking for ccache... " >&6; }
--- a/common/autoconf/libraries.m4	Tue Jun 18 11:29:34 2013 +0200
+++ b/common/autoconf/libraries.m4	Tue Jun 18 11:30:36 2013 +0200
@@ -123,11 +123,17 @@
   if test "x$x_includes" = xNONE; then
     if test -f "$SYS_ROOT/usr/X11R6/include/X11/Xlib.h"; then
       x_includes="$SYS_ROOT/usr/X11R6/include"
+    elif test -f "$SYS_ROOT/usr/include/X11/Xlib.h"; then
+      x_includes="$SYS_ROOT/usr/include"
     fi
   fi
   if test "x$x_libraries" = xNONE; then
     if test -f "$SYS_ROOT/usr/X11R6/lib/libX11.so"; then
       x_libraries="$SYS_ROOT/usr/X11R6/lib"
+    elif test "$SYS_ROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+      x_libraries="$SYS_ROOT/usr/lib64"
+    elif test -f "$SYS_ROOT/usr/lib/libX11.so"; then
+      x_libraries="$SYS_ROOT/usr/lib"
     fi
   fi
 fi
@@ -153,8 +159,7 @@
 if test "x$OPENJDK_TARGET_OS" = xlinux; then
     if test -d "$SYS_ROOT/usr/X11R6"; then
         OPENWIN_HOME="$SYS_ROOT/usr/X11R6"
-    fi
-    if test -d "$SYS_ROOT/usr/include/X11"; then
+    elif test -d "$SYS_ROOT/usr/include/X11"; then
         OPENWIN_HOME="$SYS_ROOT/usr"
     fi
 fi
@@ -359,12 +364,12 @@
 	if test "x$FREETYPE2_FOUND" = xno; then
 	    AC_MSG_CHECKING([for freetype in some standard locations])
 	
-	    if test -s /usr/X11/include/ft2build.h && test -d /usr/X11/include/freetype2/freetype; then
-	        DEFAULT_FREETYPE_CFLAGS="-I/usr/X11/include/freetype2 -I/usr/X11/include"
-	        DEFAULT_FREETYPE_LIBS="-L/usr/X11/lib -lfreetype"
+	    if test -s $SYS_ROOT/usr/X11/include/ft2build.h && test -d $SYS_ROOT/usr/X11/include/freetype2/freetype; then
+	        DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/X11/include/freetype2 -I$SYS_ROOT/usr/X11/include"
+	        DEFAULT_FREETYPE_LIBS="-L$SYS_ROOT/usr/X11/lib -lfreetype"
 	    fi
-	    if test -s /usr/include/ft2build.h && test -d /usr/include/freetype2/freetype; then
-	        DEFAULT_FREETYPE_CFLAGS="-I/usr/include/freetype2"
+	    if test -s $SYS_ROOT/usr/include/ft2build.h && test -d $SYS_ROOT/usr/include/freetype2/freetype; then
+	        DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/include/freetype2"
 	        DEFAULT_FREETYPE_LIBS="-lfreetype"
 	    fi
 	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/makefiles/devkit/Makefile	Tue Jun 18 11:30:36 2013 +0200
@@ -0,0 +1,123 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+##########################################################################################
+#
+# This Makefile, together with Tools.gmk, can be used to compile a set of 
+# gcc based cross compilation, portable, self contained packages, capable 
+# of building OpenJDK.
+# 
+# In addition to the makefiles, access to Oracle Linux installation 
+# media is required. This has been tested against Oracle Enterprise Linux 
+# 5.5. Set variables RPM_DIR_x86_64 and RPM_DIR_i686 respectively to point
+# to directory containing the RPMs.
+#
+# By default this Makefile will build crosstools for:
+# * i686-unknown-linux-gnu
+# * x86_64-unknown-linux-gnu
+# The x86_64 version of the compilers will work in multi arch mode and will
+# be able to compile 32bit binaries with the -m32 flag. This makes the
+# explicit cross compiler for i686 somewhat redundant and is a known issue.
+#
+# To build the full set of crosstools, use a command line looking like this:
+#
+# make tars  RPM_DIR_x86_64=/tmp/oel55-x86_64/Server/ RPM_DIR_i686=/tmp/oel55-i686/Server/
+#
+# To create a x86_64 package without the redundant i686 cross compiler, do 
+# like this:
+#
+# make tars platforms=x86_64-unknown-linux-gnu RPM_DIR_x86_64=/tmp/oel55-x86_64/Server/ RPM_DIR_i686=/tmp/oel55-i686/Server/
+
+#
+# Main makefile which iterates over all host and target platforms.
+#
+
+os		:= $(shell uname -o)
+cpu 		:= x86_64
+#$(shell uname -p)
+
+#
+# This wrapper script can handle exactly these platforms
+#
+platforms	:= $(foreach p,x86_64 i686,$(p)-unknown-linux-gnu)
+#platforms	:= $(foreach p,x86_64,$(p)-unknown-linux-gnu)
+
+# Figure out what platform this is building on.
+me		:= $(cpu)-$(if $(findstring Linux,$(os)),unknown-linux-gnu)
+
+$(info Building on platform $(me))
+
+all compile	: $(platforms)
+
+ifeq (,$(SKIP_ME))
+$(foreach p,$(filter-out $(me),$(platforms)),$(eval $(p) : $$(me)))
+endif
+
+OUTPUT_ROOT	= $(abspath ../../../build/devkit)
+RESULT		= $(OUTPUT_ROOT)/result
+
+submakevars	= HOST=$@ BUILD=$(me)				\
+			RESULT=$(RESULT) PREFIX=$(RESULT)/$@    \
+			OUTPUT_ROOT=$(OUTPUT_ROOT)
+$(platforms)	:
+		@echo 'Building compilers for $@'
+		@echo 'Targets: $(platforms)'
+		for p in $@ $(filter-out $@,$(platforms)); do	\
+			$(MAKE) -f Tools.gmk all $(submakevars)	\
+				TARGET=$$p || exit 1	;	\
+		done
+		@echo 'Building ccache program for $@'
+		$(MAKE) -f Tools.gmk ccache $(submakevars) TARGET=$@
+		@echo 'All done"'
+
+$(foreach a,i686 x86_64,$(eval $(a) : $(filter $(a)%,$(platforms))))
+
+ia32		:  i686
+today		:= $(shell date +%Y%m%d)
+
+
+define Mktar
+$(1)_tar	= $$(RESULT)/sdk-$(1)-$$(today).tar.gz
+$$($(1)_tar)	: PLATFORM = $(1)
+TARFILES	+= $$($(1)_tar)
+$$($(1)_tar)	: $(1) $$(shell find $$(RESULT)/$(1))
+endef
+
+$(foreach p,$(platforms),$(eval $(call Mktar,$(p))))
+
+tars		: all $(TARFILES)
+onlytars	: $(TARFILES)
+%.tar.gz	:
+		@echo 'Creating compiler package $@'
+		cd $(RESULT)/$(PLATFORM) && tar -czf $@ *
+		touch $@
+
+clean		:
+	rm -rf build result
+
+FORCE		:
+.PHONY		: $(configs) $(platforms)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/makefiles/devkit/Tools.gmk	Tue Jun 18 11:30:36 2013 +0200
@@ -0,0 +1,473 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+##########################################################################################
+#
+# Workhorse makefile for creating ONE cross compiler
+# Needs either to be from BUILD -> BUILD OR have 
+# BUILD -> HOST prebuilt
+#
+# NOTE: There is a bug here. We don't limit the 
+# PATH when building BUILD -> BUILD, which means that 
+# if you configure after you've once build the BUILD->BUILD
+# compiler THAT one will be picked up as the compiler for itself.
+# This is not so great, especially if you did a partial delete
+# of the target tree. 
+#
+# Fix this...
+#
+
+$(info TARGET=$(TARGET))
+$(info HOST=$(HOST))
+$(info BUILD=$(BUILD))
+
+ARCH		:= $(word 1,$(subst -, ,$(TARGET)))
+
+##########################################################################################
+# Define external dependencies
+
+# Latest that could be made to work.
+gcc_ver		:= gcc-4.7.3
+binutils_ver	:= binutils-2.22
+ccache_ver	:= ccache-3.1.9
+mpfr_ver        := mpfr-3.0.1
+gmp_ver         := gmp-4.3.2
+mpc_ver		:= mpc-1.0.1
+
+GCC		:= http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.bz2
+BINUTILS	:= http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.bz2
+CCACHE		:= http://samba.org/ftp/ccache/$(ccache_ver).tar.gz
+MPFR		:= http://www.mpfr.org/${mpfr_ver}/${mpfr_ver}.tar.bz2
+GMP 		:= http://ftp.gnu.org/pub/gnu/gmp/${gmp_ver}.tar.bz2
+MPC		:= http://www.multiprecision.org/mpc/download/${mpc_ver}.tar.gz
+
+# RPMs in OEL5.5
+RPM_LIST 	:= \
+		kernel-headers \
+		glibc-2 glibc-headers glibc-devel \
+		cups-libs cups-devel \
+		libX11 libX11-devel \
+		xorg-x11-proto-devel \
+		alsa-lib alsa-lib-devel \
+		libXext libXext-devel \
+		libXtst libXtst-devel \
+		libXrender libXrender-devel \
+		freetype freetype-devel \
+		libXt libXt-devel \
+		libSM libSM-devel \
+		libICE libICE-devel \
+		libXi libXi-devel \
+		libXdmcp libXdmcp-devel \
+		libXau libXau-devel \
+		libgcc
+
+
+ifeq ($(ARCH),x86_64)
+  RPM_DIR ?= $(RPM_DIR_x86_64)
+  RPM_ARCHS := x86_64
+  ifeq ($(BUILD),$(HOST))
+    ifeq ($(TARGET),$(HOST))
+      # When building the native compiler for x86_64, enable mixed mode.
+      RPM_ARCHS	+= i386 i686
+    endif
+  endif
+else
+  RPM_DIR ?= $(RPM_DIR_i686)
+  RPM_ARCHS := i386 i686
+endif
+
+# Sort to remove duplicates
+RPM_FILE_LIST := $(sort $(foreach a,$(RPM_ARCHS),$(wildcard $(patsubst %,$(RPM_DIR)/%*$a.rpm,$(RPM_LIST)))))
+
+ifeq ($(RPM_FILE_LIST),)
+  $(error Found no RPMs, RPM_DIR must point to list of directories to search for RPMs)
+endif
+
+##########################################################################################
+# Define common directories and files
+
+# Ensure we have 32-bit libs also for x64. We enable mixed-mode.
+ifeq (x86_64,$(ARCH))
+  LIBDIRS	:= lib64 lib
+  CFLAGS_lib	:= -m32
+else
+  LIBDIRS 	:= lib
+endif
+
+# Define directories
+RESULT		:= $(OUTPUT_ROOT)/result
+BUILDDIR	:= $(OUTPUT_ROOT)/$(HOST)/$(TARGET)
+PREFIX		:= $(RESULT)/$(HOST)
+TARGETDIR	:= $(PREFIX)/$(TARGET)
+SYSROOT		:= $(TARGETDIR)/sys-root
+DOWNLOAD	:= $(OUTPUT_ROOT)/download
+SRCDIR		:= $(OUTPUT_ROOT)/src
+
+# Marker file for unpacking rpms
+rpms		:= $(SYSROOT)/rpms_unpacked
+
+# Need to patch libs that are linker scripts to use non-absolute paths 
+libs		:= $(SYSROOT)/libs_patched
+
+##########################################################################################
+# Unpack source packages
+
+# Generate downloading + unpacking of sources. 
+define Download
+$(1)_DIR	= $(abspath $(SRCDIR)/$(basename $(basename $(notdir $($(1))))))
+$(1)_CFG	= $$($(1)_DIR)/configure
+$(1)_FILE	= $(DOWNLOAD)/$(notdir $($(1)))
+
+$$($(1)_CFG)	: $$($(1)_FILE)
+		mkdir -p $$(SRCDIR)
+		tar -C $$(SRCDIR) -x$$(if $$(findstring .gz, $$<),z,j)f $$<
+		$$(foreach p,$$(abspath $$(wildcard $$(notdir $$($(1)_DIR)).patch)),	\
+			echo PATCHING $$(p) ;						\
+			patch -d $$($(1)_DIR) -p1 -i $$(p) ; 				\
+			)
+		touch $$@
+
+$$($(1)_FILE)	:
+		wget -P $(DOWNLOAD) $$($(1))
+endef
+
+# Download and unpack all source packages
+$(foreach p,GCC BINUTILS CCACHE MPFR GMP MPC,$(eval $(call Download,$(p))))
+
+##########################################################################################
+# Unpack RPMS
+
+# Note. For building linux you should install rpm2cpio. 
+define unrpm
+$(SYSROOT)/$(notdir $(1)).unpacked	\
+		: $(1)
+$$(rpms)	: $(SYSROOT)/$(notdir $(1)).unpacked
+endef
+
+%.unpacked	:
+		$(info Unpacking target rpms and libraries from $<)
+		@(mkdir -p $(@D);					\
+		cd $(@D);						\
+		rpm2cpio $< | 						\
+			cpio --extract --make-directories 		\
+				-f 					\
+				"./usr/share/doc/*" 			\
+				"./usr/share/man/*"			\
+				"./usr/X11R6/man/*" 			\
+				"*/X11/locale/*"			\
+				|| die ; )
+		touch $@
+
+$(foreach p,$(RPM_FILE_LIST),$(eval $(call unrpm,$(p))))
+
+##########################################################################################
+
+# Note: MUST create a <sys-root>/usr/lib even if not really needed. 
+# gcc will use a path relative to it to resolve lib64. (x86_64). 
+# we're creating multi-lib compiler with 32bit libc as well, so we should 
+# have it anyway, but just to make sure...
+# Patch libc.so and libpthread.so to force linking against libraries in sysroot
+# and not the ones installed on the build machine.
+$(libs)		: $(rpms)
+		@echo Patching libc and pthreads
+		@(for f in `find $(SYSROOT) -name libc.so -o -name libpthread.so`; do \
+			(cat $$f | sed -e 's|/usr/lib64/||g' 		\
+				       -e 's|/usr/lib/||g'		\
+				       -e 's|/lib64/||g'		\
+				       -e 's|/lib/||g' ) > $$f.tmp ;	\
+			mv $$f.tmp $$f				;	\
+		done)
+		@mkdir -p $(SYSROOT)/usr/lib
+		@touch $@
+
+##########################################################################################
+
+# Define marker files for each source package to be compiled
+$(foreach t,binutils mpfr gmp mpc gcc ccache,$(eval $(t) = $(TARGETDIR)/$($(t)_ver).done))
+
+##########################################################################################
+
+# Default base config
+CONFIG		= --target=$(TARGET) 					\
+			--host=$(HOST) --build=$(BUILD)			\
+			--prefix=$(PREFIX)
+
+PATHEXT 	= $(RESULT)/$(BUILD)/bin:
+
+PATHPRE		= PATH=$(PATHEXT)$(PATH)
+BUILDPAR	= -j16
+
+# Default commands to when making
+MAKECMD		=
+INSTALLCMD	= install
+
+
+declare_tools   = CC$(1)=$(2)gcc LD$(1)=$(2)ld AR$(1)=$(2)ar AS$(1)=$(2)as RANLIB$(1)=$(2)ranlib CXX$(1)=$(2)g++ OBJDUMP$(1)=$(2)objdump
+
+ifeq ($(HOST),$(BUILD))
+ifeq ($(HOST),$(TARGET))
+TOOLS		= $(call declare_tools,_FOR_TARGET,)
+endif
+endif
+
+TOOLS		?=  $(call declare_tools,_FOR_TARGET,$(TARGET)-)
+
+##########################################################################################
+
+# Create a TARGET bfd + libiberty only. 
+# Configure one or two times depending on mulitlib arch.
+# If multilib, the second should be 32-bit, and we resolve 
+# CFLAG_<name> to most likely -m32.
+define mk_bfd
+$$(info Libs for $(1)) 
+$$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \
+		: CFLAGS += $$(CFLAGS_$(1))
+$$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \
+		: LIBDIRS = --libdir=$(TARGETDIR)/$(1)
+
+bfdlib		+= $$(TARGETDIR)/$$(binutils_ver)-$(subst /,-,$(1)).done
+bfdmakes	+= $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile
+endef
+
+# Create one set of bfds etc for each multilib arch
+$(foreach l,$(LIBDIRS),$(eval $(call mk_bfd,$(l))))
+
+# Only build these two libs.
+$(bfdlib)	: MAKECMD 	= all-libiberty all-bfd
+$(bfdlib)	: INSTALLCMD 	= install-libiberty install-bfd
+
+# Building targets libbfd + libiberty. HOST==TARGET, i.e not 
+# for a cross env. 
+$(bfdmakes)	: CONFIG = --target=$(TARGET) 				\
+			--host=$(TARGET) --build=$(BUILD)		\
+			--prefix=$(TARGETDIR) 				\
+			--with-sysroot=$(SYSROOT) 			\
+			$(LIBDIRS)
+
+$(bfdmakes)	: TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-)
+
+##########################################################################################
+
+$(gcc)		\
+$(binutils)	\
+$(gmp)		\
+$(mpfr)		\
+$(mpc)		\
+$(bfdmakes)	\
+$(ccache)	: ENVS += $(TOOLS)
+
+# libdir to work around hateful bfd stuff installing into wrong dirs...
+# ensure we have 64 bit bfd support in the HOST library. I.e our 
+# compiler on i686 will know 64 bit symbols, BUT later
+# we build just the libs again for TARGET, then with whatever the arch 
+# wants.
+$(BUILDDIR)/$(binutils_ver)/Makefile : CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS))
+
+# Makefile creation. Simply run configure in build dir.
+$(bfdmakes)				\
+$(BUILDDIR)/$(binutils_ver)/Makefile	\
+		: $(BINUTILS_CFG)
+		$(info Configuring $@. Log in $(@D)/log.config)
+		@mkdir -p $(@D)
+		(						\
+			cd $(@D) ;				\
+			$(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)"	\
+				$(BINUTILS_CFG) 		\
+				$(CONFIG) 			\
+				--with-sysroot=$(SYSROOT)	\
+				--disable-nls			\
+				--program-prefix=$(TARGET)-	\
+				--enable-multilib		\
+		) > $(@D)/log.config 2>&1
+		@echo 'done'
+
+$(BUILDDIR)/$(mpfr_ver)/Makefile	\
+		: $(MPFR_CFG)
+		$(info Configuring $@. Log in $(@D)/log.config)
+		@mkdir -p $(@D)
+		(						\
+			cd $(@D) ;				\
+			$(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)"	\
+				$(MPFR_CFG) 			\
+				$(CONFIG) 			\
+				--program-prefix=$(TARGET)-	\
+				--enable-shared=no		\
+				--with-gmp=$(PREFIX)	\
+		) > $(@D)/log.config 2>&1
+		@echo 'done'
+
+$(BUILDDIR)/$(gmp_ver)/Makefile	\
+		: $(GMP_CFG)
+		$(info Configuring $@. Log in $(@D)/log.config)
+		@mkdir -p $(@D)
+		(						\
+			cd $(@D) ;				\
+			$(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)"	\
+				$(GMP_CFG) 			\
+				--host=$(HOST) --build=$(BUILD)	\
+				--prefix=$(PREFIX)		\
+				--disable-nls			\
+				--program-prefix=$(TARGET)-	\
+				--enable-shared=no		\
+				--with-mpfr=$(PREFIX)	\
+		) > $(@D)/log.config 2>&1
+		@echo 'done'
+
+$(BUILDDIR)/$(mpc_ver)/Makefile	\
+		: $(MPC_CFG)
+		$(info Configuring $@. Log in $(@D)/log.config)
+		@mkdir -p $(@D)
+		(						\
+			cd $(@D) ;				\
+			$(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)"	\
+				$(MPC_CFG) 			\
+				$(CONFIG) 			\
+				--program-prefix=$(TARGET)-	\
+				--enable-shared=no		\
+				--with-mpfr=$(PREFIX)	\
+				--with-gmp=$(PREFIX)	\
+		) > $(@D)/log.config 2>&1
+		@echo 'done'
+
+# Only valid if glibc target -> linux
+# proper destructor handling for c++
+ifneq (,$(findstring linux,$(TARGET)))
+$(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --enable-__cxa_atexit 
+endif
+
+# Want:
+# 	c,c++
+# 	shared libs
+#	multilib (-m32/-m64 on x64)
+# 	skip native language. 
+#	and link and assemble with the binutils we created 
+#	earlier, so --with-gnu*
+$(BUILDDIR)/$(gcc_ver)/Makefile	\
+		: $(GCC_CFG) 
+		$(info Configuring $@. Log in $(@D)/log.config)
+		mkdir -p $(@D)
+		(						\
+			cd $(@D) ;				\
+			$(PATHPRE) $(ENVS) $(GCC_CFG) $(EXTRA_CFLAGS) \
+				$(CONFIG) 			\
+				--with-sysroot=$(SYSROOT)	\
+				--enable-languages=c,c++ 	\
+				--enable-shared			\
+				--enable-multilib		\
+				--disable-nls			\
+				--with-gnu-as 			\
+				--with-gnu-ld			\
+				--with-mpfr=$(PREFIX)		\
+				--with-gmp=$(PREFIX)		\
+				--with-mpc=$(PREFIX)		\
+		) > $(@D)/log.config 2>&1
+		@echo 'done'
+
+# need binutils for gcc
+$(gcc)		: $(binutils) 
+
+# as of 4.3 or so need these for doing config
+$(BUILDDIR)/$(gcc_ver)/Makefile : $(gmp) $(mpfr) $(mpc)
+$(mpfr)		: $(gmp)
+$(mpc)		: $(gmp) $(mpfr)
+
+##########################################################################################
+# very straightforward. just build a ccache. it is only for host. 
+$(BUILDDIR)/$(ccache_ver)/Makefile	\
+		: $(CCACHE_CFG)
+		$(info Configuring $@. Log in $(@D)/log.config)
+		@mkdir -p $(@D)
+		@(						\
+			cd $(@D) ;				\
+			$(PATHPRE) $(ENVS) $(CCACHE_CFG)	\
+				$(CONFIG) 			\
+		) > $(@D)/log.config 2>&1
+		@echo 'done'
+
+gccpatch	= $(TARGETDIR)/gcc-patched
+
+##########################################################################################
+# For some reason cpp is not created as a target-compiler 
+ifeq ($(HOST),$(TARGET))
+$(gccpatch)	: $(gcc) link_libs
+		@echo -n 'Creating compiler symlinks...'
+		@for f in cpp; do 				\
+			if [ ! -e $(PREFIX)/bin/$(TARGET)-$$f ];\
+			then					\
+			cd $(PREFIX)/bin && 			\
+				ln -s $$f $(TARGET)-$$f ;	\
+			fi					\
+		done
+		@touch $@
+		@echo 'done'
+
+##########################################################################################
+# Ugly at best. Seems that when we compile host->host compiler, that are NOT
+# the BUILD compiler, the result will not try searching for libs in package root.
+# "Solve" this by create links from the target libdirs to where they are. 
+link_libs:
+		@echo -n 'Creating library symlinks...'
+		@$(foreach l,$(LIBDIRS),							\
+		for f in `cd $(PREFIX)/$(l) && ls`; do 						\
+			if [ ! -e $(TARGETDIR)/$(l)/$$f ]; then					\
+				mkdir -p $(TARGETDIR)/$(l) &&					\
+				cd $(TARGETDIR)/$(l)/ && 					\
+				ln -s $(if $(findstring /,$(l)),../,)../../$(l)/$$f $$f;	\
+			fi									\
+		done;) 
+		@echo 'done'
+else
+$(gccpatch)	:
+		@echo 'done'
+endif
+
+##########################################################################################
+# Build in two steps. 
+# make <default>
+# make install. 
+# Use path to our build hosts cross tools
+# Always need to build cross tools for build host self. 
+$(TARGETDIR)/%.done : $(BUILDDIR)/%/Makefile 
+		$(info Building $(basename $@). Log in $(<D)/log.build)
+		$(PATHPRE) $(ENVS) $(MAKE) $(BUILDPAR) -f $< -C $(<D) $(MAKECMD) $(MAKECMD.$(notdir $@)) > $(<D)/log.build 2>&1
+		@echo -n 'installing...'
+		$(PATHPRE) $(MAKE) $(INSTALLPAR) -f $< -C $(<D) $(INSTALLCMD) $(MAKECMD.$(notdir $@))  > $(<D)/log.install 2>&1
+		@touch $@
+		@echo 'done'
+
+##########################################################################################
+
+bfdlib		: $(bfdlib)
+binutils	: $(binutils)
+rpms		: $(rpms)
+libs		: $(libs)
+sysroot		: rpms libs
+gcc		: sysroot $(gcc) $(gccpatch)
+all		: binutils gcc bfdlib
+
+# this is only built for host. so separate. 
+ccache		: $(ccache)
+
+.PHONY		: gcc all binutils bfdlib link_libs rpms libs sysroot