
# copyright Thomas Haller
# version 0.1

PREFIX				?= cross_compiler/

TARGET				?= x86_64-elf

DIR_DOWNLOAD		?= download/
DIR_SOURCE			?= source/
DIR_BUILD			?= build/

REL_DIR_DOWNLOAD	:= $(DIR_DOWNLOAD)
REL_DIR_SOURCE		:= $(DIR_SOURCE)
REL_DIR_BUILD		:= $(DIR_BUILD)

DIR_DOWNLOAD		:= $(abspath $(REL_DIR_DOWNLOAD))/
DIR_SOURCE			:= $(abspath $(REL_DIR_SOURCE))/
DIR_BUILD			:= $(abspath $(REL_DIR_BUILD))/

ABS_PREFIX			:= $(abspath $(PREFIX))
PATH 				:= $(ABS_PREFIX)/bin:$(PATH)
SYSROOT				:= $(ABS_PREFIX)/$(TARGET)/


BINUTILS_VERSION	:= 2.21.1
BINUTILS_SUBVERSION	:= 2.21.1a
GCC_VERSION			:= 4.6.1
GMP_VERSION			:= 5.0.2
MPFR_VERSION		:= 3.0.1
MPC_VERSION			:= 0.9
NEWLIB_VERSION		:= 1.19.0
BOCHS_VERSION		:= 2.4.6
GRUB2_VERSION		:= 1.99
XORRISO_VERSION		:= 1.1.4
GDB_VERSION			:= 7.3
GDB_SUBVERSION		:= 7.3a

BINUTILS_OPTIONS	:= --target=$(TARGET) --prefix=$(ABS_PREFIX) --disable-nls --with-sysroot=$(SYSROOT)
GCC_C_OPTIONS		:= --target=$(TARGET) --prefix=$(ABS_PREFIX) --disable-nls --with-sysroot=$(SYSROOT) --enable-languages=c --without-headers
GCC_CPP_OPTIONS		:= --target=$(TARGET) --prefix=$(ABS_PREFIX) --disable-nls --with-sysroot=$(SYSROOT) --enable-languages=c,c++ --with-newlib --enable-sjlj-exceptions=no
NEWLIB_OPTIONS		:= --target=$(TARGET) --prefix=$(ABS_PREFIX) --disable-nls --with-sysroot=$(SYSROOT)
GDB_OPTIONS			:= --target=$(TARGET) --prefix=$(ABS_PREFIX) --disable-nls --with-sysroot=$(SYSROOT)

BOCHS_OPTIONS		:=                    --prefix=$(ABS_PREFIX) --disable-nls --enable-all-optimizations --enable-iodebug --disable-plugins --disable-docbook --with-all-libs --enable-x86-64
BOCHS_OPTIONS_INT	:= --enable-smp --enable-debugger --enable-disasm --enable-debugger-gui
BOCHS_OPTIONS_GDB	:= --enable-gdb-stub
GRUB2_OPTIONS		:=                    --prefix=$(ABS_PREFIX) --disable-nls --sbindir=$(ABS_PREFIX)/bin
XORRISO_OPTIONS		:=                    --prefix=$(ABS_PREFIX) --disable-nls --sbindir=$(ABS_PREFIX)/bin



CPPFLAGS_FOR_TARGET	:= -ffunction-sections -fdata-sections
CPPFLAGS_FOR_TARGET	+= -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables
ifneq (,$(findstring x86_64,$(TARGET)))
CPPFLAGS_FOR_TARGET	+= -mcmodel=kernel
endif


BINUTILS_EXEC		:= $(ABS_PREFIX)/bin/$(TARGET)-as
GCC_C_EXEC			:= $(ABS_PREFIX)/bin/$(TARGET)-gcc
GCC_CPP_EXEC		:= $(ABS_PREFIX)/bin/$(TARGET)-g++
NEWLIB_EXEC			:= $(SYSROOT)/lib/libc.a
BOCHS_EXEC			:= $(ABS_PREFIX)/bin/bochs
GRUB2_EXEC			:= $(ABS_PREFIX)/bin/grub-install
XORRISO_EXEC		:= $(ABS_PREFIX)/bin/xorriso
GDB_EXEC			:= $(ABS_PREFIX)/bin/$(TARGET)-gdb


LOG					 = @echo "$@ : $?" >> make.log

# phony names for all tools
ALL_TARGETS			:= binutils gcc_c gcc_cpp newlib bochs grub2 xorriso gdb

# standard targets
.PHONY: all clean usage $(ALL_TARGETS)

usage:
	$(LOG)
	@echo usage: make \<target\>
	@echo
	@echo possible targets: all clean $(ALL_TARGETS)
	@echo
	@echo you may want to set the following environment variables:
	@echo
	@echo "PREFIX            default cross_compiler/  currently:" $(PREFIX)
	@echo "TARGET            default x86_64-elf       currently:" $(TARGET)
	@echo "DIR_DOWNLOAD      default download/        currently:" $(REL_DIR_DOWNLOAD)
	@echo "DIR_SOURCE        default source/          currently:" $(REL_DIR_SOURCE)
	@echo "DIR_BUILD         default build/           currently:" $(REL_DIR_BUILD)

all: $(ALL_TARGETS)
	$(LOG)

clean:
	$(LOG)
	rm -rf $(DIR_SOURCE)
	rm -rf $(DIR_BUILD)

$(DIR_DOWNLOAD):
	mkdir -p $(DIR_DOWNLOAD)

$(DIR_SOURCE):
	mkdir -p $(DIR_SOURCE)



# binutils
binutils: $(BINUTILS_EXEC)
	$(LOG)

$(DIR_DOWNLOAD)binutils-$(BINUTILS_SUBVERSION).tar.bz2: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://ftpmirror.gnu.org/binutils/binutils-$(BINUTILS_SUBVERSION).tar.bz2

$(DIR_SOURCE)binutils-$(BINUTILS_VERSION)/ping: $(DIR_DOWNLOAD)binutils-$(BINUTILS_SUBVERSION).tar.bz2 | $(DIR_SOURCE)
	$(LOG)
	tar xvj -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)binutils-$(BINUTILS_SUBVERSION).tar.bz2
	touch $(DIR_SOURCE)binutils-$(BINUTILS_VERSION)/ping

$(BINUTILS_EXEC): $(DIR_SOURCE)binutils-$(BINUTILS_VERSION)/ping
	$(LOG)
	mkdir -p $(DIR_BUILD)binutils-$(BINUTILS_VERSION)-$(TARGET)
	cd $(DIR_BUILD)binutils-$(BINUTILS_VERSION)-$(TARGET); $(DIR_SOURCE)binutils-$(BINUTILS_VERSION)/configure  $(BINUTILS_OPTIONS)
	cd $(DIR_BUILD)binutils-$(BINUTILS_VERSION)-$(TARGET); $(MAKE) all
	cd $(DIR_BUILD)binutils-$(BINUTILS_VERSION)-$(TARGET); $(MAKE) install



# gcc
gcc_c: $(GCC_C_EXEC)
	$(LOG)
gcc_cpp: $(GCC_CPP_EXEC)
	$(LOG)

$(DIR_DOWNLOAD)gcc-$(GCC_VERSION).tar.bz2: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://ftpmirror.gnu.org/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.bz2

$(DIR_DOWNLOAD)gmp-$(GMP_VERSION).tar.bz2: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://ftpmirror.gnu.org/gmp/gmp-$(GMP_VERSION).tar.bz2

$(DIR_DOWNLOAD)mpfr-$(MPFR_VERSION).tar.bz2: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://ftpmirror.gnu.org/mpfr/mpfr-$(MPFR_VERSION).tar.bz2

