1,27 → 1,524 |
# Copyright (c) 2007 Fabio Checconi <fabio@gandalf.sssup.it> |
# |
# Main S.Ha.R.K. makefile |
# This is a non-recursive makefile that supports a Kbuild-like syntax |
# for input/output specification. |
|
# Handle the V=0|1 option. We use both a long and a short form. In |
# the short one we use the $(Q) variable prepended to shell commands |
# (e.g., $(Q)mkdir) that in quiet mode expands to @, and in verbose |
# mode expands to nothing. In the long one we have a couple of strings |
# per command, one named quiet_cmd, the other cmd, and we always echo |
# $(QS)cmd, so if $(QS) expands to quiet_ the first string is printed. |
# The first string is the quiet version of the command, the second one |
# holds the whole command. |
ifneq ($(V),1) |
Q:=@ |
QS:=quiet_ |
endif |
|
# Handle the make -s flag: produce no output at all... |
ifneq ($(findstring s,$(MAKEFLAGS)),) |
Q:=@ |
QS:=nothing_ |
endif |
|
# The variables used to generate the rules to build targets. Use |
# CROSS_COMPILE to specify the prefix to be used for the toolchain. |
ar:= $(CROSS_COMPILE)$(AR) |
as:= $(CROSS_COMPILE)$(CC) |
cc:= $(CROSS_COMPILE)$(CC) |
ld:= $(CROSS_COMPILE)$(LD) |
rm:= $(if $(RM),$(RM),rm) |
install:= $(if $(INSTALL),$(INSTALL),install) |
|
# As in the rules we cannot use the variables we use in the makefile, |
# because we reassign them for every directory we visit, we just try |
# to recover the information from the targets being built. Another |
# way could have been to expand the variables when generating the |
# rules, but it would have made rule generation unreadable. |
in-local:= $$(subst $$(srctree)/,,$$<) |
out-local:= $$(subst install-,,$$(subst $$(objtree)/,,$$@)) |
in-objs:= $$(filter %.o,$$^) |
in-objs-local:= $$(filter %.o,$$(subst $$(objtree)/,,$$^)) |
|
# The rule patterns, in quiet and in verbose form. The verbose form is |
# used also for the actual command. |
quiet_ar_cmd := ' AR\\t$(out-local) $(in-objs-local)' |
ar_cmd := $(ar) cr $$@ $(in-objs) |
|
quiet_cc_cmd := ' CC\\t$(in-local)' |
cc_cmd := $(cc) $$(cflags-$$(<:.c=.o)) $$(cppflags-$$(<:.c=.o)) \ |
-c $$< -o $$@ |
|
quiet_as_cmd := ' AS\\t$(in-local)' |
as_cmd := $(as) $$(aflags-$$(<:.s=.o)) -c $$< -o $$@ |
|
quiet_dep_cmd := ' DEP\\t$(in-local)' |
dep_cmd := $(cc) $$(cflags-$$(<:.c=.o)) $$(cppflags-$$(<:.c=.o)) \ |
-M -MT \ |
"$$(subst $$(srctree),$$(objtree),$$(<:.c=.o))\ |
$$@" $$< > $$@ 2>/dev/null |
|
quiet_ld-r_cmd := ' LD\\t$(out-local) $(in-objs-local)' |
ld-r_cmd := $(ld) $$(ldflags-$$(dir $$@)) -r $(in-objs) -o $$@ |
|
quiet_rm_cmd := ' RM\\t$$(subst clean-,,$$(subst distclean-,,$(out-local)))' |
rm_cmd := -$(rm) $$(subst clean-,,$$(subst distclean-,,$$@)) |
|
quiet_install_cmd := ' INSTALL $(out-local)' |
install_cmd := -$(install) $$(subst install-,,$$@) $$(installdir) |
|
# Generate the requested rule for the requested directory. First echo |
# the command according to the requested verbosity (suppress all the |
# output if $(QS)$(1)_cmd is not defined, i.e., in the silent make case,) |
# and then emit the actual command. |
define cmd |
$(if $($(QS)$(1)_cmd),@echo -e '$($(QS)$(1)_cmd)') |
@$($(1)_cmd) |
endef |
|
# Remove duplicate slashes, ../'s, trailing slashes and so on from paths. |
define clean-path |
$(dir $(abspath $(1)))$(notdir $(abspath $(1))) |
endef |
|
# Adjust the paths for all the prerequisites of a target. Given a list |
# of objects, with relative or absolute path, figure out the right paths |
# in the build directory. Leave the output in $(target-objs). |
define all-prerequisites-templ |
target-obj-list:=$(1) |
|
# Filter absolute paths. |
target-objs:=$$(filter $(srctree)/%,$$(target-obj-list)) |
target-obj-list:=$$(filter-out $$(target-objs),$$(target-obj-list)) |
|
# Add all the other objects, and convert the path to the $(objtree) |
# root and with a reasonable path. |
target-objs+=$$(addprefix $$(curdir)/,$$(target-obj-list)) |
target-objs:=$$(foreach dir,$$(subst $(srctree),$(objtree),$$(target-objs)),\ |
$$(call clean-path,$$(dir))) |
endef |
|
# Produce targets for a given library. |
define lib-templ |
lib:=$(1) |
lib-target:=$$(objdir)/$$(lib) |
|
# Get a list of all the prerequisites needed to build the library. |
$$(eval $$(call all-prerequisites-templ,\ |
$$(patsubst %/,%/obj.o,$$($$(lib)-objs)))) |
|
$$(foreach flag,$(flags),$$(eval $$(call flags-per-target,$$(flag),$$(lib)))) |
$$(foreach obj,$$(target-objs),\ |
$$(eval $$(call flags-per-objects,$$(obj),$$(lib)))) |
|
# Produce the real target, in $(objtree), and the user-friendly target, |
# with a relative path to $(srctree). Note that even when the two trees |
# are equal we define two targets; a possible optimization could be to |
# use relative paths for the object tree in this case, but the code can |
# become even less readable than it is now... |
$$(lib-target): $$(target-objs) |
$(call cmd,ar) |
short-lib-taget:=$$(subst $$(srctree)/,,$$(curdir)/$$(lib)) |
.PHONY: $$(short-lib-target) |
$$(short-lib-target): $$(lib-target) |
|
# Update the $(subdirs) for $(curdir) and its target list. |
subdirs+=$$(filter %/,$$($$(lib)-objs)) |
curdir-targets+=$$(lib-target) |
|
.PHONY: clean-$$(lib-target) |
clean-$$(lib-target): |
$(call cmd,rm) |
curdir-clean-targets+= clean-$$(lib-target) |
|
.PHONY: install-$$(lib-target) |
install-$$(lib-target): $$(lib-target) |
$(call cmd,install) |
curdir-install-targets+= install-$$(lib-target) |
endef |
|
# Produce the needed code for a given object. |
define obj-templ |
obj:=$(1) |
obj-target:=$$(objdir)/$$(obj) |
obj-dep:=$$(objdir)/.$$(obj:.o=.c).deps |
|
# Handle dependencies. |
ifeq ($(goals-have-clean),) |
$$(obj-dep): $$(objdir-prereq) |
-include $$(obj-dep) |
endif |
|
# Produce the user shortcut for the real target (that does not need to |
# be produced, as it is handled by implicit rules.) |
short-obj-target:= $$(subst $$(srctree)/,,$$(curdir)/$$(obj)) |
.PHONY: $$(short-obj-target) |
$$(short-obj-target): $$(obj-target) |
|
curdir-targets+=$$(obj-target) |
|
.PHONY: clean-$$(obj-target) distclean-$$(obj-dep) |
clean-$$(obj-target): |
$(call cmd,rm) |
distclean-$$(obj-dep): |
$(call cmd,rm) |
curdir-clean-targets+= clean-$$(obj-target) |
curdir-distclean-targets+= distclean-$$(obj-dep) |
|
endef |
|
# Handle the flags for the current directory. for each *FLAGS variable |
# used by the implicit rules there are two variants: |
# o the local one, e.g., cflags:=-I. or cflags+=-I. changing the |
# flags used only by the current directory. |
# o The global one, e.g., exported-cflags:=-I$(srctree) changing the |
# flags for the current directory and all its subdirs. |
# The flag handling is split in three parts, one to be inserted before |
# including the current directory makefile, one before recurring into |
# subdirs, the other one after the recursion. |
define flags-save-templ |
flag:=$(1) |
# Flags on input to this dir; they must be preserved for our sibling |
# directories. |
saved-$$(flag)-$$(curdir):= $$($$(flag)) |
endef |
|
define flags-pre-templ |
flag:=$(1) |
|
# For the current directory, use the user-specified flags (that may |
# come from our parent directory.) Extra flags are used to specify |
# library-specific flags. |
$$(flag)-$$(curdir):=$$($$(flag)) $$(exported-$$(flag)) |
|
#to-print+= [ $$(flag)-$$(curdir) = $$($$(flag)-$$(curdir)) ] RET |
|
# Export to our children also the user exported flags. |
$$(flag):= $$(saved-$$(flag)-$$(curdir)) $$(exported-$$(flag)) |
exported-$$(flag):= |
endef |
|
define flags-post-templ |
flag:=$(1) |
|
# Restore the flags that our parent specified. |
$$(flag):= $$(saved-$$(flag)-$$(curdir)) |
endef |
|
# Allow redefinition of flags on the basis of a single target. Each |
# target gets its own version of the flags, based on the ones of the |
# current directory and its own ones. |
define flags-per-target |
flag:=$(1) |
target:=$(2) |
|
$$(flag)-$$(curdir)/$$(target):=$$($$(flag)-$$(curdir)) \ |
$$($$(target)-$$(flag)) $$(extra-$$(flag)-$$(curdir)/$$(target)) |
|
# Those are the flags coming from the upper directories, they are set for |
# obj.o targets, we must export them to our children, so we leave them here. |
exported-$$(flag)-$$(curdir)/$$(target):= $$($$(target)-$$(flag)) \ |
$$(extra-$$(flag)-$$(curdir)/$$(target)) |
$$(target)-$$(flag):= |
endef |
|
define flags-per-object |
# Generate flags only for objects in the current directory, as prerequisites |
# that come from ousdide are not compiled here. |
flag:=$(1) |
target:=$(3) |
ifeq ($(dir $(subst $(objtree),$(srctree),$(2))),$$(curdir)/) |
this-obj:=$(notdir $(2)) |
|
# The flags for a given object are the ones specified for its target |
# plus any specific one. |
$$(flag)-$$(curdir)/$$(this-obj):=$$($$(flag)-$$(curdir)/$$(target)) \ |
$$($$(this-obj)-$$(flag)) |
$$(this-obj)-$$(flag):= |
|
#to-print+= [ $$(flag)-$$(curdir)/$$(this-obj) = $$($$(flag)-$$(curdir)/$$(this-obj)) ] RET |
endif |
# Pass the right flags to the subdirs we use to build $(target). |
ifeq ($$(notdir $(2)),obj.o) |
extra-$$(flag)-$(2):= $$(exported-$$(flag)-$$(curdir)/$$(target)) |
endif |
endef |
|
# Allow the user to specify per-object flags |
define flags-per-objects |
$$(foreach flag,$$(flags),\ |
$$(eval $$(call flags-per-object,$$(flags),$(1),$(2)))) |
endef |
|
# Helper to define per-library flags. |
define flags-per-libs |
$$(foreach flag,$$(flags),\ |
$$(eval $$(call flags-per-lib,$$(flags),$(1),$(2)))) |
endef |
|
# Disable default implicit rules. |
.SUFFIXES: |
|
# The roots of our source and object trees. If an O=dir option is |
# passed to the toplevel makefile all the output of the building |
# process is in dir. |
srctree:=$(call clean-path,$(CURDIR)) |
objtree:=$(if $(O),$(call clean-path,$(O)),$(srctree)) |
|
ifeq ($(wildcard $(objtree)),) |
$(error Output directory $(objtree) does not exist) |
endif |
|
clean-targets:= |
distclean-targets:= |
install-targets:= |
|
goals-have-clean:=$(strip $(filter clean distclean,$(MAKECMDGOALS))) |
|
aflags:= $(AFLAGS) |
cflags:= $(CFLAGS) |
cppflags:= $(CPPFLAGS) |
ldflags:= $(LDFLAGS) |
flags:= aflags cflags cppflags ldflags |
|
# XXX debug only |
to-print:= |
|
# The following macro is used to do a standard set of operations |
# for every subdirectory we have to work on. It is instantiated |
# every time we change subdirectory, and generates a set of targets |
# specific to that directory. |
define recurse-templ |
|
# Remember where we are in the source and object tree. The clean-path |
# macro is used for user output and for generating targets independently |
# from directories being specified as dir or dir/ or with multiple slashes |
# and so on. |
curdir:=$$(call clean-path,$(1)) |
objdir:=$(objtree)$$(subst $(srctree),,$$(curdir)) |
|
# Save the flags our parent passed us. |
$$(foreach flag,$(flags),$$(eval $$(call flags-save-templ,$$(flag)))) |
|
# A list of all the targets defined for the current directory. It is |
# used to produce an user-reachable target for submakes into source tree |
# subdirectories, e.g., if src/utils is a source directory, make src/utils |
# will build all the targets defined inside it. Start with the short path |
# to all subdirs. |
curdir-targets:= |
|
curdir-clean-targets:= |
curdir-distclean-targets:= |
curdir-install-targets:= |
|
# If the output directory does not exist every target that actually |
# needs it will have to create it. |
ifneq ($(objtree),$(srctree)) |
ifeq ($$(wildcard $$(objdir)),) |
objdir-prereq:=$$(objdir)/.build |
$$(objdir)/.build: |
$(Q)if [ ! -d $$(dir $$@) ] ; then \ |
mkdir -p $$(dir $$@) ; touch $$@ ; fi |
endif |
endif |
|
# Include the next subdirectory. Don't include the root makefile, |
# if we are at the first step of the recursion. |
include $$(subst $(srctree)/Makefile,,$$(curdir)/Makefile) |
|
# Figure out all the targets. We support three kind of targets: |
# - subdirectories |
# - libraries |
# - objects |
# |
# Subdirectories are recursively processed, libraries are built using |
# the objects specified in their *.a-objs target (if it contains a |
# subdirectory the latter is processed and the resulting obj.o object |
# is included,) and objects are compiled and incrementally linked |
# together in a obj.o file. |
subdirs:=$$(filter %/, $$(targets)) |
objs:=$$(filter %.o, $$(targets)) |
libs:=$$(filter %.a, $$(targets)) |
|
ifndef BASE |
BASE=. |
$$(eval $$(call all-prerequisites-templ, $$(subdirs))) |
subdir-targets:= $$(target-objs) |
|
# Recurse into all the subdirectories. |
curdir-targets+=$$(subst $(objtree)/,,$$(subdir-targets)) |
|
# Look for prerequisites to build obj.o for the current directory. |
$$(eval $$(call all-prerequisites-templ,\ |
$$(filter-out $$(exclude),$$(objs)))) |
target-objs+=$$(addsuffix /obj.o,$$(subdir-targets)) |
|
$$(foreach flag,$(flags),$$(eval $$(call flags-pre-templ,$$(flag)))) |
|
# Produce a target for obj.o, even if not needed (it will be empty in |
# this case.) |
ifneq ($$(strip $$(target-objs)),) |
$$(foreach flag,$(flags),$$(eval $$(call flags-per-target,$$(flag),obj.o))) |
$$(foreach obj,$$(target-objs),\ |
$$(eval $$(call flags-per-objects,$$(obj),obj.o))) |
$$(objdir)/obj.o: $$(target-objs) |
$(call cmd,ld-r) |
else |
$$(objdir)/obj.o: |
$(Q)touch $$@ |
endif |
curdir-targets+= $$(objdir)/obj.o |
|
include $(BASE)/config/config.mk |
# to-print+= [ [ $$(objdir)/obj.o ] $$(target-objs) ] |
|
# Produce the needed targets for each library. |
ifneq ($$(strip $$(libs)),) |
$$(foreach lib,$$(libs),$$(eval $$(call lib-templ,$$(lib)))) |
endif |
|
# Produce a target for each local object. Build the list of all the |
# targets specified by the current subdir. It is given by all the local |
# objects in $(targets) or in a library contained in it. Non-local |
# objects can be specified as dependencies but must be built from the |
# directory containing them (if needed their directory can specify that |
# they are not to be included in the local obj.o putting them into |
# $(exclude); this may not seem straightforward but is to support a |
# few corner cases.) |
# |
# First build a relative path for all the .o files in the targets (the |
# default one and the library ones,) taking care of not being confused |
# by relative directory specifications. |
all-local-objs-paths:=$$(subst $$(curdir)/,,\ |
$$(abspath $$(addprefix $$(curdir)/,\ |
$$(objs) $$(foreach lib,$$(libs),$$(filter %.o,$$($$(lib)-objs)))))) |
|
.PHONY: install all clean cleanall distrib depend |
# Then keep only those with a dir equal to ./ A local object is not |
# allowed to be specified with a path specifying a directory different |
# from the current one. |
all-local-objs:=$$(foreach obj, $$(all-local-objs-paths), \ |
$$(if $$(subst ./,,$$(dir $$(obj))),,$$(obj))) |
|
install all clean cleanall depend: |
make -C $(OSLIB) $@ |
make -C kernel $@ |
make -C modules $@ |
make -C drivers $@ |
make -C lib $@ |
make -C libc $@ |
make -C ports $@ |
make -C tracer $@ |
ifeq ($(findstring YES,$(SHARK_FS)) , YES) |
make -C fs $@ |
# Produce one target per object, and the rules to build them along with |
# their dependencies. |
ifneq ($$(strip $$(all-local-objs)),) |
$$(foreach obj,$$(all-local-objs),$$(eval $$(call obj-templ,$$(obj)))) |
|
$$(objdir)/%.o: $$(curdir)/%.c |
$(call cmd,cc) |
|
$$(objdir)/%.o: $$(curdir)/%.s |
$(call cmd,as) |
|
$$(objdir)/.%.c.deps: $$(curdir)/%.c |
$(call cmd,dep) |
|
endif |
|
# Produce the user-friendly target for the source dir, depending |
# on its obj.o, libs and local objects (only if they can be built.) |
curdir-target:= $$(subst $$(srctree)/,,$$(curdir)) |
.PHONY: $$(curdir-target) |
$$(curdir-target): $$(curdir-targets) |
|
# Produce the clean and distclean targets for the current directory. |
.PHONY: clean-$$(curdir-target) distclean-$$(curdir-target) |
clean-$$(curdir-target): $$(curdir-clean-targets) |
|
distclean-$$(curdir-target): clean-$$(curdir-target) \ |
$$(curdir-distclean-targets) |
|
# to-print+=[ distclean-$$(curdir-target) ] |
|
clean-targets+= clean-$$(curdir-target) |
distclean-targets+= distclean-$$(curdir-target) |
|
# Produce the install target. This is very Shark specific... |
.PHONY: install-$$(curdir-target) |
$$(curdir-install-targets): $(installdir)/.build |
install-$$(curdir-target): $$(curdir-install-targets) |
install-targets+= install-$$(curdir-target) |
|
#to-print+=[ install-$$(curdir-target) = $$(curdir-install-targets) ] |
|
# Actually do the recursion, generating the code specified by |
# recurse-tmpl for every subdirectory needed from the one we are |
# leaving. |
ifneq ($$(strip $$(subdirs)),) |
$$(foreach dir,$$(subdirs),$$(eval $$(call recurse-templ,$(1)/$$(dir)))) |
curdir:=$$(call clean-path,$(1)) |
endif |
|
$$(foreach flag,$(flags),$$(eval $$(call flags-post-templ,$$(flag)))) |
endef |
|
.DEFAULT_GOAL:= all |
|
include shark.cfg |
|
installdir:=$(objtree)/.lib |
|
# Handle Shark configuration. Really insane, indeed. |
options:=TSC APIC BIOS TRACER FG FB COMPILER |
define strip-in-place |
$(1):=$(strip $($(1))) |
endef |
$(foreach cfgopt,$(options),$(eval $(call strip-in-place,$(cfgopt)))) |
|
cpp-tsc-TRUE:= -D__TSC__ |
cpp-apic-TRUE:= -D__APIC__ |
cpp-bios-VM86:= -DVM86 |
cpp-tracer-NEW:= -D__NEW_TRACER__ |
cpp-tracer-OLD:= -D__OLD_TRACER__ |
cpp-fg-FORCE_PXC:= -D__FORCE_PXC__ |
cpp-fb-VESA:= -DCONFIG_FB_VESA -DCONFIG_LOGO |
cpp-fb-FINDPCI:= -DCONFIG_FB_RIVA -DCONFIG_FB_RADEON -DCONFIG_FB_MATROX \ |
-DCONFIG_LOGO -DCONFIG_FB_MATROX_G100 \ |
-DCONFIG_FB_MATROX_MILLENIUM -DCONFIG_FB_MATROX_MYSTIQUE |
cpp-fb-VGA16:= -DCONFIG_FB_VGA16 |
|
include-dirs:= \ |
-I$(srctree)/include -I$(srctree)/modules \ |
-I$(srctree)/libc/arch/$(ARCH)/include \ |
-I$(srctree)/tracer/include \ |
-I$(srctree)/oslib |
|
config:= -D__LINUX__ \ |
$(cpp-tsc-$(TSC)) $(cpp-apic-$(APIC)) $(cpp-bios-$(BIOS)) \ |
$(cpp-tracer-$(TRACER)) $(cpp-fg-$(FG)) $(cpp-fb-$(FB)) |
|
exported-cppflags:= $(include-dirs) $(config) |
exported-aflags:= -x assembler-with-cpp $(include-dirs) $(config) |
|
cc-compiler-GCC4:= -Wimplicit-function-declaration -Wno-attributes \ |
-Wno-pointer-sign -Wall -O -fno-builtin -nostdinc \ |
-minline-all-stringops -fno-stack-protector |
cc-compiler-GCC3:= -Wimplicit-function-declaration -Wall -O \ |
-fno-builtin -nostdinc -minline-all-stringops |
cc-compiler-DJGPP:= -Wimplicit-function-declaration -Wall -O \ |
-fno-builtin -nostdinc -minline-all-stringops |
|
exported-cflags:= $(cc-compiler-$(COMPILER)) |
|
fs-YES:= fs/ |
|
targets:= libgkern.a drivers/ libc/ ports/ tracer/ $(fs-$(SHARK_FS)) |
libgkern.a-objs:= oslib/ kernel/ modules/ |
|
# Let the good times roll... |
$(eval $(call recurse-templ,$(srctree))) |
|
all: $(srctree) |
|
.PHONY: clean distclean |
clean: $(clean-targets) |
distclean: $(distclean-targets) |
|
debug: |
@echo $(to-print) |
|
.PHONY: install $(install-targets) |
$(installdir)/.build: |
$(Q)if [ ! -d $(dir $@) ] ; then \ |
mkdir -p $(dir $@) ; touch $@ ; fi |
|
install: $(install-targets) |
|