common/makefiles/devkit/Tools.gmk
author rbackman
Mon, 15 Jul 2013 12:06:50 +0200
changeset 18935 10110aabe1eb
parent 18021 680b9b43e2d6
child 20363 fa7663fc5d50
permissions -rw-r--r--
Merge

#
# 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