$(DIR_DOWNLOAD)mpc-$(MPC_VERSION).tar.gz: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://www.multiprecision.org/mpc/download/mpc-$(MPC_VERSION).tar.gz

$(DIR_SOURCE)gcc-$(GCC_VERSION)/ping: $(DIR_DOWNLOAD)gcc-$(GCC_VERSION).tar.bz2 | $(DIR_SOURCE)
	$(LOG)
	tar xvj -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)gcc-$(GCC_VERSION).tar.bz2
	touch $(DIR_SOURCE)gcc-$(GCC_VERSION)/ping

$(DIR_SOURCE)gcc-$(GCC_VERSION)/gmp/ping: $(DIR_DOWNLOAD)gmp-$(GMP_VERSION).tar.bz2 $(DIR_SOURCE)gcc-$(GCC_VERSION)/ping
	$(LOG)
	tar xvj -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)gmp-$(GMP_VERSION).tar.bz2
	ln -sf $(DIR_SOURCE)gmp-$(GMP_VERSION) $(DIR_SOURCE)gcc-$(GCC_VERSION)/gmp
	touch $(DIR_SOURCE)gcc-$(GCC_VERSION)/gmp/ping

$(DIR_SOURCE)gcc-$(GCC_VERSION)/mpfr/ping: $(DIR_DOWNLOAD)mpfr-$(MPFR_VERSION).tar.bz2 $(DIR_SOURCE)gcc-$(GCC_VERSION)/ping
	$(LOG)
	tar xvj -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)mpfr-$(MPFR_VERSION).tar.bz2
	ln -sf $(DIR_SOURCE)mpfr-$(MPFR_VERSION) $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpfr
	touch $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpfr/ping

$(DIR_SOURCE)gcc-$(GCC_VERSION)/mpc/ping: $(DIR_DOWNLOAD)mpc-$(MPC_VERSION).tar.gz $(DIR_SOURCE)gcc-$(GCC_VERSION)/ping
	$(LOG)
	tar xvz -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)mpc-$(MPC_VERSION).tar.gz
	ln -sf $(DIR_SOURCE)mpc-$(MPC_VERSION) $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpc
	touch $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpc/ping

$(GCC_C_EXEC): export CPPFLAGS_FOR_TARGET := $(CPPFLAGS_FOR_TARGET)
$(GCC_C_EXEC): $(DIR_SOURCE)gcc-$(GCC_VERSION)/ping $(DIR_SOURCE)gcc-$(GCC_VERSION)/gmp/ping $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpfr/ping $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpc/ping $(BINUTILS_EXEC)
	$(LOG)
	mkdir -p $(SYSROOT)/usr/include
	mkdir -p $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-c
	cd $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-c; $(DIR_SOURCE)gcc-$(GCC_VERSION)/configure $(GCC_C_OPTIONS)
	cd $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-c; $(MAKE) all-gcc
	cd $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-c; $(MAKE) install-gcc

$(GCC_CPP_EXEC): export CPPFLAGS_FOR_TARGET := $(CPPFLAGS_FOR_TARGET)
$(GCC_CPP_EXEC): $(DIR_SOURCE)gcc-$(GCC_VERSION)/ping $(DIR_SOURCE)gcc-$(GCC_VERSION)/gmp/ping $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpfr/ping $(DIR_SOURCE)gcc-$(GCC_VERSION)/mpc/ping $(BINUTILS_EXEC) $(NEWLIB_EXEC)
	$(LOG)
	mkdir -p $(SYSROOT)/usr/include
	mkdir -p $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-cpp
	cd $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-cpp; $(DIR_SOURCE)gcc-$(GCC_VERSION)/configure $(GCC_CPP_OPTIONS)
	cd $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-cpp; $(MAKE) all
	cd $(DIR_BUILD)gcc-$(GCC_VERSION)-$(TARGET)-cpp; $(MAKE) install


# newlib
newlib: $(NEWLIB_EXEC)
	$(LOG)

$(DIR_DOWNLOAD)newlib-$(NEWLIB_VERSION).tar.gz: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) ftp://sources.redhat.com/pub/newlib/newlib-$(NEWLIB_VERSION).tar.gz

$(DIR_SOURCE)newlib-$(NEWLIB_VERSION)/ping: $(DIR_DOWNLOAD)newlib-$(NEWLIB_VERSION).tar.gz | $(DIR_SOURCE)
	$(LOG)
	tar xvz -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)newlib-$(NEWLIB_VERSION).tar.gz
	touch $(DIR_SOURCE)newlib-$(NEWLIB_VERSION)/ping

$(NEWLIB_EXEC): export CPPFLAGS_FOR_TARGET := $(CPPFLAGS_FOR_TARGET)
$(NEWLIB_EXEC): $(DIR_SOURCE)newlib-$(NEWLIB_VERSION)/ping | $(GCC_C_EXEC)
	$(LOG)
	mkdir -p $(DIR_BUILD)newlib-$(NEWLIB_VERSION)-$(TARGET)
	cd $(DIR_BUILD)newlib-$(NEWLIB_VERSION)-$(TARGET); $(DIR_SOURCE)newlib-$(NEWLIB_VERSION)/configure  $(NEWLIB_OPTIONS)
	cd $(DIR_BUILD)newlib-$(NEWLIB_VERSION)-$(TARGET); $(MAKE) all
	cd $(DIR_BUILD)newlib-$(NEWLIB_VERSION)-$(TARGET); $(MAKE) install



#bochs
bochs: $(BOCHS_EXEC)
	$(LOG)

$(DIR_DOWNLOAD)bochs-$(BOCHS_VERSION).tar.gz: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://downloads.sourceforge.net/project/bochs/bochs/$(BOCHS_VERSION)/bochs-$(BOCHS_VERSION).tar.gz

$(DIR_SOURCE)bochs-$(BOCHS_VERSION)/ping: $(DIR_DOWNLOAD)bochs-$(BOCHS_VERSION).tar.gz | $(DIR_SOURCE)
	$(LOG)
	tar xvz -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)bochs-$(BOCHS_VERSION).tar.gz
	touch $(DIR_SOURCE)bochs-$(BOCHS_VERSION)/ping

$(BOCHS_EXEC): $(DIR_SOURCE)bochs-$(BOCHS_VERSION)/ping
	$(LOG)
	mkdir -p $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET)-gdb
	cd $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET)-gdb; $(DIR_SOURCE)bochs-$(BOCHS_VERSION)/configure $(BOCHS_OPTIONS) $(BOCHS_OPTIONS_GDB)
	cd $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET)-gdb; $(MAKE)
	cd $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET)-gdb; $(MAKE) install
	mv $(BOCHS_EXEC) $(BOCHS_EXEC)-gdb
	mkdir -p $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET)
	cd $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET); $(DIR_SOURCE)bochs-$(BOCHS_VERSION)/configure $(BOCHS_OPTIONS) $(BOCHS_OPTIONS_INT)
	cd $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET); $(MAKE)
	cd $(DIR_BUILD)bochs-$(BOCHS_VERSION)-$(TARGET); $(MAKE) install



#grub2
grub2: $(GRUB2_EXEC)
	$(LOG)

$(DIR_DOWNLOAD)grub-$(GRUB2_VERSION).tar.gz: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://ftpmirror.gnu.org/grub/grub-$(GRUB2_VERSION).tar.gz

$(DIR_SOURCE)grub-$(GRUB2_VERSION)/ping: $(DIR_DOWNLOAD)grub-$(GRUB2_VERSION).tar.gz | $(DIR_SOURCE)
	$(LOG)
	tar xvz -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)grub-$(GRUB2_VERSION).tar.gz
	cp grub2.patch $(DIR_SOURCE)grub-$(GRUB2_VERSION)/
	cd $(DIR_SOURCE)grub-$(GRUB2_VERSION)/; patch -p 1 < grub2.patch	
	touch source/grub-$(GRUB2_VERSION)/ping

$(GRUB2_EXEC): $(DIR_SOURCE)grub-$(GRUB2_VERSION)/ping
	$(LOG)
	mkdir -p $(DIR_BUILD)grub-$(GRUB2_VERSION)
	cd $(DIR_BUILD)grub-$(GRUB2_VERSION); $(DIR_SOURCE)grub-$(GRUB2_VERSION)/configure  $(GRUB2_OPTIONS)
	cd $(DIR_BUILD)grub-$(GRUB2_VERSION); $(MAKE)
	cd $(DIR_BUILD)grub-$(GRUB2_VERSION); $(MAKE) install



#xorriso
xorriso: $(XORRISO_EXEC)

$(DIR_DOWNLOAD)xorriso-$(XORRISO_VERSION).tar.gz: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://ftpmirror.gnu.org/xorriso/xorriso-$(XORRISO_VERSION).tar.gz

$(DIR_SOURCE)xorriso-$(XORRISO_VERSION)/ping: $(DIR_DOWNLOAD)xorriso-$(XORRISO_VERSION).tar.gz | $(DIR_SOURCE)
	$(LOG)
	tar xvz -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)xorriso-$(XORRISO_VERSION).tar.gz
	touch $(DIR_SOURCE)xorriso-$(XORRISO_VERSION)/ping

$(XORRISO_EXEC): $(DIR_SOURCE)xorriso-$(XORRISO_VERSION)/ping
	$(LOG)
	rm -rf $(DIR_BUILD)xorriso-$(XORRISO_VERSION)
	cp -R $(DIR_SOURCE)xorriso-$(XORRISO_VERSION) $(DIR_BUILD)xorriso-$(XORRISO_VERSION)
	cd $(DIR_BUILD)xorriso-$(XORRISO_VERSION); ./configure  $(XORRISO_OPTIONS)
	cd $(DIR_BUILD)xorriso-$(XORRISO_VERSION); $(MAKE)
	cd $(DIR_BUILD)xorriso-$(XORRISO_VERSION); $(MAKE) install



#gdb
gdb: $(GDB_EXEC)
	$(LOG)

$(DIR_DOWNLOAD)gdb-$(GDB_SUBVERSION).tar.bz2: | $(DIR_DOWNLOAD)
	$(LOG)
	wget -P $(DIR_DOWNLOAD) http://ftpmirror.gnu.org/gdb/gdb-$(GDB_SUBVERSION).tar.bz2

$(DIR_SOURCE)gdb-$(GDB_VERSION)/ping: $(DIR_DOWNLOAD)gdb-$(GDB_SUBVERSION).tar.bz2 | $(DIR_SOURCE)
	$(LOG)
	tar xvj -C $(DIR_SOURCE) -f $(DIR_DOWNLOAD)gdb-$(GDB_SUBVERSION).tar.bz2
	cp gdb.patch $(DIR_SOURCE)gdb-$(GDB_VERSION)/
	cd $(DIR_SOURCE)gdb-$(GDB_VERSION)/; patch -p 1 < gdb.patch	
	touch $(DIR_SOURCE)gdb-$(GDB_VERSION)/ping

$(GDB_EXEC): $(DIR_SOURCE)gdb-$(GDB_VERSION)/ping
	$(LOG)
	mkdir -p $(DIR_BUILD)gdb-$(GDB_VERSION)-$(TARGET)
	cd $(DIR_BUILD)gdb-$(GDB_VERSION)-$(TARGET); $(DIR_SOURCE)gdb-$(GDB_VERSION)/configure $(GDB_OPTIONS)
	cd $(DIR_BUILD)gdb-$(GDB_VERSION)-$(TARGET); $(MAKE)
	cd $(DIR_BUILD)gdb-$(GDB_VERSION)-$(TARGET); $(MAKE) install
