Tools.gmk revision 2369:66b770c85156
1#
2# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
3# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4#
5# This code is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 2 only, as
7# published by the Free Software Foundation.  Oracle designates this
8# particular file as subject to the "Classpath" exception as provided
9# by Oracle in the LICENSE file that accompanied this code.
10#
11# This code is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14# version 2 for more details (a copy is included in the LICENSE file that
15# accompanied this code).
16#
17# You should have received a copy of the GNU General Public License version
18# 2 along with this work; if not, write to the Free Software Foundation,
19# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22# or visit www.oracle.com if you need additional information or have any
23# questions.
24#
25
26##########################################################################################
27#
28# Workhorse makefile for creating ONE cross compiler
29# Needs either to be from BUILD -> BUILD OR have
30# BUILD -> HOST prebuilt
31#
32# NOTE: There is a bug here. We don't limit the
33# PATH when building BUILD -> BUILD, which means that
34# if you configure after you've once build the BUILD->BUILD
35# compiler THAT one will be picked up as the compiler for itself.
36# This is not so great, especially if you did a partial delete
37# of the target tree.
38#
39# Fix this...
40#
41
42$(info TARGET=$(TARGET))
43$(info HOST=$(HOST))
44$(info BUILD=$(BUILD))
45
46ARCH := $(word 1,$(subst -, ,$(TARGET)))
47
48##########################################################################################
49# Define external dependencies
50
51# Latest that could be made to work.
52gcc_ver := gcc-4.9.2
53binutils_ver := binutils-2.25
54ccache_ver := ccache-3.2.1
55mpfr_ver := mpfr-3.0.1
56gmp_ver := gmp-4.3.2
57mpc_ver := mpc-1.0.1
58
59GCC := http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.bz2
60BINUTILS := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.bz2
61CCACHE := http://samba.org/ftp/ccache/$(ccache_ver).tar.gz
62MPFR := http://www.mpfr.org/${mpfr_ver}/${mpfr_ver}.tar.bz2
63GMP := http://ftp.gnu.org/pub/gnu/gmp/${gmp_ver}.tar.bz2
64MPC := http://www.multiprecision.org/mpc/download/${mpc_ver}.tar.gz
65
66# RPMs in OEL6.4
67LINUX_VERSION := OEL6.4
68RPM_LIST := \
69    kernel-headers \
70    glibc glibc-headers glibc-devel \
71    cups-libs cups-devel \
72    libX11 libX11-devel \
73    xorg-x11-proto-devel \
74    alsa-lib alsa-lib-devel \
75    libXext libXext-devel \
76    libXtst libXtst-devel \
77    libXrender libXrender-devel \
78    freetype freetype-devel \
79    libXt libXt-devel \
80    libSM libSM-devel \
81    libICE libICE-devel \
82    libXi libXi-devel \
83    libXdmcp libXdmcp-devel \
84    libXau libXau-devel \
85    libgcc \
86    elfutils elfutils-libs elfutils-devel \
87    elfutils-libelf elfutils-libelf-devel \
88    zlib zlib-devel \
89    libffi libffi-devel
90
91ifeq ($(ARCH),x86_64)
92  RPM_DIR ?= $(RPM_DIR_x86_64)
93  RPM_ARCHS := x86_64 noarch
94  ifeq ($(BUILD),$(HOST))
95    ifeq ($(TARGET),$(HOST))
96      # When building the native compiler for x86_64, enable mixed mode.
97      RPM_ARCHS += i386 i686
98    endif
99  endif
100else
101  RPM_DIR ?= $(RPM_DIR_i686)
102  RPM_ARCHS := i386 i686
103endif
104
105# Sort to remove duplicates
106RPM_FILE_LIST := $(sort $(foreach a,$(RPM_ARCHS),$(wildcard $(patsubst %,$(RPM_DIR)/%*$a.rpm,$(RPM_LIST)))))
107
108#$(info RPM_FILE_LIST $(RPM_FILE_LIST))
109
110ifeq ($(RPM_FILE_LIST),)
111  $(error Found no RPMs, RPM_DIR must point to list of directories to search for RPMs)
112endif
113
114##########################################################################################
115# Define common directories and files
116
117# Ensure we have 32-bit libs also for x64. We enable mixed-mode.
118ifeq (x86_64,$(ARCH))
119  LIBDIRS := lib64 lib
120  CFLAGS_lib := -m32
121else
122  LIBDIRS := lib
123endif
124
125# Define directories
126RESULT := $(OUTPUT_ROOT)/result
127BUILDDIR := $(OUTPUT_ROOT)/$(HOST)/$(TARGET)
128PREFIX := $(RESULT)/$(HOST)
129TARGETDIR := $(PREFIX)/$(TARGET)
130SYSROOT := $(TARGETDIR)/sysroot
131DOWNLOAD := $(OUTPUT_ROOT)/download
132SRCDIR := $(OUTPUT_ROOT)/src
133
134# Marker file for unpacking rpms
135rpms := $(SYSROOT)/rpms_unpacked
136
137# Need to patch libs that are linker scripts to use non-absolute paths
138libs := $(SYSROOT)/libs_patched
139
140##########################################################################################
141# Unpack source packages
142
143# Generate downloading + unpacking of sources.
144define Download
145  $(1)_DIR = $(abspath $(SRCDIR)/$(basename $(basename $(notdir $($(1))))))
146  $(1)_CFG = $$($(1)_DIR)/configure
147  $(1)_FILE = $(DOWNLOAD)/$(notdir $($(1)))
148
149  $$($(1)_CFG) : $$($(1)_FILE)
150	mkdir -p $$(SRCDIR)
151	tar -C $$(SRCDIR) -x$$(if $$(findstring .gz, $$<),z,j)f $$<
152	$$(foreach p,$$(abspath $$(wildcard $$(notdir $$($(1)_DIR)).patch)), \
153	  echo PATCHING $$(p) ; \
154	  patch -d $$($(1)_DIR) -p1 -i $$(p) ; \
155	)
156	touch $$@
157
158  $$($(1)_FILE) :
159	wget -P $(DOWNLOAD) $$($(1))
160endef
161
162# Download and unpack all source packages
163$(foreach p,GCC BINUTILS CCACHE MPFR GMP MPC,$(eval $(call Download,$(p))))
164
165##########################################################################################
166# Unpack RPMS
167
168# Note. For building linux you should install rpm2cpio.
169define unrpm
170  $(SYSROOT)/$(notdir $(1)).unpacked \
171    : $(1)
172  $$(rpms) : $(SYSROOT)/$(notdir $(1)).unpacked
173endef
174
175%.unpacked :
176	$(info Unpacking target rpms and libraries from $<)
177	@(mkdir -p $(@D); \
178	cd $(@D); \
179	rpm2cpio $< | \
180	    cpio --extract --make-directories \
181	        -f \
182	        "./usr/share/doc/*" \
183	        "./usr/share/man/*" \
184	        "./usr/X11R6/man/*" \
185	        "*/X11/locale/*" \
186	    || die ; )
187	touch $@
188
189$(foreach p,$(RPM_FILE_LIST),$(eval $(call unrpm,$(p))))
190
191##########################################################################################
192
193# Note: MUST create a <sysroot>/usr/lib even if not really needed.
194# gcc will use a path relative to it to resolve lib64. (x86_64).
195# we're creating multi-lib compiler with 32bit libc as well, so we should
196# have it anyway, but just to make sure...
197# Patch libc.so and libpthread.so to force linking against libraries in sysroot
198# and not the ones installed on the build machine.
199$(libs) : $(rpms)
200	@echo Patching libc and pthreads
201	@(for f in `find $(SYSROOT) -name libc.so -o -name libpthread.so`; do \
202	  (cat $$f | sed -e 's|/usr/lib64/||g' \
203	      -e 's|/usr/lib/||g' \
204	      -e 's|/lib64/||g' \
205	      -e 's|/lib/||g' ) > $$f.tmp ; \
206	  mv $$f.tmp $$f ; \
207	done)
208	@mkdir -p $(SYSROOT)/usr/lib
209	@touch $@
210
211##########################################################################################
212# Create links for ffi header files so that they become visible by default when using the
213# devkit.
214
215$(SYSROOT)/usr/include/ffi.h: $(rpms)
216	cd $(@D) && rm $(@F) && ln -s ../lib/libffi-*/include/$(@F) .
217
218$(SYSROOT)/usr/include/ffitarget.h: $(rpms)
219	cd $(@D) && rm $(@F) && ln -s ../lib/libffi-*/include/$(@F) .
220
221SYSROOT_LINKS += $(SYSROOT)/usr/include/ffi.h $(SYSROOT)/usr/include/ffitarget.h
222
223##########################################################################################
224
225# Define marker files for each source package to be compiled
226$(foreach t,binutils mpfr gmp mpc gcc ccache,$(eval $(t) = $(TARGETDIR)/$($(t)_ver).done))
227
228##########################################################################################
229
230# Default base config
231CONFIG = --target=$(TARGET) \
232    --host=$(HOST) --build=$(BUILD) \
233    --prefix=$(PREFIX)
234
235PATHEXT = $(RESULT)/$(BUILD)/bin:
236
237PATHPRE = PATH=$(PATHEXT)$(PATH)
238BUILDPAR = -j16
239
240# Default commands to when making
241MAKECMD =
242INSTALLCMD = install
243
244
245declare_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
246
247ifeq ($(HOST),$(BUILD))
248  ifeq ($(HOST),$(TARGET))
249    TOOLS = $(call declare_tools,_FOR_TARGET,)
250  endif
251endif
252
253TOOLS ?= $(call declare_tools,_FOR_TARGET,$(TARGET)-)
254
255##########################################################################################
256
257# Create a TARGET bfd + libiberty only.
258# Configure one or two times depending on mulitlib arch.
259# If multilib, the second should be 32-bit, and we resolve
260# CFLAG_<name> to most likely -m32.
261define mk_bfd
262  $$(info Libs for $(1))
263  $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \
264      : CFLAGS += $$(CFLAGS_$(1))
265  $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \
266      : LIBDIRS = --libdir=$(TARGETDIR)/$(1)
267
268  bfdlib += $$(TARGETDIR)/$$(binutils_ver)-$(subst /,-,$(1)).done
269  bfdmakes += $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile
270endef
271
272# Create one set of bfds etc for each multilib arch
273$(foreach l,$(LIBDIRS),$(eval $(call mk_bfd,$(l))))
274
275# Only build these two libs.
276$(bfdlib) : MAKECMD = all-libiberty all-bfd
277$(bfdlib) : INSTALLCMD = install-libiberty install-bfd
278
279# Building targets libbfd + libiberty. HOST==TARGET, i.e not
280# for a cross env.
281$(bfdmakes) : CONFIG = --target=$(TARGET) \
282    --host=$(TARGET) --build=$(BUILD) \
283    --prefix=$(TARGETDIR) \
284    --with-sysroot=$(SYSROOT) \
285    $(LIBDIRS)
286
287$(bfdmakes) : TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-)
288
289##########################################################################################
290
291$(gcc) \
292    $(binutils) \
293    $(gmp) \
294    $(mpfr) \
295    $(mpc) \
296    $(bfdmakes) \
297    $(ccache) : ENVS += $(TOOLS)
298
299# libdir to work around hateful bfd stuff installing into wrong dirs...
300# ensure we have 64 bit bfd support in the HOST library. I.e our
301# compiler on i686 will know 64 bit symbols, BUT later
302# we build just the libs again for TARGET, then with whatever the arch
303# wants.
304$(BUILDDIR)/$(binutils_ver)/Makefile : CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS))
305
306# Makefile creation. Simply run configure in build dir.
307$(bfdmakes) \
308$(BUILDDIR)/$(binutils_ver)/Makefile \
309    : $(BINUTILS_CFG)
310	$(info Configuring $@. Log in $(@D)/log.config)
311	@mkdir -p $(@D)
312	( \
313	  cd $(@D) ; \
314	  $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \
315	      $(BINUTILS_CFG) \
316	      $(CONFIG) \
317	      --with-sysroot=$(SYSROOT) \
318	      --disable-nls \
319	      --program-prefix=$(TARGET)- \
320	      --enable-multilib \
321	) > $(@D)/log.config 2>&1
322	@echo 'done'
323
324$(BUILDDIR)/$(mpfr_ver)/Makefile \
325    : $(MPFR_CFG)
326	$(info Configuring $@. Log in $(@D)/log.config)
327	@mkdir -p $(@D)
328	( \
329	  cd $(@D) ; \
330	  $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \
331	      $(MPFR_CFG) \
332	      $(CONFIG) \
333	      --program-prefix=$(TARGET)- \
334	      --enable-shared=no \
335	      --with-gmp=$(PREFIX) \
336	) > $(@D)/log.config 2>&1
337	@echo 'done'
338
339$(BUILDDIR)/$(gmp_ver)/Makefile \
340    : $(GMP_CFG)
341	$(info Configuring $@. Log in $(@D)/log.config)
342	@mkdir -p $(@D)
343	( \
344	  cd $(@D) ; \
345	  $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \
346	      $(GMP_CFG) \
347	      --host=$(HOST) --build=$(BUILD) \
348	      --prefix=$(PREFIX) \
349	      --disable-nls \
350	      --program-prefix=$(TARGET)- \
351	      --enable-shared=no \
352	      --with-mpfr=$(PREFIX) \
353	) > $(@D)/log.config 2>&1
354	@echo 'done'
355
356$(BUILDDIR)/$(mpc_ver)/Makefile \
357    : $(MPC_CFG)
358	$(info Configuring $@. Log in $(@D)/log.config)
359	@mkdir -p $(@D)
360	( \
361	  cd $(@D) ; \
362	  $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \
363	      $(MPC_CFG) \
364	      $(CONFIG) \
365	      --program-prefix=$(TARGET)- \
366	      --enable-shared=no \
367	      --with-mpfr=$(PREFIX) \
368	      --with-gmp=$(PREFIX) \
369	) > $(@D)/log.config 2>&1
370	@echo 'done'
371
372# Only valid if glibc target -> linux
373# proper destructor handling for c++
374ifneq (,$(findstring linux,$(TARGET)))
375  $(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --enable-__cxa_atexit
376endif
377
378# Want:
379# c,c++
380# shared libs
381# multilib (-m32/-m64 on x64)
382# skip native language.
383# and link and assemble with the binutils we created
384# earlier, so --with-gnu*
385$(BUILDDIR)/$(gcc_ver)/Makefile \
386    : $(GCC_CFG)
387	$(info Configuring $@. Log in $(@D)/log.config)
388	mkdir -p $(@D)
389	( \
390	  cd $(@D) ; \
391	  $(PATHPRE) $(ENVS) $(GCC_CFG) $(EXTRA_CFLAGS) \
392	      $(CONFIG) \
393	      --with-sysroot=$(SYSROOT) \
394	      --enable-languages=c,c++ \
395	      --enable-shared \
396	      --enable-multilib \
397	      --disable-nls \
398	      --with-gnu-as \
399	      --with-gnu-ld \
400	      --with-mpfr=$(PREFIX) \
401	      --with-gmp=$(PREFIX) \
402	      --with-mpc=$(PREFIX) \
403	) > $(@D)/log.config 2>&1
404	@echo 'done'
405
406# need binutils for gcc
407$(gcc) : $(binutils)
408
409# as of 4.3 or so need these for doing config
410$(BUILDDIR)/$(gcc_ver)/Makefile : $(gmp) $(mpfr) $(mpc)
411$(mpfr) : $(gmp)
412$(mpc) : $(gmp) $(mpfr)
413
414##########################################################################################
415# very straightforward. just build a ccache. it is only for host.
416$(BUILDDIR)/$(ccache_ver)/Makefile \
417    : $(CCACHE_CFG)
418	$(info Configuring $@. Log in $(@D)/log.config)
419	@mkdir -p $(@D)
420	@( \
421	  cd $(@D) ; \
422	  $(PATHPRE) $(ENVS) $(CCACHE_CFG) \
423	      $(CONFIG) \
424	) > $(@D)/log.config 2>&1
425	@echo 'done'
426
427gccpatch = $(TARGETDIR)/gcc-patched
428
429##########################################################################################
430# For some reason cpp is not created as a target-compiler
431ifeq ($(HOST),$(TARGET))
432  $(gccpatch) : $(gcc) link_libs
433	@echo -n 'Creating compiler symlinks...'
434	@for f in cpp; do \
435	  if [ ! -e $(PREFIX)/bin/$(TARGET)-$$f ]; \
436	  then \
437	    cd $(PREFIX)/bin && \
438	    ln -s $$f $(TARGET)-$$f ; \
439	  fi \
440	done
441	@touch $@
442	@echo 'done'
443
444  ##########################################################################################
445  # Ugly at best. Seems that when we compile host->host compiler, that are NOT
446  # the BUILD compiler, the result will not try searching for libs in package root.
447  # "Solve" this by create links from the target libdirs to where they are.
448  link_libs:
449	@echo -n 'Creating library symlinks...'
450	@$(foreach l,$(LIBDIRS), \
451	for f in `cd $(PREFIX)/$(l) && ls`; do \
452	  if [ ! -e $(TARGETDIR)/$(l)/$$f ]; then \
453	    mkdir -p $(TARGETDIR)/$(l) && \
454	    cd $(TARGETDIR)/$(l)/ && \
455	    ln -s $(if $(findstring /,$(l)),../,)../../$(l)/$$f $$f; \
456	  fi \
457	done;)
458	@echo 'done'
459else
460  $(gccpatch) :
461	@echo 'done'
462endif
463
464##########################################################################################
465# Build in two steps.
466# make <default>
467# make install.
468# Use path to our build hosts cross tools
469# Always need to build cross tools for build host self.
470$(TARGETDIR)/%.done : $(BUILDDIR)/%/Makefile
471	$(info Building $(basename $@). Log in $(<D)/log.build)
472	$(PATHPRE) $(ENVS) $(MAKE) $(BUILDPAR) -f $< -C $(<D) $(MAKECMD) $(MAKECMD.$(notdir $@)) > $(<D)/log.build 2>&1
473	@echo -n 'installing...'
474	$(PATHPRE) $(MAKE) $(INSTALLPAR) -f $< -C $(<D) $(INSTALLCMD) $(MAKECMD.$(notdir $@)) > $(<D)/log.install 2>&1
475	@touch $@
476	@echo 'done'
477
478##########################################################################################
479
480$(PREFIX)/devkit.info: FRC
481	@echo 'Creating devkit.info in the root of the kit'
482	rm -f $@
483	touch $@
484	echo '# This file describes to configure how to interpret the contents of this' >> $@
485	echo '# devkit' >> $@
486	echo '' >> $@
487	echo 'DEVKIT_NAME="$(gcc_ver) - $(LINUX_VERSION)"' >> $@
488	echo 'DEVKIT_TOOLCHAIN_PATH="$$DEVKIT_ROOT/bin"' >> $@
489	echo 'DEVKIT_SYSROOT="$$DEVKIT_ROOT/$$host/sysroot"' >> $@
490
491##########################################################################################
492
493ifeq ($(TARGET), $(HOST))
494  $(PREFIX)/bin/%:
495	@echo 'Creating missing $* soft link'
496	ln -s $(TARGET)-$* $@
497
498  missing-links := $(addprefix $(PREFIX)/bin/, \
499      addr2line ar as c++ c++filt elfedit g++ gcc gprof ld nm objcopy ranlib readelf \
500      size strings strip)
501endif
502
503##########################################################################################
504
505bfdlib : $(bfdlib)
506binutils : $(binutils)
507rpms : $(rpms)
508libs : $(libs)
509sysroot : rpms libs
510gcc : sysroot $(gcc) $(gccpatch)
511all : binutils gcc bfdlib $(PREFIX)/devkit.info $(missing-links) $(SYSROOT_LINKS)
512
513# this is only built for host. so separate.
514ccache : $(ccache)
515
516# Force target
517FRC:
518
519.PHONY : gcc all binutils bfdlib link_libs rpms libs sysroot
520