# -*- Makefile -*-
# vim:set ft=make:
#
# DROPS (Dresden Realtime OPerating System) Component
#
# Make configuration file
#
# $Id: Makeconf 418 2008-11-12 03:50:31Z l4check $
#
# $Author: l4check $
#
# This file is included by all Makefile-templates. This file defines macros
# for div commands, sets general DROPS-Makefile variables, ensures the
# dependencies from the various Makeconf.locals, defines the messages for
# div actions, and permits the dependency-creation on clean-rules.
#
# The macros BUILD_MULTIPLE_ARCHITECTURES and BUILD_ONE_ARCHITECTURE are
# defined here.
#
# BUILD_MULTIPLE_ARCHITECTURES is set if ARCHS is set to multiple
# architectures in the Makefile. If ARCHS is not set, the default value
# l4_i386 will be assumed, not defining BUILD_MULTIPLE_ARCHITECTURES.
# In the muli-arch case, binary.inc triggers build the files into subdirs,
# dir-name is the architecture. Then, make is called recursively with ARCH
# set to one architecture.
#
# BUILD_ONE_ARCHITECTURE is set if ARCH contains one architecture, and we
# actually build files (in subdirs for multi-arch case, in the same dir in
# the single-arch case).

ifeq ($(origin _L4DIR_MK_MAKECONF),undefined)
_L4DIR_MK_MAKECONF=y

SYSTEMS = x86-l4v2
ARCH = x86

# the default target is all
all::

# make .general.d dependent on the role-file
$(if $(ROLE),$(OBJ_DIR)/.general.d: $(L4DIR)/mk/$(ROLE))

SYSTEM_TARGET	  = $(SYSTEM_TARGET_$(ARCH))
SYSTEM_TARGET_arm = arm-linux-

CARCHFLAGS_amd64  = -mno-red-zone
ASFLAGS_amd64     = -m64

LD_EMULATION_amd64= elf_x86_64
LD_EMULATION_arm  = armelf
LD_EMULATION_x86  = elf_i386
LD_EMULATION      = $(LD_EMULATION_$(ARCH))

OFORMAT_amd64     = elf64-x86-64
OFORMAT_arm       = default
OFORMAT_x86       = elf32-i386
OFORMAT           = $(OFORMAT_$(ARCH))

# This is quite bad: There is no other chance to disable the page-alignedment
# of the linker. The linker aligns the first section at 0x100000 for AMD64!
# We don't want this. Be careful for interactions with objcopy -S!
LDNMAGIC           ?= -n
LDFLAGS_amd64      += $(LDNMAGIC)

CARCHFLAGS_x86_586        = -march=i586
CARCHFLAGS_x86_pentium    = -march=i586
CARCHFLAGS_x86_pentiummmx = -march=pentium-mmx
CARCHFLAGS_x86_pentiumpro = -march=pentiumpro
CARCHFLAGS_x86_686        = -march=i686
CARCHFLAGS_x86_pentium2   = -march=pentium2
CARCHFLAGS_x86_pentium3   = -march=pentium3
CARCHFLAGS_x86_pentiumm   = -march=pentium-m
CARCHFLAGS_x86_pentium4   = -march=pentium4
CARCHFLAGS_x86_prescott   = -march=prescott
CARCHFLAGS_x86_nocona     = -march=nocona
CARCHFLAGS_x86_K6         = -march=k6
CARCHFLAGS_x86_K7         = -march=athlon
CARCHFLAGS_x86_athlon4    = -march=athlon-4
CARCHFLAGS_x86_K8         = -march=k8
CARCHFLAGS_x86_opteron    = -march=opteron

IDL_SYSTEMS 	= x86-l4v2

AR		= $(SYSTEM_TARGET)ar
AS		= $(SYSTEM_TARGET)as
AWKP		= gawk --posix
CVS		= cvs -q
SVN		= svn
CP		= cp
DICE_SRCDIR	?= $(L4DIR)/../dice
DICE_OBJDIR	?= $(DICE_SRCDIR)
DICE		= $(firstword $(wildcard $(DICE_OBJDIR)/src/dice \
				$(DROPS_STDDIR)/tool/bin/dice \
				 $(shell which dice 2>/dev/null) ) \
				 did_not_find_dice___please_install_dice )
DICE_CPP_NAME	= cpp0

DICE_INCDIR	?= $(DICE_SRCDIR)/include

ECHO		= echo

GENOFFSETS	= $(L4DIR)/tool/bin/genoffsets.pl
GOSH		= $(firstword $(wildcard $(L4DIR)/../tools/gosh/gosh \
				$(DROPS_STDDIR)/tool/bin/gosh \
				 $(shell which gosh 2>/dev/null) ) \
				 did_not_find_gosh___please_install_gosh )
HOST_CC		= gcc
HOST_CXX	= g++
INDENT		= indent -sob
INSTALL		= install
# the following two variables should be overwritten in Makeconf.bid.local
LD		= $(SYSTEM_TARGET)ld
LATEX		= latex
PDFLATEX	= pdflatex
GREP		= grep
LN		= ln
MKDIR		= mkdir -p
MKFLAGS		+=$(MKFLAGS_$@)
NM		= $(SYSTEM_TARGET)nm
OBJCOPY		= $(SYSTEM_TARGET)objcopy
PWDCMD		= sh -c pwd
RANLIB		= $(SYSTEM_TARGET)ranlib
RM		= rm -f
SCRUB		= $(RM) $(wildcard *.old) $(wildcard *~) $(wildcard *.bak) \
                        $(wildcard \#*\#)
SED		= sed
SHELL		= /bin/bash
SIZE		= $(SYSTEM_TARGET)size
STRIP		= $(SYSTEM_TARGET)strip
TR		= tr
GEN_DOPECODE	= $(L4DIR)/tool/gen_dopecode/gen_dopecode
ABS2REL		= $(L4DIR)/tool/bin/abs2rel.sh
# it's optional to be able to set it as environment variable
FIASCOUX	?= $(L4DIR)/../kernel/fiasco/build-ux/fiasco
DISASM_CMD      ?= $(SYSTEM_TARGET)objdump -ld $(1) | less

# functions that are handy
absfilename_target_dir_needs_to_exist = $(foreach w,$(1),$(addsuffix /$(notdir $(w)),$(shell cd $(dir $(w)) 2>/dev/null&&$(PWDCMD))))
absfilename     = $(shell $(L4DIR)/mk/rel2abs.sh $(1))
findfile	= $(firstword $(wildcard $(addsuffix /$(1),$(2))) $(1)_NOT_FOUND)

# include this one early to be able to set OBJ_BASE
-include $(L4DIR)/Makeconf.local

#ifeq ($(filter $(IGNORE_OBJDIR_TARGETS),$(MAKECMDGOALS)),)
# output directory
#ifeq ($(O)$(OBJ_BASE),)
#$(error need to give builddir with O=.../builddir)
#else
#ifneq ($(O),)
#ifeq ($(origin OBJ_BASE),undefined)
#OBJ_BASE := $(call absfilename, $(O))
#export OBJ_BASE
#endif
#endif
#endif
#endif

ifeq ($(origin L4DIR_ABS),undefined)
L4DIR_ABS      := $(call absfilename,$(L4DIR))
endif
ifeq ($(origin PKGDIR_ABS),undefined)
PKGDIR_ABS     := $(call absfilename,$(PKGDIR))
endif
ifeq ($(origin SRC_DIR),undefined)
SRC_DIR        := $(shell pwd)
endif
ifeq ($(origin SRC_BASE_ABS),undefined)
SRC_BASE     ?= $(L4DIR)
SRC_BASE_ABS := $(call absfilename,$(SRC_BASE))
export SRC_BASE_ABS
endif
ifeq ($(origin OBJ_DIR),undefined)
OBJ_DIR        := $(subst $(SRC_BASE_ABS),$(OBJ_BASE),$(SRC_DIR))
endif
ifeq ($(origin PKGDIR_OBJ),undefined)
PKGDIR_OBJ     := $(call absfilename,$(OBJ_DIR)/$(PKGDIR))
endif

# if PKGDIR is not in L4DIR, we have an external package, so make up some
# build-dir for it
ifneq ($(patsubst $(L4DIR_ABS)/%,,$(PKGDIR_ABS)),)
ifneq ($(filter-out $(OBJ_BASE)/ext-pkg%,$(PKGDIR_OBJ)),)
PKGDIR_OBJ     := $(OBJ_BASE)/ext-pkg$(PKGDIR_OBJ)
OBJ_DIR        := $(OBJ_BASE)/ext-pkg$(OBJ_DIR)
endif
endif

# sanity check the object dir
ifneq ($(SRC_BASE_ABS),$(OBJ_BASE))
ifeq ($(SRC_DIR),$(OBJ_DIR))
$(warning Sorry, your object or source path became garbled.)
$(warning OBJ_BASE: $(OBJ_BASE))
$(warning SRC_BASE_ABS: $(SRC_BASE_ABS))
$(warning SRC_DIR: $(SRC_DIR))
$(warning OBJ_DIR: $(OBJ_DIR))
$(warning PKGDIR: $(PKGDIR))
$(warning L4DIR_ABS: $(L4DIR_ABS))
$(warning PKGDIR_ABS: $(PKGDIR_ABS))
$(warning PKGDIR_OBJ: $(PKGDIR_OBJ))
$(error Please investigate.)
endif
endif


OBJ_DIR_EXPORT = $(OBJ_DIR)
export OBJ_DIR_EXPORT

VPATH_SRC_BASE ?= $(SRC_DIR)

# Makeconf.local handling
# dont use -include here, as we have special build conditions in $(L4DIR)/
#ifeq ($(origin BID_ROOT_CONF),undefined)
#BID_ROOT_CONF := $(call absfilename, $(OBJ_BASE))/Makeconf.bid.local
#endif
#ifeq ($(filter $(IGNORE_OBJDIR_TARGETS),$(MAKECMDGOALS)),)
#ifeq ($(wildcard $(BID_ROOT_CONF)),)
#ifeq ($(BID_IGN_ROOT_CONF),)
#$(error No configuration file found in build directory "$(OBJ_BASE)". Please run "make O=/path/to/objdir config" in "$(L4DIR_ABS)" or specify a valid build directory)
#endif
#else
#include $(BID_ROOT_CONF)
#endif
#endif

#-include $(L4DIR)/Makeconf.$(CONFIG_LABEL)

#-include $(OBJ_BASE)/Makeconf.local
#ifneq ($(PKGDIR),)
#-include $(PKGDIR)/Makeconf.local
#endif
# if it is not already set, we use this in the local dir
MAKECONFLOCAL ?= Makeconf.local
-include $(MAKECONFLOCAL)

DROPS_STDDIR	?= $(PKGDIR)/build
ifeq ($(STATICFILE),)
STATICFILE	= $(OBJ_BASE)/pkg/STATIC $(L4DIR)/pkg/STATIC
endif

# a nasty workaround for make-3.79/make-3.80. The former needs an additional
# $$ for $-quotation when calling a function.
BID_IDENT	= $(1)
ifeq ($(call BID_IDENT,$$),)
BID_DOLLARQUOTE	= $$
endif
BID_COMMA	= ,

ifneq ($(PL),)
PL_j := -j $(PL)
export PL
endif

#include $(L4DIR)/mk/config.inc

ifeq ($(HAVE_LDSO),y)
# MAKEDEP-call:
# arg1 - compiler binary name
# arg2 - [opt] compiler target. Will be written as target within the
# 	       dependency file
# arg3 - [opt] name of the dependency file. If unset, .<arg2>.d will be used.
# arg4 - [opt] alternative binary name
ifeq ($(origin BID_LIBGENDEP), undefined)
BID_LIBGENDEP := $(firstword $(wildcard $(call absfilename, \
				$(OBJ_BASE)/tool/gendep/libgendep.so \
				$(DROPS_STDDIR)/tool/lib/libgendep.so )))
endif

ifeq ($(HOST_SYSTEM),linux)
	LD_PRELOAD = LD_PRELOAD
endif
ifeq ($(HOST_SYSTEM),darwin)
	LD_PRELOAD = DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES
endif
MAKEDEP=$(LD_PRELOAD)=$(BID_LIBGENDEP) GENDEP_TARGET=$(if $(2),$(2),$@) \
		    GENDEP_BINARY=$(1) $(if $(3),GENDEP_DEPFILE=$(3)) \
		    $(if $(4),GENDEP_BINARY_ALT1=$(4))
endif

# macros used here and in packages
checkcc   = $(shell if $(CC) $(1) -o /dev/null -c -x c \
                    /dev/null > /dev/null 2>&1; then echo "$(1)"; fi)
checkcxx  = $(shell if $(CXX) $(1) -o /dev/null -c -x c++ \
                    /dev/null > /dev/null 2>&1; then echo "$(1)"; fi)

# the gcc specific variables: version, base dir, include dir, gcc lib
# note: determining these variables is slow, and the values should
#       be set in Makeconf.bid.local. However, this is the place were
#       they are determined on a 'make config' in $(L4DIR)
GCCVERSION_f	= $(shell $(CC) -dumpversion | sed -e 's/\(.*\)\..*/\1/')
GCCMAJORVERSION_f=$(shell $(CC) -dumpversion | sed -e 's/\([^.]*\).*/\1/')
GCCMINORVERSION_f=$(shell $(CC) -dumpversion | sed -e 's/[^.]*\.\([^.]*\).*/\1/')
GCCSUBVERSION_f	= $(shell $(CC) -dumpversion | sed -e 's/.*\.\(.*\)/\1/')
GCCDIR_f	= $(shell LC_ALL=C $(CC) -print-search-dirs|sed -ne 's+^install: \(.*[^/][^/]*\)/+\1+p' )
GCCLIB_f	= $(shell $(CC) -print-libgcc-file-name)
GCCLIB_EH_f	= $(filter /%,$(shell $(CC) -print-file-name=libgcc_eh.a))
GCCINCDIR_f	= $(addprefix $(call GCCDIR_f),/include /include-fixed)
GCCNOSTACKPROTOPT_f= $(call checkcc,-fno-stack-protector)

GCCINCDIR	= $(GCCDIR)/include $(GCCDIR)/include-fixed
I_GCCINCDIR	= $(addprefix -I,$(GCCINCDIR))

ifneq ($(PKGDIR),)
  ifeq ($(origin PKGNAME),undefined)
    PKGNAME := $(notdir $(shell cd $(PKGDIR);pwd))
  endif
endif

ifeq ($(V),1)
  VERBOSE =
endif
ifeq ($(V),0)
  VERBOSE = @
endif

# indicate if we are using dietlibc or uClibc
ifeq ($(USE_DIETLIBC),y)
# dietlibc explicitly set for all architectures
  DEFINES	+= -DUSE_DIETLIBC=y
  USE_DIETLIBC	= y
  LIBC_TYPE	= diet
  $(warning The use of dietlibc is deprecated, please switch to uclibc.)
  $(warning Dietlibc will soon be removed from the tree.)
else
  # uClibc explicitly set for all architectures
  DEFINES	+= #-DUSE_UCLIBC=y
  USE_UCLIBC	= #y
  LIBC_TYPE	= uc
endif

ifeq ($(RELEASE_MODE),y)
DEFINES		+= -DL4BID_RELEASE_MODE
endif

ifeq ($(USE_TASKLIB),y)
DEFINES		+= -DUSE_TASKLIB=y
endif

ifeq ($(ARCH),arm)
ifeq ($(RAM_BASE),)
$(error RAM_BASE not given, needed for ARM architecture builds.)
endif
else #arch != arm
  RAM_BASE	= 0x0
endif

DEFINES         += -DRAM_BASE=$(RAM_BASE)


ifneq ($(filter linux l4linux host,$(MODE)),)
HOST_LINK      := 1
endif

#
# SUBDIR handling, not within the OBJ-*/ dirs
#
ifeq ($(SYSTEM),)
ifneq ($(SUBDIRS),)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
	$(VERBOSE)PWD=$(PWD)/$@ $(MAKE) -C $@ all

# we know that SUBDIRS isn't empty, hence we can avoid the dir-test
scrub clean cleanall::
	$(VERBOSE)set -e; $(foreach i,$(SUBDIRS), \
		PWD=$(PWD)/$(i) $(MAKE) -C $(i) $@ $(MKFLAGS) $(MKFLAGS_$(i));)

install:: $(SUBDIRS)
	$(VERBOSE)set -e; $(foreach i,$(SUBDIRS), \
		PWD=$(PWD)/$(i) $(MAKE) -C $(i) $@ $(MKFLAGS) $(MKFLAGS_$(i));)

endif

all:: $(OBJ_DIR)/Makefile

$(OBJ_DIR)/Makefile: $(L4DIR)/mk/Makeconf
	$(VERBOSE)install -d $(dir $@)
	$(VERBOSE)echo '# automatically created -- modifications will be lost' > $@
	$(VERBOSE)echo 'SRC := $(SRC_DIR)'                                    >> $@
	$(VERBOSE)echo 'OBJ := $(OBJ_BASE)'                                   >> $@
	$(VERBOSE)echo '.PHONY: x $$(MAKECMDGOALS)'                           >> $@
	$(VERBOSE)echo 'x:'                                                   >> $@
	$(VERBOSE)echo '	PWD=$$(SRC) $$(MAKE) -C $$(SRC) O=$$(OBJ)'    >> $@
	$(VERBOSE)echo '$$(MAKECMDGOALS):'                                    >> $@
	$(VERBOSE)echo '	PWD=$$(SRC) $$(MAKE) -C $$(SRC) O=$$(OBJ) $$@'>> $@

else
# we are within an OBJ-*/ dir, create dummy target
$(SUBDIRS):
endif

#
# Dependency section
#
#

# the general dependencies: All generated files depend on ".general.d".
# ".general.d" itself depends on the mk-Makeconf, the optional
# Makeconf.local, the Makeconf.bid.local, the packet-Makeconf.local and the
# Makeconf.local. This ensures a rebuilt if any of the configuration-
# or make-files changes.
#
# We have this nasty if-readable-magic to allow the files to disappear
# or to appear. Depending on if the according makeconf exists now, the
# if-readable magic .general.d is used on existance or non-existence.

BID_DEPEND_GENERAL_D_COND = \
	if [ -r $(1) ] ; then echo -e '$@: $(1)\n$(1):\n' >>$@ ; \
	  else echo '$$(if $$(wildcard $(1)), $@: FORCE)' >>$@; fi

ifeq ($(SYSTEM),)
GENERAL_D_LOC := $(OBJ_DIR)/.general.d
else
GENERAL_D_LOC := .general.d
endif

$(GENERAL_D_LOC): $(L4DIR)/mk/Makeconf
	@$(BUILD_MESSAGE)
	@install -d $(dir $@)
	$(DEPEND_VERBOSE)echo '$@: $(SRC_DIR)/Makefile ' > $@
	$(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\
		$(OBJ_BASE)/Makeconf.bid.local)
	$(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\
		$(OBJ_BASE)/Makeconf.local)
	$(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\
		$(L4DIR)/Makeconf.local)
	$(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\
		$(L4DIR)/Makeconf.$(CONFIG_LABEL))
	$(if $(PKGDIR),$(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\
		$(PKGDIR)/Makeconf.local))
	$(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\
		$(MAKECONFLOCAL))

DEPS	+= $(GENERAL_D_LOC)

ifneq ($(DEPENDS_PKGS),)
DEPENDS_PKGS_MISSING := $(strip $(foreach i,$(DEPENDS_PKGS),		\
	                          $(if $(wildcard $(L4DIR)/pkg/$(i)),,$(i))))

ifneq ($(DEPENDS_PKGS_MISSING),)
# clear TARGET to prevent building anything
TARGET =
all::
	@echo -e "\033[32mPackage dependencies missing: \033[1m$(DEPENDS_PKGS_MISSING)\033[22m, skipping.\033[0m"
endif
endif

#
# Messages
#

# set SHOWMESSAGES=true or 'y' to print textual action descriptions
SHOWMESSAGES ?= true

# coloring on color-capable terminals
# enabled by setting BID_COLORED_PHASES to y
ifeq ($(BID_COLORED_PHASES),y)
ifeq ($(COLOR_TERMINAL),y)
  EMPHSTART = '\033[34m'
  EMPHSTOP  = '\033[0m'
else
  EMPHSTART =
  EMPHSTOP  =
endif
endif


ifneq (,$(filter y true, $(SHOWMESSAGES)))
AR_MESSAGE?=	echo -e "  ==> Archiving into $@"
BUILD_MESSAGE?=	echo -e "  ... Building $@"
BUILT_MESSAGE?= echo -e $(EMPHSTART)'  ==> "$@" built'$(EMPHSTOP)
COMP_MESSAGE?=	echo -e "  ... Compiling $@"
COMP_P_MESSAGE?=echo -e "  ... Compiling PIC $@"
COMP_PR_MESSAGE?=echo -e "  ... Compiling PROFILE $@"
GEN_MESSAGE?=	echo -e "  ... Generating $@"
LINK_MESSAGE?=	echo -e "  ==> Linking $@"
LINK_SHARED_MESSAGE?=	echo -e "  ==> Linking to shared $@"
LINK_PARTIAL_MESSAGE?= echo -e "  ==> Partial linking to $@"
DEP_MESSAGE?=	echo -e "  ... Building dependencies for $<"
CLEAN_MESSAGE?=	echo -e "  ... Removing created files"
CLEANALL_MESSAGE?=echo -e "  ... Removing all created files"
INSTALL_LINK_MESSAGE?=echo -e "  ==> Updating symlinks"
INSTALL_DOC_MESSAGE?=echo -e "  ==> Installing $(<) documentation"
INSTALL_DOC_LOCAL_MESSAGE?= echo -e "  ==> Installing $(<) documentation locally"
INSTALL_MESSAGE?=echo -e "  ==> Installing $^"
INSTALL_LOCAL_MESSAGE?=echo -e "  ==> Installing $(<) to local build-tree"
UPDATE_HTML_MESSAGE?=echo -e "  ! You should remake your doc directory in $(1)"
endif


# allows an include $(DEPSVAR) at the end of the makefile
# but prevents rebuilding them on a scrub, clean, cleanall and help
ifneq ($(filter scrub clean cleanall help,$(MAKECMDGOALS)),)
DEPSVAR	=
else
DEPSVAR	= $(DEPS)
endif

#
# Some rules
#

# addfileheader-rule: allows "make addfileheader main.c server.c"-like
# commands and automatically inserts the path within the package
# options may be passed with $(ADDFILEHEADER_OPTIONS)
ADDFILEHEADER_PREFIX = $(patsubst $(call absfilename,$(PKGDIR)/)%,\
				  $(PKGNAME)/%,$(call absfilename,./))
ADDFILEHEADER_FILES = $(filter-out addfileheader,$(MAKECMDGOALS))
addfileheader:
	addfileheader $(ADDFILEHEADER_OPTIONS) -p $(ADDFILEHEADER_PREFIX) $(ADDFILEHEADER_FILES)
        

.PHONY: FORCE

endif	# _L4DIR_MK_MAKECONF undefined
