parent
88271e5177
commit
c56078afcc
|
@ -0,0 +1 @@
|
||||||
|
# placeholder
|
|
@ -0,0 +1 @@
|
||||||
|
# placeholder
|
|
@ -0,0 +1,217 @@
|
||||||
|
####
|
||||||
|
# kbuild: Generic definitions
|
||||||
|
|
||||||
|
# Convinient variables
|
||||||
|
comma := ,
|
||||||
|
squote := '
|
||||||
|
empty :=
|
||||||
|
space := $(empty) $(empty)
|
||||||
|
|
||||||
|
###
|
||||||
|
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
|
||||||
|
dot-target = $(dir $@).$(notdir $@)
|
||||||
|
|
||||||
|
###
|
||||||
|
# The temporary file to save gcc -MD generated dependencies must not
|
||||||
|
# contain a comma
|
||||||
|
depfile = $(subst $(comma),_,$(dot-target).d)
|
||||||
|
|
||||||
|
###
|
||||||
|
# filename of target with directory and extension stripped
|
||||||
|
basetarget = $(basename $(notdir $@))
|
||||||
|
|
||||||
|
###
|
||||||
|
# Escape single quote for use in echo statements
|
||||||
|
escsq = $(subst $(squote),'\$(squote)',$1)
|
||||||
|
|
||||||
|
###
|
||||||
|
# filechk is used to check if the content of a generated file is updated.
|
||||||
|
# Sample usage:
|
||||||
|
# define filechk_sample
|
||||||
|
# echo $KERNELRELEASE
|
||||||
|
# endef
|
||||||
|
# version.h : Makefile
|
||||||
|
# $(call filechk,sample)
|
||||||
|
# The rule defined shall write to stdout the content of the new file.
|
||||||
|
# The existing file will be compared with the new one.
|
||||||
|
# - If no file exist it is created
|
||||||
|
# - If the content differ the new file is used
|
||||||
|
# - If they are equal no change, and no timestamp update
|
||||||
|
# - stdin is piped in from the first prerequisite ($<) so one has
|
||||||
|
# to specify a valid file as first prerequisite (often the kbuild file)
|
||||||
|
define filechk
|
||||||
|
$(Q)set -e; \
|
||||||
|
echo ' CHK $@'; \
|
||||||
|
mkdir -p $(dir $@); \
|
||||||
|
$(filechk_$(1)) < $< > $@.tmp; \
|
||||||
|
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
|
||||||
|
rm -f $@.tmp; \
|
||||||
|
else \
|
||||||
|
echo ' UPD $@'; \
|
||||||
|
mv -f $@.tmp $@; \
|
||||||
|
fi
|
||||||
|
endef
|
||||||
|
|
||||||
|
######
|
||||||
|
# gcc support functions
|
||||||
|
# See documentation in Documentation/kbuild/makefiles.txt
|
||||||
|
|
||||||
|
# output directory for tests below
|
||||||
|
TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
|
||||||
|
|
||||||
|
# as-option
|
||||||
|
# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
|
||||||
|
|
||||||
|
as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
|
||||||
|
-xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
|
||||||
|
else echo "$(2)"; fi ;)
|
||||||
|
|
||||||
|
# as-instr
|
||||||
|
# Usage: cflags-y += $(call as-instr, instr, option1, option2)
|
||||||
|
|
||||||
|
as-instr = $(shell if echo -e "$(1)" | \
|
||||||
|
$(CC) $(AFLAGS) -c -xassembler - \
|
||||||
|
-o $(TMPOUT)astest$$$$.out > /dev/null 2>&1; \
|
||||||
|
then rm $(TMPOUT)astest$$$$.out; echo "$(2)"; \
|
||||||
|
else echo "$(3)"; fi)
|
||||||
|
|
||||||
|
# cc-option
|
||||||
|
# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
|
||||||
|
|
||||||
|
cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
|
||||||
|
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
|
||||||
|
|
||||||
|
# cc-option-yn
|
||||||
|
# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
|
||||||
|
cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
|
||||||
|
> /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
|
||||||
|
|
||||||
|
# cc-option-align
|
||||||
|
# Prefix align with either -falign or -malign
|
||||||
|
cc-option-align = $(subst -functions=0,,\
|
||||||
|
$(call cc-option,-falign-functions=0,-malign-functions=0))
|
||||||
|
|
||||||
|
# cc-version
|
||||||
|
# Usage gcc-ver := $(call cc-version, $(CC))
|
||||||
|
cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
|
||||||
|
|
||||||
|
# cc-ifversion
|
||||||
|
# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
|
||||||
|
cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
|
||||||
|
echo $(3); fi;)
|
||||||
|
|
||||||
|
# ld-option
|
||||||
|
# Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
|
||||||
|
ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \
|
||||||
|
-o $(TMPOUT)ldtest$$$$.out > /dev/null 2>&1; \
|
||||||
|
then rm $(TMPOUT)ldtest$$$$.out; echo "$(1)"; \
|
||||||
|
else echo "$(2)"; fi)
|
||||||
|
|
||||||
|
###
|
||||||
|
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
|
||||||
|
# Usage:
|
||||||
|
# $(Q)$(MAKE) $(build)=dir
|
||||||
|
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
|
||||||
|
|
||||||
|
# Prefix -I with $(srctree) if it is not an absolute path
|
||||||
|
addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
|
||||||
|
# Find all -I options and call addtree
|
||||||
|
flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
|
||||||
|
|
||||||
|
# If quiet is set, only print short version of command
|
||||||
|
cmd = @$(echo-cmd) $(cmd_$(1))
|
||||||
|
|
||||||
|
# Add $(obj)/ for paths that is not absolute
|
||||||
|
objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
|
||||||
|
|
||||||
|
###
|
||||||
|
# if_changed - execute command if any prerequisite is newer than
|
||||||
|
# target, or command line has changed
|
||||||
|
# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies
|
||||||
|
# including used config symbols
|
||||||
|
# if_changed_rule - as if_changed but execute rule instead
|
||||||
|
# See Documentation/kbuild/makefiles.txt for more info
|
||||||
|
|
||||||
|
ifneq ($(KBUILD_NOCMDDEP),1)
|
||||||
|
# Check if both arguments has same arguments. Result in empty string if equal
|
||||||
|
# User may override this check using make KBUILD_NOCMDDEP=1
|
||||||
|
arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
|
||||||
|
$(filter-out $(cmd_$@), $(cmd_$(1))) )
|
||||||
|
endif
|
||||||
|
|
||||||
|
# echo command. Short version is $(quiet) equals quiet, otherwise full command
|
||||||
|
echo-cmd = $(if $($(quiet)cmd_$(1)), \
|
||||||
|
echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
|
||||||
|
|
||||||
|
# >'< substitution is for echo to work,
|
||||||
|
# >$< substitution to preserve $ when reloading .cmd file
|
||||||
|
# note: when using inline perl scripts [perl -e '...$$t=1;...']
|
||||||
|
# in $(cmd_xxx) double $$ your perl vars
|
||||||
|
make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
|
||||||
|
|
||||||
|
# Find any prerequisites that is newer than target or that does not exist.
|
||||||
|
# PHONY targets skipped in both cases.
|
||||||
|
any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
|
||||||
|
|
||||||
|
# Execute command if command has changed or prerequisitei(s) are updated
|
||||||
|
#
|
||||||
|
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
|
||||||
|
@set -e; \
|
||||||
|
$(echo-cmd) $(cmd_$(1)); \
|
||||||
|
echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
|
||||||
|
|
||||||
|
# execute the command and also postprocess generated .d dependencies
|
||||||
|
# file
|
||||||
|
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
|
||||||
|
@set -e; \
|
||||||
|
$(echo-cmd) $(cmd_$(1)); \
|
||||||
|
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
|
||||||
|
rm -f $(depfile); \
|
||||||
|
mv -f $(dot-target).tmp $(dot-target).cmd)
|
||||||
|
|
||||||
|
# Usage: $(call if_changed_rule,foo)
|
||||||
|
# will check if $(cmd_foo) changed, or any of the prequisites changed,
|
||||||
|
# and if so will execute $(rule_foo)
|
||||||
|
if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
|
||||||
|
@set -e; \
|
||||||
|
$(rule_$(1)))
|
||||||
|
|
||||||
|
###
|
||||||
|
# why - tell why a a target got build
|
||||||
|
# enabled by make V=2
|
||||||
|
# Output (listed in the order they are checked):
|
||||||
|
# (1) - due to target is PHONY
|
||||||
|
# (2) - due to target missing
|
||||||
|
# (3) - due to: file1.h file2.h
|
||||||
|
# (4) - due to command line change
|
||||||
|
# (5) - due to missing .cmd file
|
||||||
|
# (6) - due to target not in $(targets)
|
||||||
|
# (1) PHONY targets are always build
|
||||||
|
# (2) No target, so we better build it
|
||||||
|
# (3) Prerequisite is newer than target
|
||||||
|
# (4) The command line stored in the file named dir/.target.cmd
|
||||||
|
# differed from actual command line. This happens when compiler
|
||||||
|
# options changes
|
||||||
|
# (5) No dir/.target.cmd file (used to store command line)
|
||||||
|
# (6) No dir/.target.cmd file and target not listed in $(targets)
|
||||||
|
# This is a good hint that there is a bug in the kbuild file
|
||||||
|
ifeq ($(KBUILD_VERBOSE),2)
|
||||||
|
why = \
|
||||||
|
$(if $(filter $@, $(PHONY)),- due to target is PHONY, \
|
||||||
|
$(if $(wildcard $@), \
|
||||||
|
$(if $(strip $(any-prereq)),- due to: $(any-prereq), \
|
||||||
|
$(if $(arg-check), \
|
||||||
|
$(if $(cmd_$@),- due to command line change, \
|
||||||
|
$(if $(filter $@, $(targets)), \
|
||||||
|
- due to missing .cmd file, \
|
||||||
|
- due to $(notdir $@) not in $$(targets) \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
|
), \
|
||||||
|
- due to target missing \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
|
echo-why = $(call escsq, $(strip $(why)))
|
||||||
|
endif
|
|
@ -0,0 +1,25 @@
|
||||||
|
###
|
||||||
|
# scripts contains sources for various helper programs used throughout
|
||||||
|
# the kernel for the build process.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# kallsyms: Find all symbols in vmlinux
|
||||||
|
# pnmttologo: Convert pnm files to logo files
|
||||||
|
# conmakehash: Create chartable
|
||||||
|
# conmakehash: Create arrays for initializing the kernel console tables
|
||||||
|
|
||||||
|
hostprogs-$(CONFIG_KALLSYMS) += kallsyms
|
||||||
|
hostprogs-$(CONFIG_LOGO) += pnmtologo
|
||||||
|
hostprogs-$(CONFIG_VT) += conmakehash
|
||||||
|
hostprogs-$(CONFIG_PROM_CONSOLE) += conmakehash
|
||||||
|
hostprogs-$(CONFIG_IKCONFIG) += bin2c
|
||||||
|
|
||||||
|
always := $(hostprogs-y) $(hostprogs-m)
|
||||||
|
|
||||||
|
# The following hostprogs-y programs are only build on demand
|
||||||
|
hostprogs-y += unifdef
|
||||||
|
|
||||||
|
#subdir-$(CONFIG_MODVERSIONS) += genksyms
|
||||||
|
#subdir-y += mod
|
||||||
|
|
||||||
|
# Let clean descend into subdirs
|
||||||
|
subdir- += basic kconfig
|
|
@ -0,0 +1,349 @@
|
||||||
|
# ==========================================================================
|
||||||
|
# Building
|
||||||
|
# ==========================================================================
|
||||||
|
|
||||||
|
src := $(obj)
|
||||||
|
|
||||||
|
PHONY := __build
|
||||||
|
__build:
|
||||||
|
|
||||||
|
# Read .config if it exist, otherwise ignore
|
||||||
|
-include include/config/auto.conf
|
||||||
|
|
||||||
|
include scripts/Kbuild.include
|
||||||
|
|
||||||
|
# The filename Kbuild has precedence over Makefile
|
||||||
|
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
|
||||||
|
include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
|
||||||
|
|
||||||
|
include scripts/Makefile.lib
|
||||||
|
|
||||||
|
ifdef host-progs
|
||||||
|
ifneq ($(hostprogs-y),$(host-progs))
|
||||||
|
$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!)
|
||||||
|
hostprogs-y += $(host-progs)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Do not include host rules unles needed
|
||||||
|
ifneq ($(hostprogs-y)$(hostprogs-m),)
|
||||||
|
include scripts/Makefile.host
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(KBUILD_SRC),)
|
||||||
|
# Create output directory if not already present
|
||||||
|
_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
|
||||||
|
|
||||||
|
# Create directories for object files if directory does not exist
|
||||||
|
# Needed when obj-y := dir/file.o syntax is used
|
||||||
|
_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d)))
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifdef EXTRA_TARGETS
|
||||||
|
$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.6. Please fix!)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef build-targets
|
||||||
|
$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.6. Please fix!)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef export-objs
|
||||||
|
$(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.6. Please fix!)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef O_TARGET
|
||||||
|
$(warning kbuild: $(obj)/Makefile - Usage of O_TARGET := $(O_TARGET) is obsolete in 2.6. Please fix!)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef L_TARGET
|
||||||
|
$(error kbuild: $(obj)/Makefile - Use of L_TARGET is replaced by lib-y in 2.6. Please fix!)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef list-multi
|
||||||
|
$(warning kbuild: $(obj)/Makefile - list-multi := $(list-multi) is obsolete in 2.6. Please fix!)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef obj
|
||||||
|
$(warning kbuild: Makefile.build is included improperly)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
|
||||||
|
lib-target := $(obj)/lib.a
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
|
||||||
|
builtin-target := $(obj)/built-in.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
# We keep a list of all modules in $(MODVERDIR)
|
||||||
|
|
||||||
|
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
|
||||||
|
$(if $(KBUILD_MODULES),$(obj-m)) \
|
||||||
|
$(subdir-ym) $(always)
|
||||||
|
@:
|
||||||
|
|
||||||
|
# Linus' kernel sanity checking tool
|
||||||
|
ifneq ($(KBUILD_CHECKSRC),0)
|
||||||
|
ifeq ($(KBUILD_CHECKSRC),2)
|
||||||
|
quiet_cmd_force_checksrc = CHECK $<
|
||||||
|
cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
|
||||||
|
else
|
||||||
|
quiet_cmd_checksrc = CHECK $<
|
||||||
|
cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# Compile C sources (.c)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Default is built-in, unless we know otherwise
|
||||||
|
modkern_cflags := $(CFLAGS_KERNEL)
|
||||||
|
quiet_modtag := $(empty) $(empty)
|
||||||
|
|
||||||
|
$(real-objs-m) : modkern_cflags := $(CFLAGS_MODULE)
|
||||||
|
$(real-objs-m:.o=.i) : modkern_cflags := $(CFLAGS_MODULE)
|
||||||
|
$(real-objs-m:.o=.s) : modkern_cflags := $(CFLAGS_MODULE)
|
||||||
|
$(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE)
|
||||||
|
|
||||||
|
$(real-objs-m) : quiet_modtag := [M]
|
||||||
|
$(real-objs-m:.o=.i) : quiet_modtag := [M]
|
||||||
|
$(real-objs-m:.o=.s) : quiet_modtag := [M]
|
||||||
|
$(real-objs-m:.o=.lst): quiet_modtag := [M]
|
||||||
|
|
||||||
|
$(obj-m) : quiet_modtag := [M]
|
||||||
|
|
||||||
|
# Default for not multi-part modules
|
||||||
|
modname = $(basetarget)
|
||||||
|
|
||||||
|
$(multi-objs-m) : modname = $(modname-multi)
|
||||||
|
$(multi-objs-m:.o=.i) : modname = $(modname-multi)
|
||||||
|
$(multi-objs-m:.o=.s) : modname = $(modname-multi)
|
||||||
|
$(multi-objs-m:.o=.lst) : modname = $(modname-multi)
|
||||||
|
$(multi-objs-y) : modname = $(modname-multi)
|
||||||
|
$(multi-objs-y:.o=.i) : modname = $(modname-multi)
|
||||||
|
$(multi-objs-y:.o=.s) : modname = $(modname-multi)
|
||||||
|
$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
|
||||||
|
|
||||||
|
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
|
||||||
|
cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
|
||||||
|
|
||||||
|
%.s: %.c FORCE
|
||||||
|
$(call if_changed_dep,cc_s_c)
|
||||||
|
|
||||||
|
quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
|
||||||
|
cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $<
|
||||||
|
|
||||||
|
%.i: %.c FORCE
|
||||||
|
$(call if_changed_dep,cc_i_c)
|
||||||
|
|
||||||
|
quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
|
||||||
|
cmd_cc_symtypes_c = \
|
||||||
|
$(CPP) -D__GENKSYMS__ $(c_flags) $< \
|
||||||
|
| $(GENKSYMS) -T $@ >/dev/null; \
|
||||||
|
test -s $@ || rm -f $@
|
||||||
|
|
||||||
|
%.symtypes : %.c FORCE
|
||||||
|
$(call if_changed_dep,cc_symtypes_c)
|
||||||
|
|
||||||
|
# C (.c) files
|
||||||
|
# The C file is compiled and updated dependency information is generated.
|
||||||
|
# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
|
||||||
|
|
||||||
|
quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
|
||||||
|
|
||||||
|
ifndef CONFIG_MODVERSIONS
|
||||||
|
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
|
||||||
|
|
||||||
|
else
|
||||||
|
# When module versioning is enabled the following steps are executed:
|
||||||
|
# o compile a .tmp_<file>.o from <file>.c
|
||||||
|
# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
|
||||||
|
# not export symbols, we just rename .tmp_<file>.o to <file>.o and
|
||||||
|
# are done.
|
||||||
|
# o otherwise, we calculate symbol versions using the good old
|
||||||
|
# genksyms on the preprocessed source and postprocess them in a way
|
||||||
|
# that they are usable as a linker script
|
||||||
|
# o generate <file>.o from .tmp_<file>.o using the linker to
|
||||||
|
# replace the unresolved symbols __crc_exported_symbol with
|
||||||
|
# the actual value of the checksum generated by genksyms
|
||||||
|
|
||||||
|
cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
|
||||||
|
cmd_modversions = \
|
||||||
|
if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
|
||||||
|
$(CPP) -D__GENKSYMS__ $(c_flags) $< \
|
||||||
|
| $(GENKSYMS) $(if $(KBUILD_SYMTYPES), \
|
||||||
|
-T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH) \
|
||||||
|
> $(@D)/.tmp_$(@F:.o=.ver); \
|
||||||
|
\
|
||||||
|
$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
|
||||||
|
-T $(@D)/.tmp_$(@F:.o=.ver); \
|
||||||
|
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
|
||||||
|
else \
|
||||||
|
mv -f $(@D)/.tmp_$(@F) $@; \
|
||||||
|
fi;
|
||||||
|
endif
|
||||||
|
|
||||||
|
define rule_cc_o_c
|
||||||
|
$(call echo-cmd,checksrc) $(cmd_checksrc) \
|
||||||
|
$(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
|
||||||
|
$(cmd_modversions) \
|
||||||
|
scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \
|
||||||
|
$(dot-target).tmp; \
|
||||||
|
rm -f $(depfile); \
|
||||||
|
mv -f $(dot-target).tmp $(dot-target).cmd
|
||||||
|
endef
|
||||||
|
|
||||||
|
# Built-in and composite module parts
|
||||||
|
|
||||||
|
%.o: %.c FORCE
|
||||||
|
$(call cmd,force_checksrc)
|
||||||
|
$(call if_changed_rule,cc_o_c)
|
||||||
|
|
||||||
|
# Single-part modules are special since we need to mark them in $(MODVERDIR)
|
||||||
|
|
||||||
|
$(single-used-m): %.o: %.c FORCE
|
||||||
|
$(call cmd,force_checksrc)
|
||||||
|
$(call if_changed_rule,cc_o_c)
|
||||||
|
@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
|
||||||
|
|
||||||
|
quiet_cmd_cc_lst_c = MKLST $@
|
||||||
|
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
|
||||||
|
$(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
|
||||||
|
System.map $(OBJDUMP) > $@
|
||||||
|
|
||||||
|
%.lst: %.c FORCE
|
||||||
|
$(call if_changed_dep,cc_lst_c)
|
||||||
|
|
||||||
|
# Compile assembler sources (.S)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
modkern_aflags := $(AFLAGS_KERNEL)
|
||||||
|
|
||||||
|
$(real-objs-m) : modkern_aflags := $(AFLAGS_MODULE)
|
||||||
|
$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
|
||||||
|
|
||||||
|
quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
|
||||||
|
cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
|
||||||
|
|
||||||
|
%.s: %.S FORCE
|
||||||
|
$(call if_changed_dep,as_s_S)
|
||||||
|
|
||||||
|
quiet_cmd_as_o_S = AS $(quiet_modtag) $@
|
||||||
|
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
|
||||||
|
|
||||||
|
%.o: %.S FORCE
|
||||||
|
$(call if_changed_dep,as_o_S)
|
||||||
|
|
||||||
|
targets += $(real-objs-y) $(real-objs-m) $(lib-y)
|
||||||
|
targets += $(extra-y) $(MAKECMDGOALS) $(always)
|
||||||
|
|
||||||
|
# Linker scripts preprocessor (.lds.S -> .lds)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
quiet_cmd_cpp_lds_S = LDS $@
|
||||||
|
cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
|
||||||
|
|
||||||
|
%.lds: %.lds.S FORCE
|
||||||
|
$(call if_changed_dep,cpp_lds_S)
|
||||||
|
|
||||||
|
# Build the compiled-in targets
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# To build objects in subdirs, we need to descend into the directories
|
||||||
|
$(sort $(subdir-obj-y)): $(subdir-ym) ;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rule to compile a set of .o files into one .o file
|
||||||
|
#
|
||||||
|
ifdef builtin-target
|
||||||
|
quiet_cmd_link_o_target = LD $@
|
||||||
|
# If the list of objects to link is empty, just create an empty built-in.o
|
||||||
|
cmd_link_o_target = $(if $(strip $(obj-y)),\
|
||||||
|
$(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
|
||||||
|
rm -f $@; $(AR) rcs $@)
|
||||||
|
|
||||||
|
$(builtin-target): $(obj-y) FORCE
|
||||||
|
$(call if_changed,link_o_target)
|
||||||
|
|
||||||
|
targets += $(builtin-target)
|
||||||
|
endif # builtin-target
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rule to compile a set of .o files into one .a file
|
||||||
|
#
|
||||||
|
ifdef lib-target
|
||||||
|
quiet_cmd_link_l_target = AR $@
|
||||||
|
cmd_link_l_target = rm -f $@; $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-y)
|
||||||
|
|
||||||
|
$(lib-target): $(lib-y) FORCE
|
||||||
|
$(call if_changed,link_l_target)
|
||||||
|
|
||||||
|
targets += $(lib-target)
|
||||||
|
endif
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rule to link composite objects
|
||||||
|
#
|
||||||
|
# Composite objects are specified in kbuild makefile as follows:
|
||||||
|
# <composite-object>-objs := <list of .o files>
|
||||||
|
# or
|
||||||
|
# <composite-object>-y := <list of .o files>
|
||||||
|
link_multi_deps = \
|
||||||
|
$(filter $(addprefix $(obj)/, \
|
||||||
|
$($(subst $(obj)/,,$(@:.o=-objs))) \
|
||||||
|
$($(subst $(obj)/,,$(@:.o=-y)))), $^)
|
||||||
|
|
||||||
|
quiet_cmd_link_multi-y = LD $@
|
||||||
|
cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps)
|
||||||
|
|
||||||
|
quiet_cmd_link_multi-m = LD [M] $@
|
||||||
|
cmd_link_multi-m = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $(link_multi_deps)
|
||||||
|
|
||||||
|
# We would rather have a list of rules like
|
||||||
|
# foo.o: $(foo-objs)
|
||||||
|
# but that's not so easy, so we rather make all composite objects depend
|
||||||
|
# on the set of all their parts
|
||||||
|
$(multi-used-y) : %.o: $(multi-objs-y) FORCE
|
||||||
|
$(call if_changed,link_multi-y)
|
||||||
|
|
||||||
|
$(multi-used-m) : %.o: $(multi-objs-m) FORCE
|
||||||
|
$(call if_changed,link_multi-m)
|
||||||
|
@{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
|
||||||
|
|
||||||
|
targets += $(multi-used-y) $(multi-used-m)
|
||||||
|
|
||||||
|
|
||||||
|
# Descending
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PHONY += $(subdir-ym)
|
||||||
|
$(subdir-ym):
|
||||||
|
$(Q)$(MAKE) $(build)=$@
|
||||||
|
|
||||||
|
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PHONY += FORCE
|
||||||
|
|
||||||
|
FORCE:
|
||||||
|
|
||||||
|
# Read all saved command lines and dependencies for the $(targets) we
|
||||||
|
# may be building above, using $(if_changed{,_dep}). As an
|
||||||
|
# optimization, we don't need to read them if the target does not
|
||||||
|
# exist, we will rebuild anyway in that case.
|
||||||
|
|
||||||
|
targets := $(wildcard $(sort $(targets)))
|
||||||
|
cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
|
||||||
|
|
||||||
|
ifneq ($(cmd_files),)
|
||||||
|
include $(cmd_files)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# Declare the contents of the .PHONY variable as phony. We keep that
|
||||||
|
# information in a variable se we can use it in if_changed and friends.
|
||||||
|
|
||||||
|
.PHONY: $(PHONY)
|
|
@ -0,0 +1,102 @@
|
||||||
|
# ==========================================================================
|
||||||
|
# Cleaning up
|
||||||
|
# ==========================================================================
|
||||||
|
|
||||||
|
src := $(obj)
|
||||||
|
|
||||||
|
PHONY := __clean
|
||||||
|
__clean:
|
||||||
|
|
||||||
|
# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
|
||||||
|
# Usage:
|
||||||
|
# $(Q)$(MAKE) $(clean)=dir
|
||||||
|
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
|
||||||
|
|
||||||
|
# The filename Kbuild has precedence over Makefile
|
||||||
|
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
|
||||||
|
include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
|
||||||
|
|
||||||
|
# Figure out what we need to build from the various variables
|
||||||
|
# ==========================================================================
|
||||||
|
|
||||||
|
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
|
||||||
|
subdir-y += $(__subdir-y)
|
||||||
|
__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
|
||||||
|
subdir-m += $(__subdir-m)
|
||||||
|
__subdir-n := $(patsubst %/,%,$(filter %/, $(obj-n)))
|
||||||
|
subdir-n += $(__subdir-n)
|
||||||
|
__subdir- := $(patsubst %/,%,$(filter %/, $(obj-)))
|
||||||
|
subdir- += $(__subdir-)
|
||||||
|
|
||||||
|
# Subdirectories we need to descend into
|
||||||
|
|
||||||
|
subdir-ym := $(sort $(subdir-y) $(subdir-m))
|
||||||
|
subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
|
||||||
|
|
||||||
|
# Add subdir path
|
||||||
|
|
||||||
|
subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
|
||||||
|
|
||||||
|
# build a list of files to remove, usually releative to the current
|
||||||
|
# directory
|
||||||
|
|
||||||
|
__clean-files := $(extra-y) $(EXTRA_TARGETS) $(always) \
|
||||||
|
$(targets) $(clean-files) \
|
||||||
|
$(host-progs) \
|
||||||
|
$(hostprogs-y) $(hostprogs-m) $(hostprogs-)
|
||||||
|
|
||||||
|
# as clean-files is given relative to the current directory, this adds
|
||||||
|
# a $(obj) prefix, except for absolute paths
|
||||||
|
|
||||||
|
__clean-files := $(wildcard \
|
||||||
|
$(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \
|
||||||
|
$(filter /%, $(__clean-files)))
|
||||||
|
|
||||||
|
# as clean-dirs is given relative to the current directory, this adds
|
||||||
|
# a $(obj) prefix, except for absolute paths
|
||||||
|
|
||||||
|
__clean-dirs := $(wildcard \
|
||||||
|
$(addprefix $(obj)/, $(filter-out /%, $(clean-dirs))) \
|
||||||
|
$(filter /%, $(clean-dirs)))
|
||||||
|
|
||||||
|
# ==========================================================================
|
||||||
|
|
||||||
|
quiet_cmd_clean = CLEAN $(obj)
|
||||||
|
cmd_clean = rm -f $(__clean-files)
|
||||||
|
quiet_cmd_cleandir = CLEAN $(__clean-dirs)
|
||||||
|
cmd_cleandir = rm -rf $(__clean-dirs)
|
||||||
|
|
||||||
|
|
||||||
|
__clean: $(subdir-ymn)
|
||||||
|
ifneq ($(strip $(__clean-files)),)
|
||||||
|
+$(call cmd,clean)
|
||||||
|
endif
|
||||||
|
ifneq ($(strip $(__clean-dirs)),)
|
||||||
|
+$(call cmd,cleandir)
|
||||||
|
endif
|
||||||
|
ifneq ($(strip $(clean-rule)),)
|
||||||
|
+$(clean-rule)
|
||||||
|
endif
|
||||||
|
@:
|
||||||
|
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Generic stuff
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
# Descending
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PHONY += $(subdir-ymn)
|
||||||
|
$(subdir-ymn):
|
||||||
|
$(Q)$(MAKE) $(clean)=$@
|
||||||
|
|
||||||
|
# If quiet is set, only print short version of command
|
||||||
|
|
||||||
|
cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
|
||||||
|
|
||||||
|
|
||||||
|
# Declare the contents of the .PHONY variable as phony. We keep that
|
||||||
|
# information in a variable se we can use it in if_changed and friends.
|
||||||
|
|
||||||
|
.PHONY: $(PHONY)
|
|
@ -0,0 +1,170 @@
|
||||||
|
# ==========================================================================
|
||||||
|
# Building binaries on the host system
|
||||||
|
# Binaries are used during the compilation of the kernel, for example
|
||||||
|
# to preprocess a data file.
|
||||||
|
#
|
||||||
|
# Both C and C++ is supported, but preferred language is C for such utilities.
|
||||||
|
#
|
||||||
|
# Samle syntax (see Documentation/kbuild/makefile.txt for reference)
|
||||||
|
# hostprogs-y := bin2hex
|
||||||
|
# Will compile bin2hex.c and create an executable named bin2hex
|
||||||
|
#
|
||||||
|
# hostprogs-y := lxdialog
|
||||||
|
# lxdialog-objs := checklist.o lxdialog.o
|
||||||
|
# Will compile lxdialog.c and checklist.c, and then link the executable
|
||||||
|
# lxdialog, based on checklist.o and lxdialog.o
|
||||||
|
#
|
||||||
|
# hostprogs-y := qconf
|
||||||
|
# qconf-cxxobjs := qconf.o
|
||||||
|
# qconf-objs := menu.o
|
||||||
|
# Will compile qconf as a C++ program, and menu as a C program.
|
||||||
|
# They are linked as C++ code to the executable qconf
|
||||||
|
|
||||||
|
# hostprogs-y := conf
|
||||||
|
# conf-objs := conf.o libkconfig.so
|
||||||
|
# libkconfig-objs := expr.o type.o
|
||||||
|
# Will create a shared library named libkconfig.so that consist of
|
||||||
|
# expr.o and type.o (they are both compiled as C code and the object file
|
||||||
|
# are made as position independent code).
|
||||||
|
# conf.c is compiled as a c program, and conf.o is linked together with
|
||||||
|
# libkconfig.so as the executable conf.
|
||||||
|
# Note: Shared libraries consisting of C++ files are not supported
|
||||||
|
|
||||||
|
__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
|
||||||
|
|
||||||
|
# C code
|
||||||
|
# Executables compiled from a single .c file
|
||||||
|
host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))
|
||||||
|
|
||||||
|
# C executables linked based on several .o files
|
||||||
|
host-cmulti := $(foreach m,$(__hostprogs),\
|
||||||
|
$(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
|
||||||
|
|
||||||
|
# Object (.o) files compiled from .c files
|
||||||
|
host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
|
||||||
|
|
||||||
|
# C++ code
|
||||||
|
# C++ executables compiled from at least on .cc file
|
||||||
|
# and zero or more .c files
|
||||||
|
host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
|
||||||
|
|
||||||
|
# C++ Object (.o) files compiled from .cc files
|
||||||
|
host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
|
||||||
|
|
||||||
|
# Shared libaries (only .c supported)
|
||||||
|
# Shared libraries (.so) - all .so files referenced in "xxx-objs"
|
||||||
|
host-cshlib := $(sort $(filter %.so, $(host-cobjs)))
|
||||||
|
# Remove .so files from "xxx-objs"
|
||||||
|
host-cobjs := $(filter-out %.so,$(host-cobjs))
|
||||||
|
|
||||||
|
#Object (.o) files used by the shared libaries
|
||||||
|
host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
|
||||||
|
|
||||||
|
# output directory for programs/.o files
|
||||||
|
# hostprogs-y := tools/build may have been specified. Retreive directory
|
||||||
|
host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
|
||||||
|
# directory of .o files from prog-objs notation
|
||||||
|
host-objdirs += $(foreach f,$(host-cmulti), \
|
||||||
|
$(foreach m,$($(f)-objs), \
|
||||||
|
$(if $(dir $(m)),$(dir $(m)))))
|
||||||
|
# directory of .o files from prog-cxxobjs notation
|
||||||
|
host-objdirs += $(foreach f,$(host-cxxmulti), \
|
||||||
|
$(foreach m,$($(f)-cxxobjs), \
|
||||||
|
$(if $(dir $(m)),$(dir $(m)))))
|
||||||
|
|
||||||
|
host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs))))
|
||||||
|
|
||||||
|
|
||||||
|
__hostprogs := $(addprefix $(obj)/,$(__hostprogs))
|
||||||
|
host-csingle := $(addprefix $(obj)/,$(host-csingle))
|
||||||
|
host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
|
||||||
|
host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
|
||||||
|
host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
|
||||||
|
host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
|
||||||
|
host-cshlib := $(addprefix $(obj)/,$(host-cshlib))
|
||||||
|
host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs))
|
||||||
|
host-objdirs := $(addprefix $(obj)/,$(host-objdirs))
|
||||||
|
|
||||||
|
obj-dirs += $(host-objdirs)
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Handle options to gcc. Support building with separate output directory
|
||||||
|
|
||||||
|
_hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
|
||||||
|
$(HOSTCFLAGS_$(basetarget).o)
|
||||||
|
_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
|
||||||
|
$(HOSTCXXFLAGS_$(basetarget).o)
|
||||||
|
|
||||||
|
ifeq ($(KBUILD_SRC),)
|
||||||
|
__hostc_flags = $(_hostc_flags)
|
||||||
|
__hostcxx_flags = $(_hostcxx_flags)
|
||||||
|
else
|
||||||
|
__hostc_flags = -I$(obj) $(call flags,_hostc_flags)
|
||||||
|
__hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags)
|
||||||
|
endif
|
||||||
|
|
||||||
|
hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags)
|
||||||
|
hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags)
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Compile programs on the host
|
||||||
|
|
||||||
|
# Create executable from a single .c file
|
||||||
|
# host-csingle -> Executable
|
||||||
|
quiet_cmd_host-csingle = HOSTCC $@
|
||||||
|
cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \
|
||||||
|
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
|
||||||
|
$(host-csingle): %: %.c FORCE
|
||||||
|
$(call if_changed_dep,host-csingle)
|
||||||
|
|
||||||
|
# Link an executable based on list of .o files, all plain c
|
||||||
|
# host-cmulti -> executable
|
||||||
|
quiet_cmd_host-cmulti = HOSTLD $@
|
||||||
|
cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
|
||||||
|
$(addprefix $(obj)/,$($(@F)-objs)) \
|
||||||
|
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
|
||||||
|
$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE
|
||||||
|
$(call if_changed,host-cmulti)
|
||||||
|
|
||||||
|
# Create .o file from a single .c file
|
||||||
|
# host-cobjs -> .o
|
||||||
|
quiet_cmd_host-cobjs = HOSTCC $@
|
||||||
|
cmd_host-cobjs = $(HOSTCC) $(hostc_flags) -c -o $@ $<
|
||||||
|
$(host-cobjs): %.o: %.c FORCE
|
||||||
|
$(call if_changed_dep,host-cobjs)
|
||||||
|
|
||||||
|
# Link an executable based on list of .o files, a mixture of .c and .cc
|
||||||
|
# host-cxxmulti -> executable
|
||||||
|
quiet_cmd_host-cxxmulti = HOSTLD $@
|
||||||
|
cmd_host-cxxmulti = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
|
||||||
|
$(foreach o,objs cxxobjs,\
|
||||||
|
$(addprefix $(obj)/,$($(@F)-$(o)))) \
|
||||||
|
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
|
||||||
|
$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
|
||||||
|
$(call if_changed,host-cxxmulti)
|
||||||
|
|
||||||
|
# Create .o file from a single .cc (C++) file
|
||||||
|
quiet_cmd_host-cxxobjs = HOSTCXX $@
|
||||||
|
cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
|
||||||
|
$(host-cxxobjs): %.o: %.cc FORCE
|
||||||
|
$(call if_changed_dep,host-cxxobjs)
|
||||||
|
|
||||||
|
# Compile .c file, create position independent .o file
|
||||||
|
# host-cshobjs -> .o
|
||||||
|
quiet_cmd_host-cshobjs = HOSTCC -fPIC $@
|
||||||
|
cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
|
||||||
|
$(host-cshobjs): %.o: %.c FORCE
|
||||||
|
$(call if_changed_dep,host-cshobjs)
|
||||||
|
|
||||||
|
# Link a shared library, based on position independent .o files
|
||||||
|
# *.o -> .so shared library (host-cshlib)
|
||||||
|
quiet_cmd_host-cshlib = HOSTLLD -shared $@
|
||||||
|
cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
|
||||||
|
$(addprefix $(obj)/,$($(@F:.so=-objs))) \
|
||||||
|
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
|
||||||
|
$(host-cshlib): %: $(host-cshobjs) FORCE
|
||||||
|
$(call if_changed,host-cshlib)
|
||||||
|
|
||||||
|
targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
|
||||||
|
$(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs)
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
# Backward compatibility - to be removed...
|
||||||
|
extra-y += $(EXTRA_TARGETS)
|
||||||
|
# Figure out what we need to build from the various variables
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
# When an object is listed to be built compiled-in and modular,
|
||||||
|
# only build the compiled-in version
|
||||||
|
|
||||||
|
obj-m := $(filter-out $(obj-y),$(obj-m))
|
||||||
|
|
||||||
|
# Libraries are always collected in one lib file.
|
||||||
|
# Filter out objects already built-in
|
||||||
|
|
||||||
|
lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
|
||||||
|
|
||||||
|
|
||||||
|
# Handle objects in subdirs
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o
|
||||||
|
# and add the directory to the list of dirs to descend into: $(subdir-y)
|
||||||
|
# o if we encounter foo/ in $(obj-m), remove it from $(obj-m)
|
||||||
|
# and add the directory to the list of dirs to descend into: $(subdir-m)
|
||||||
|
|
||||||
|
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
|
||||||
|
subdir-y += $(__subdir-y)
|
||||||
|
__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
|
||||||
|
subdir-m += $(__subdir-m)
|
||||||
|
obj-y := $(patsubst %/, %/built-in.o, $(obj-y))
|
||||||
|
obj-m := $(filter-out %/, $(obj-m))
|
||||||
|
|
||||||
|
# Subdirectories we need to descend into
|
||||||
|
|
||||||
|
subdir-ym := $(sort $(subdir-y) $(subdir-m))
|
||||||
|
|
||||||
|
# if $(foo-objs) exists, foo.o is a composite object
|
||||||
|
multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
|
||||||
|
multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
|
||||||
|
multi-used := $(multi-used-y) $(multi-used-m)
|
||||||
|
single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
|
||||||
|
|
||||||
|
# Build list of the parts of our composite objects, our composite
|
||||||
|
# objects depend on those (obviously)
|
||||||
|
multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y)))
|
||||||
|
multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y)))
|
||||||
|
multi-objs := $(multi-objs-y) $(multi-objs-m)
|
||||||
|
|
||||||
|
# $(subdir-obj-y) is the list of objects in $(obj-y) which do not live
|
||||||
|
# in the local directory
|
||||||
|
subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)))
|
||||||
|
|
||||||
|
# $(obj-dirs) is a list of directories that contain object files
|
||||||
|
obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
|
||||||
|
|
||||||
|
# Replace multi-part objects by their individual parts, look at local dir only
|
||||||
|
real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
|
||||||
|
real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
|
||||||
|
|
||||||
|
# Add subdir path
|
||||||
|
|
||||||
|
extra-y := $(addprefix $(obj)/,$(extra-y))
|
||||||
|
always := $(addprefix $(obj)/,$(always))
|
||||||
|
targets := $(addprefix $(obj)/,$(targets))
|
||||||
|
obj-y := $(addprefix $(obj)/,$(obj-y))
|
||||||
|
obj-m := $(addprefix $(obj)/,$(obj-m))
|
||||||
|
lib-y := $(addprefix $(obj)/,$(lib-y))
|
||||||
|
subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
|
||||||
|
real-objs-y := $(addprefix $(obj)/,$(real-objs-y))
|
||||||
|
real-objs-m := $(addprefix $(obj)/,$(real-objs-m))
|
||||||
|
single-used-m := $(addprefix $(obj)/,$(single-used-m))
|
||||||
|
multi-used-y := $(addprefix $(obj)/,$(multi-used-y))
|
||||||
|
multi-used-m := $(addprefix $(obj)/,$(multi-used-m))
|
||||||
|
multi-objs-y := $(addprefix $(obj)/,$(multi-objs-y))
|
||||||
|
multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m))
|
||||||
|
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
|
||||||
|
obj-dirs := $(addprefix $(obj)/,$(obj-dirs))
|
||||||
|
|
||||||
|
# These flags are needed for modversions and compiling, so we define them here
|
||||||
|
# already
|
||||||
|
# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will
|
||||||
|
# end up in (or would, if it gets compiled in)
|
||||||
|
# Note: It's possible that one object gets potentially linked into more
|
||||||
|
# than one module. In that case KBUILD_MODNAME will be set to foo_bar,
|
||||||
|
# where foo and bar are the name of the modules.
|
||||||
|
name-fix = $(subst $(comma),_,$(subst -,_,$1))
|
||||||
|
basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
|
||||||
|
modname_flags = $(if $(filter 1,$(words $(modname))),\
|
||||||
|
-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
|
||||||
|
|
||||||
|
_c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(basetarget).o)
|
||||||
|
_a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
|
||||||
|
_cpp_flags = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F))
|
||||||
|
|
||||||
|
# If building the kernel in a separate objtree expand all occurrences
|
||||||
|
# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
|
||||||
|
|
||||||
|
ifeq ($(KBUILD_SRC),)
|
||||||
|
__c_flags = $(_c_flags)
|
||||||
|
__a_flags = $(_a_flags)
|
||||||
|
__cpp_flags = $(_cpp_flags)
|
||||||
|
else
|
||||||
|
|
||||||
|
# -I$(obj) locates generated .h files
|
||||||
|
# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
|
||||||
|
# and locates generated .h files
|
||||||
|
# FIXME: Replace both with specific CFLAGS* statements in the makefiles
|
||||||
|
__c_flags = $(call addtree,-I$(obj)) $(call flags,_c_flags)
|
||||||
|
__a_flags = $(call flags,_a_flags)
|
||||||
|
__cpp_flags = $(call flags,_cpp_flags)
|
||||||
|
endif
|
||||||
|
|
||||||
|
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
|
||||||
|
$(__c_flags) $(modkern_cflags) \
|
||||||
|
-D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
|
||||||
|
|
||||||
|
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
|
||||||
|
$(__a_flags) $(modkern_aflags)
|
||||||
|
|
||||||
|
cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
|
||||||
|
|
||||||
|
ld_flags = $(LDFLAGS) $(EXTRA_LDFLAGS)
|
||||||
|
|
||||||
|
# Finds the multi-part object the current object will be linked into
|
||||||
|
modname-multi = $(sort $(foreach m,$(multi-used),\
|
||||||
|
$(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=))))
|
||||||
|
|
||||||
|
# Shipped files
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
quiet_cmd_shipped = SHIPPED $@
|
||||||
|
cmd_shipped = cat $< > $@
|
||||||
|
|
||||||
|
$(obj)/%:: $(src)/%_shipped
|
||||||
|
$(call cmd,shipped)
|
||||||
|
|
||||||
|
# Commands useful for building a boot image
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# Use as following:
|
||||||
|
#
|
||||||
|
# target: source(s) FORCE
|
||||||
|
# $(if_changed,ld/objcopy/gzip)
|
||||||
|
#
|
||||||
|
# and add target to EXTRA_TARGETS so that we know we have to
|
||||||
|
# read in the saved command line
|
||||||
|
|
||||||
|
# Linking
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
quiet_cmd_ld = LD $@
|
||||||
|
cmd_ld = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) \
|
||||||
|
$(filter-out FORCE,$^) -o $@
|
||||||
|
|
||||||
|
# Objcopy
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
quiet_cmd_objcopy = OBJCOPY $@
|
||||||
|
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
|
||||||
|
|
||||||
|
# Gzip
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
quiet_cmd_gzip = GZIP $@
|
||||||
|
cmd_gzip = gzip -f -9 < $< > $@
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
###
|
||||||
|
# Makefile.basic list the most basic programs used during the build process.
|
||||||
|
# The programs listed herein is what is needed to do the basic stuff,
|
||||||
|
# such as fix dependency file.
|
||||||
|
# This initial step is needed to avoid files to be recompiled
|
||||||
|
# when kernel configuration changes (which is what happens when
|
||||||
|
# .config is included by main Makefile.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# fixdep: Used to generate dependency information during build process
|
||||||
|
# docproc: Used in Documentation/docbook
|
||||||
|
|
||||||
|
hostprogs-y := fixdep docproc
|
||||||
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
|
# fixdep is needed to compile other host programs
|
||||||
|
$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
|
|
@ -0,0 +1,399 @@
|
||||||
|
/*
|
||||||
|
* docproc is a simple preprocessor for the template files
|
||||||
|
* used as placeholders for the kernel internal documentation.
|
||||||
|
* docproc is used for documentation-frontend and
|
||||||
|
* dependency-generator.
|
||||||
|
* The two usages have in common that they require
|
||||||
|
* some knowledge of the .tmpl syntax, therefore they
|
||||||
|
* are kept together.
|
||||||
|
*
|
||||||
|
* documentation-frontend
|
||||||
|
* Scans the template file and call kernel-doc for
|
||||||
|
* all occurrences of ![EIF]file
|
||||||
|
* Beforehand each referenced file are scanned for
|
||||||
|
* any exported sympols "EXPORT_SYMBOL()" statements.
|
||||||
|
* This is used to create proper -function and
|
||||||
|
* -nofunction arguments in calls to kernel-doc.
|
||||||
|
* Usage: docproc doc file.tmpl
|
||||||
|
*
|
||||||
|
* dependency-generator:
|
||||||
|
* Scans the template file and list all files
|
||||||
|
* referenced in a format recognized by make.
|
||||||
|
* Usage: docproc depend file.tmpl
|
||||||
|
* Writes dependency information to stdout
|
||||||
|
* in the following format:
|
||||||
|
* file.tmpl src.c src2.c
|
||||||
|
* The filenames are obtained from the following constructs:
|
||||||
|
* !Efilename
|
||||||
|
* !Ifilename
|
||||||
|
* !Dfilename
|
||||||
|
* !Ffilename
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
/* exitstatus is used to keep track of any failing calls to kernel-doc,
|
||||||
|
* but execution continues. */
|
||||||
|
int exitstatus = 0;
|
||||||
|
|
||||||
|
typedef void DFL(char *);
|
||||||
|
DFL *defaultline;
|
||||||
|
|
||||||
|
typedef void FILEONLY(char * file);
|
||||||
|
FILEONLY *internalfunctions;
|
||||||
|
FILEONLY *externalfunctions;
|
||||||
|
FILEONLY *symbolsonly;
|
||||||
|
|
||||||
|
typedef void FILELINE(char * file, char * line);
|
||||||
|
FILELINE * singlefunctions;
|
||||||
|
FILELINE * entity_system;
|
||||||
|
|
||||||
|
#define MAXLINESZ 2048
|
||||||
|
#define MAXFILES 250
|
||||||
|
#define KERNELDOCPATH "scripts/"
|
||||||
|
#define KERNELDOC "kernel-doc"
|
||||||
|
#define DOCBOOK "-docbook"
|
||||||
|
#define FUNCTION "-function"
|
||||||
|
#define NOFUNCTION "-nofunction"
|
||||||
|
|
||||||
|
void usage (void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: docproc {doc|depend} file\n");
|
||||||
|
fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
|
||||||
|
fprintf(stderr, "doc: frontend when generating kernel documentation\n");
|
||||||
|
fprintf(stderr, "depend: generate list of files referenced within file\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Execute kernel-doc with parameters givin in svec
|
||||||
|
*/
|
||||||
|
void exec_kernel_doc(char **svec)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
int ret;
|
||||||
|
char real_filename[PATH_MAX + 1];
|
||||||
|
/* Make sure output generated so far are flushed */
|
||||||
|
fflush(stdout);
|
||||||
|
switch(pid=fork()) {
|
||||||
|
case -1:
|
||||||
|
perror("fork");
|
||||||
|
exit(1);
|
||||||
|
case 0:
|
||||||
|
memset(real_filename, 0, sizeof(real_filename));
|
||||||
|
strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
|
||||||
|
strncat(real_filename, KERNELDOCPATH KERNELDOC,
|
||||||
|
PATH_MAX - strlen(real_filename));
|
||||||
|
execvp(real_filename, svec);
|
||||||
|
fprintf(stderr, "exec ");
|
||||||
|
perror(real_filename);
|
||||||
|
exit(1);
|
||||||
|
default:
|
||||||
|
waitpid(pid, &ret ,0);
|
||||||
|
}
|
||||||
|
if (WIFEXITED(ret))
|
||||||
|
exitstatus |= WEXITSTATUS(ret);
|
||||||
|
else
|
||||||
|
exitstatus = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Types used to create list of all exported symbols in a number of files */
|
||||||
|
struct symbols
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct symfile
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
struct symbols *symbollist;
|
||||||
|
int symbolcnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct symfile symfilelist[MAXFILES];
|
||||||
|
int symfilecnt = 0;
|
||||||
|
|
||||||
|
void add_new_symbol(struct symfile *sym, char * symname)
|
||||||
|
{
|
||||||
|
sym->symbollist =
|
||||||
|
realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
|
||||||
|
sym->symbollist[sym->symbolcnt++].name = strdup(symname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a filename to the list */
|
||||||
|
struct symfile * add_new_file(char * filename)
|
||||||
|
{
|
||||||
|
symfilelist[symfilecnt++].filename = strdup(filename);
|
||||||
|
return &symfilelist[symfilecnt - 1];
|
||||||
|
}
|
||||||
|
/* Check if file already are present in the list */
|
||||||
|
struct symfile * filename_exist(char * filename)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i < symfilecnt; i++)
|
||||||
|
if (strcmp(symfilelist[i].filename, filename) == 0)
|
||||||
|
return &symfilelist[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List all files referenced within the template file.
|
||||||
|
* Files are separated by tabs.
|
||||||
|
*/
|
||||||
|
void adddep(char * file) { printf("\t%s", file); }
|
||||||
|
void adddep2(char * file, char * line) { line = line; adddep(file); }
|
||||||
|
void noaction(char * line) { line = line; }
|
||||||
|
void noaction2(char * file, char * line) { file = file; line = line; }
|
||||||
|
|
||||||
|
/* Echo the line without further action */
|
||||||
|
void printline(char * line) { printf("%s", line); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
|
||||||
|
* in filename.
|
||||||
|
* All symbols located are stored in symfilelist.
|
||||||
|
*/
|
||||||
|
void find_export_symbols(char * filename)
|
||||||
|
{
|
||||||
|
FILE * fp;
|
||||||
|
struct symfile *sym;
|
||||||
|
char line[MAXLINESZ];
|
||||||
|
if (filename_exist(filename) == NULL) {
|
||||||
|
char real_filename[PATH_MAX + 1];
|
||||||
|
memset(real_filename, 0, sizeof(real_filename));
|
||||||
|
strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
|
||||||
|
strncat(real_filename, filename,
|
||||||
|
PATH_MAX - strlen(real_filename));
|
||||||
|
sym = add_new_file(filename);
|
||||||
|
fp = fopen(real_filename, "r");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "docproc: ");
|
||||||
|
perror(real_filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
while(fgets(line, MAXLINESZ, fp)) {
|
||||||
|
char *p;
|
||||||
|
char *e;
|
||||||
|
if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
|
||||||
|
((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
|
||||||
|
/* Skip EXPORT_SYMBOL{_GPL} */
|
||||||
|
while (isalnum(*p) || *p == '_')
|
||||||
|
p++;
|
||||||
|
/* Remove paranteses and additional ws */
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
if (*p != '(')
|
||||||
|
continue; /* Syntax error? */
|
||||||
|
else
|
||||||
|
p++;
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
e = p;
|
||||||
|
while (isalnum(*e) || *e == '_')
|
||||||
|
e++;
|
||||||
|
*e = '\0';
|
||||||
|
add_new_symbol(sym, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Document all external or internal functions in a file.
|
||||||
|
* Call kernel-doc with following parameters:
|
||||||
|
* kernel-doc -docbook -nofunction function_name1 filename
|
||||||
|
* function names are obtained from all the the src files
|
||||||
|
* by find_export_symbols.
|
||||||
|
* intfunc uses -nofunction
|
||||||
|
* extfunc uses -function
|
||||||
|
*/
|
||||||
|
void docfunctions(char * filename, char * type)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
int symcnt = 0;
|
||||||
|
int idx = 0;
|
||||||
|
char **vec;
|
||||||
|
|
||||||
|
for (i=0; i <= symfilecnt; i++)
|
||||||
|
symcnt += symfilelist[i].symbolcnt;
|
||||||
|
vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*));
|
||||||
|
if (vec == NULL) {
|
||||||
|
perror("docproc: ");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
vec[idx++] = KERNELDOC;
|
||||||
|
vec[idx++] = DOCBOOK;
|
||||||
|
for (i=0; i < symfilecnt; i++) {
|
||||||
|
struct symfile * sym = &symfilelist[i];
|
||||||
|
for (j=0; j < sym->symbolcnt; j++) {
|
||||||
|
vec[idx++] = type;
|
||||||
|
vec[idx++] = sym->symbollist[j].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec[idx++] = filename;
|
||||||
|
vec[idx] = NULL;
|
||||||
|
printf("<!-- %s -->\n", filename);
|
||||||
|
exec_kernel_doc(vec);
|
||||||
|
fflush(stdout);
|
||||||
|
free(vec);
|
||||||
|
}
|
||||||
|
void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
|
||||||
|
void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Document specific function(s) in a file.
|
||||||
|
* Call kernel-doc with the following parameters:
|
||||||
|
* kernel-doc -docbook -function function1 [-function function2]
|
||||||
|
*/
|
||||||
|
void singfunc(char * filename, char * line)
|
||||||
|
{
|
||||||
|
char *vec[200]; /* Enough for specific functions */
|
||||||
|
int i, idx = 0;
|
||||||
|
int startofsym = 1;
|
||||||
|
vec[idx++] = KERNELDOC;
|
||||||
|
vec[idx++] = DOCBOOK;
|
||||||
|
|
||||||
|
/* Split line up in individual parameters preceeded by FUNCTION */
|
||||||
|
for (i=0; line[i]; i++) {
|
||||||
|
if (isspace(line[i])) {
|
||||||
|
line[i] = '\0';
|
||||||
|
startofsym = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (startofsym) {
|
||||||
|
startofsym = 0;
|
||||||
|
vec[idx++] = FUNCTION;
|
||||||
|
vec[idx++] = &line[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec[idx++] = filename;
|
||||||
|
vec[idx] = NULL;
|
||||||
|
exec_kernel_doc(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse file, calling action specific functions for:
|
||||||
|
* 1) Lines containing !E
|
||||||
|
* 2) Lines containing !I
|
||||||
|
* 3) Lines containing !D
|
||||||
|
* 4) Lines containing !F
|
||||||
|
* 5) Default lines - lines not matching the above
|
||||||
|
*/
|
||||||
|
void parse_file(FILE *infile)
|
||||||
|
{
|
||||||
|
char line[MAXLINESZ];
|
||||||
|
char * s;
|
||||||
|
while(fgets(line, MAXLINESZ, infile)) {
|
||||||
|
if (line[0] == '!') {
|
||||||
|
s = line + 2;
|
||||||
|
switch (line[1]) {
|
||||||
|
case 'E':
|
||||||
|
while (*s && !isspace(*s)) s++;
|
||||||
|
*s = '\0';
|
||||||
|
externalfunctions(line+2);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
while (*s && !isspace(*s)) s++;
|
||||||
|
*s = '\0';
|
||||||
|
internalfunctions(line+2);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
while (*s && !isspace(*s)) s++;
|
||||||
|
*s = '\0';
|
||||||
|
symbolsonly(line+2);
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
/* filename */
|
||||||
|
while (*s && !isspace(*s)) s++;
|
||||||
|
*s++ = '\0';
|
||||||
|
/* function names */
|
||||||
|
while (isspace(*s))
|
||||||
|
s++;
|
||||||
|
singlefunctions(line +2, s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
defaultline(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
defaultline(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
FILE * infile;
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* Open file, exit on error */
|
||||||
|
infile = fopen(argv[2], "r");
|
||||||
|
if (infile == NULL) {
|
||||||
|
fprintf(stderr, "docproc: ");
|
||||||
|
perror(argv[2]);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp("doc", argv[1]) == 0)
|
||||||
|
{
|
||||||
|
/* Need to do this in two passes.
|
||||||
|
* First pass is used to collect all symbols exported
|
||||||
|
* in the various files.
|
||||||
|
* Second pass generate the documentation.
|
||||||
|
* This is required because function are declared
|
||||||
|
* and exported in different files :-((
|
||||||
|
*/
|
||||||
|
/* Collect symbols */
|
||||||
|
defaultline = noaction;
|
||||||
|
internalfunctions = find_export_symbols;
|
||||||
|
externalfunctions = find_export_symbols;
|
||||||
|
symbolsonly = find_export_symbols;
|
||||||
|
singlefunctions = noaction2;
|
||||||
|
parse_file(infile);
|
||||||
|
|
||||||
|
/* Rewind to start from beginning of file again */
|
||||||
|
fseek(infile, 0, SEEK_SET);
|
||||||
|
defaultline = printline;
|
||||||
|
internalfunctions = intfunc;
|
||||||
|
externalfunctions = extfunc;
|
||||||
|
symbolsonly = printline;
|
||||||
|
singlefunctions = singfunc;
|
||||||
|
|
||||||
|
parse_file(infile);
|
||||||
|
}
|
||||||
|
else if (strcmp("depend", argv[1]) == 0)
|
||||||
|
{
|
||||||
|
/* Create first part of dependency chain
|
||||||
|
* file.tmpl */
|
||||||
|
printf("%s\t", argv[2]);
|
||||||
|
defaultline = noaction;
|
||||||
|
internalfunctions = adddep;
|
||||||
|
externalfunctions = adddep;
|
||||||
|
symbolsonly = adddep;
|
||||||
|
singlefunctions = adddep2;
|
||||||
|
parse_file(infile);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unknown option: %s\n", argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fclose(infile);
|
||||||
|
fflush(stdout);
|
||||||
|
return exitstatus;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,393 @@
|
||||||
|
/*
|
||||||
|
* "Optimize" a list of dependencies as spit out by gcc -MD
|
||||||
|
* for the kernel build
|
||||||
|
* ===========================================================================
|
||||||
|
*
|
||||||
|
* Author Kai Germaschewski
|
||||||
|
* Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de>
|
||||||
|
*
|
||||||
|
* This software may be used and distributed according to the terms
|
||||||
|
* of the GNU General Public License, incorporated herein by reference.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Introduction:
|
||||||
|
*
|
||||||
|
* gcc produces a very nice and correct list of dependencies which
|
||||||
|
* tells make when to remake a file.
|
||||||
|
*
|
||||||
|
* To use this list as-is however has the drawback that virtually
|
||||||
|
* every file in the kernel includes <linux/config.h> which then again
|
||||||
|
* includes <linux/autoconf.h>
|
||||||
|
*
|
||||||
|
* If the user re-runs make *config, linux/autoconf.h will be
|
||||||
|
* regenerated. make notices that and will rebuild every file which
|
||||||
|
* includes autoconf.h, i.e. basically all files. This is extremely
|
||||||
|
* annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
|
||||||
|
*
|
||||||
|
* So we play the same trick that "mkdep" played before. We replace
|
||||||
|
* the dependency on linux/autoconf.h by a dependency on every config
|
||||||
|
* option which is mentioned in any of the listed prequisites.
|
||||||
|
*
|
||||||
|
* To be exact, split-include populates a tree in include/config/,
|
||||||
|
* e.g. include/config/his/driver.h, which contains the #define/#undef
|
||||||
|
* for the CONFIG_HIS_DRIVER option.
|
||||||
|
*
|
||||||
|
* So if the user changes his CONFIG_HIS_DRIVER option, only the objects
|
||||||
|
* which depend on "include/linux/config/his/driver.h" will be rebuilt,
|
||||||
|
* so most likely only his driver ;-)
|
||||||
|
*
|
||||||
|
* The idea above dates, by the way, back to Michael E Chastain, AFAIK.
|
||||||
|
*
|
||||||
|
* So to get dependencies right, there are two issues:
|
||||||
|
* o if any of the files the compiler read changed, we need to rebuild
|
||||||
|
* o if the command line given to the compile the file changed, we
|
||||||
|
* better rebuild as well.
|
||||||
|
*
|
||||||
|
* The former is handled by using the -MD output, the later by saving
|
||||||
|
* the command line used to compile the old object and comparing it
|
||||||
|
* to the one we would now use.
|
||||||
|
*
|
||||||
|
* Again, also this idea is pretty old and has been discussed on
|
||||||
|
* kbuild-devel a long time ago. I don't have a sensibly working
|
||||||
|
* internet connection right now, so I rather don't mention names
|
||||||
|
* without double checking.
|
||||||
|
*
|
||||||
|
* This code here has been based partially based on mkdep.c, which
|
||||||
|
* says the following about its history:
|
||||||
|
*
|
||||||
|
* Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
|
||||||
|
* This is a C version of syncdep.pl by Werner Almesberger.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* It is invoked as
|
||||||
|
*
|
||||||
|
* fixdep <depfile> <target> <cmdline>
|
||||||
|
*
|
||||||
|
* and will read the dependency file <depfile>
|
||||||
|
*
|
||||||
|
* The transformed dependency snipped is written to stdout.
|
||||||
|
*
|
||||||
|
* It first generates a line
|
||||||
|
*
|
||||||
|
* cmd_<target> = <cmdline>
|
||||||
|
*
|
||||||
|
* and then basically copies the .<target>.d file to stdout, in the
|
||||||
|
* process filtering out the dependency on linux/autoconf.h and adding
|
||||||
|
* dependencies on include/config/my/option.h for every
|
||||||
|
* CONFIG_MY_OPTION encountered in any of the prequisites.
|
||||||
|
*
|
||||||
|
* It will also filter out all the dependencies on *.ver. We need
|
||||||
|
* to make sure that the generated version checksum are globally up
|
||||||
|
* to date before even starting the recursive build, so it's too late
|
||||||
|
* at this point anyway.
|
||||||
|
*
|
||||||
|
* The algorithm to grep for "CONFIG_..." is bit unusual, but should
|
||||||
|
* be fast ;-) We don't even try to really parse the header files, but
|
||||||
|
* merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
|
||||||
|
* be picked up as well. It's not a problem with respect to
|
||||||
|
* correctness, since that can only give too many dependencies, thus
|
||||||
|
* we cannot miss a rebuild. Since people tend to not mention totally
|
||||||
|
* unrelated CONFIG_ options all over the place, it's not an
|
||||||
|
* efficiency problem either.
|
||||||
|
*
|
||||||
|
* (Note: it'd be easy to port over the complete mkdep state machine,
|
||||||
|
* but I don't think the added complexity is worth it)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
|
||||||
|
* CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
|
||||||
|
* fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
|
||||||
|
* UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
|
||||||
|
* through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
|
||||||
|
* those files will have correct dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define INT_CONF ntohl(0x434f4e46)
|
||||||
|
#define INT_ONFI ntohl(0x4f4e4649)
|
||||||
|
#define INT_NFIG ntohl(0x4e464947)
|
||||||
|
#define INT_FIG_ ntohl(0x4649475f)
|
||||||
|
|
||||||
|
char *target;
|
||||||
|
char *depfile;
|
||||||
|
char *cmdline;
|
||||||
|
|
||||||
|
void usage(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print out the commandline prefixed with cmd_<target filename> :=
|
||||||
|
*/
|
||||||
|
void print_cmdline(void)
|
||||||
|
{
|
||||||
|
printf("cmd_%s := %s\n\n", target, cmdline);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * str_config = NULL;
|
||||||
|
int size_config = 0;
|
||||||
|
int len_config = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grow the configuration string to a desired length.
|
||||||
|
* Usually the first growth is plenty.
|
||||||
|
*/
|
||||||
|
void grow_config(int len)
|
||||||
|
{
|
||||||
|
while (len_config + len > size_config) {
|
||||||
|
if (size_config == 0)
|
||||||
|
size_config = 2048;
|
||||||
|
str_config = realloc(str_config, size_config *= 2);
|
||||||
|
if (str_config == NULL)
|
||||||
|
{ perror("fixdep:malloc"); exit(1); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup a value in the configuration string.
|
||||||
|
*/
|
||||||
|
int is_defined_config(const char * name, int len)
|
||||||
|
{
|
||||||
|
const char * pconfig;
|
||||||
|
const char * plast = str_config + len_config - len;
|
||||||
|
for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
|
||||||
|
if (pconfig[ -1] == '\n'
|
||||||
|
&& pconfig[len] == '\n'
|
||||||
|
&& !memcmp(pconfig, name, len))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a new value to the configuration string.
|
||||||
|
*/
|
||||||
|
void define_config(const char * name, int len)
|
||||||
|
{
|
||||||
|
grow_config(len + 1);
|
||||||
|
|
||||||
|
memcpy(str_config+len_config, name, len);
|
||||||
|
len_config += len;
|
||||||
|
str_config[len_config++] = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the set of configuration strings.
|
||||||
|
*/
|
||||||
|
void clear_config(void)
|
||||||
|
{
|
||||||
|
len_config = 0;
|
||||||
|
define_config("", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the use of a CONFIG_* word.
|
||||||
|
*/
|
||||||
|
void use_config(char *m, int slen)
|
||||||
|
{
|
||||||
|
char s[PATH_MAX];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (is_defined_config(m, slen))
|
||||||
|
return;
|
||||||
|
|
||||||
|
define_config(m, slen);
|
||||||
|
|
||||||
|
memcpy(s, m, slen); s[slen] = 0;
|
||||||
|
|
||||||
|
for (p = s; p < s + slen; p++) {
|
||||||
|
if (*p == '_')
|
||||||
|
*p = '/';
|
||||||
|
else
|
||||||
|
*p = tolower((int)*p);
|
||||||
|
}
|
||||||
|
printf(" $(wildcard include/config/%s.h) \\\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_config_file(char *map, size_t len)
|
||||||
|
{
|
||||||
|
int *end = (int *) (map + len);
|
||||||
|
/* start at +1, so that p can never be < map */
|
||||||
|
int *m = (int *) map + 1;
|
||||||
|
char *p, *q;
|
||||||
|
|
||||||
|
for (; m < end; m++) {
|
||||||
|
if (*m == INT_CONF) { p = (char *) m ; goto conf; }
|
||||||
|
if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
|
||||||
|
if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
|
||||||
|
if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
|
||||||
|
continue;
|
||||||
|
conf:
|
||||||
|
if (p > map + len - 7)
|
||||||
|
continue;
|
||||||
|
if (memcmp(p, "CONFIG_", 7))
|
||||||
|
continue;
|
||||||
|
for (q = p + 7; q < map + len; q++) {
|
||||||
|
if (!(isalnum(*q) || *q == '_'))
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
|
||||||
|
found:
|
||||||
|
use_config(p+7, q-p-7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test is s ends in sub */
|
||||||
|
int strrcmp(char *s, char *sub)
|
||||||
|
{
|
||||||
|
int slen = strlen(s);
|
||||||
|
int sublen = strlen(sub);
|
||||||
|
|
||||||
|
if (sublen > slen)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return memcmp(s + slen - sublen, sub, sublen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_config_file(char *filename)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
int fd;
|
||||||
|
void *map;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "fixdep: ");
|
||||||
|
perror(filename);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
fstat(fd, &st);
|
||||||
|
if (st.st_size == 0) {
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if ((long) map == -1) {
|
||||||
|
perror("fixdep: mmap");
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_config_file(map, st.st_size);
|
||||||
|
|
||||||
|
munmap(map, st.st_size);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_dep_file(void *map, size_t len)
|
||||||
|
{
|
||||||
|
char *m = map;
|
||||||
|
char *end = m + len;
|
||||||
|
char *p;
|
||||||
|
char s[PATH_MAX];
|
||||||
|
|
||||||
|
p = strchr(m, ':');
|
||||||
|
if (!p) {
|
||||||
|
fprintf(stderr, "fixdep: parse error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memcpy(s, m, p-m); s[p-m] = 0;
|
||||||
|
printf("deps_%s := \\\n", target);
|
||||||
|
m = p+1;
|
||||||
|
|
||||||
|
clear_config();
|
||||||
|
|
||||||
|
while (m < end) {
|
||||||
|
while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
|
||||||
|
m++;
|
||||||
|
p = m;
|
||||||
|
while (p < end && *p != ' ') p++;
|
||||||
|
if (p == end) {
|
||||||
|
do p--; while (!isalnum(*p));
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
memcpy(s, m, p-m); s[p-m] = 0;
|
||||||
|
if (strrcmp(s, "include/linux/autoconf.h") &&
|
||||||
|
strrcmp(s, "arch/um/include/uml-config.h") &&
|
||||||
|
strrcmp(s, ".ver")) {
|
||||||
|
printf(" %s \\\n", s);
|
||||||
|
do_config_file(s);
|
||||||
|
}
|
||||||
|
m = p + 1;
|
||||||
|
}
|
||||||
|
printf("\n%s: $(deps_%s)\n\n", target, target);
|
||||||
|
printf("$(deps_%s):\n", target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_deps(void)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
int fd;
|
||||||
|
void *map;
|
||||||
|
|
||||||
|
fd = open(depfile, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "fixdep: ");
|
||||||
|
perror(depfile);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
fstat(fd, &st);
|
||||||
|
if (st.st_size == 0) {
|
||||||
|
fprintf(stderr,"fixdep: %s is empty\n",depfile);
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if ((long) map == -1) {
|
||||||
|
perror("fixdep: mmap");
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_dep_file(map, st.st_size);
|
||||||
|
|
||||||
|
munmap(map, st.st_size);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void traps(void)
|
||||||
|
{
|
||||||
|
static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
|
||||||
|
|
||||||
|
if (*(int *)test != INT_CONF) {
|
||||||
|
fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
|
||||||
|
*(int *)test);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
traps();
|
||||||
|
|
||||||
|
if (argc != 4)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
depfile = argv[1];
|
||||||
|
target = argv[2];
|
||||||
|
cmdline = argv[3];
|
||||||
|
|
||||||
|
print_cmdline();
|
||||||
|
print_deps();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue