394 lines
10 KiB
Plaintext
394 lines
10 KiB
Plaintext
##
|
|
# A set of makefile rules loosely based on kbuild.
|
|
|
|
default: compile
|
|
|
|
all: compile docs
|
|
|
|
test check:
|
|
|
|
ifndef build
|
|
|
|
toplevelrun:=yes
|
|
|
|
##
|
|
# Disable default rules and make output pretty.
|
|
|
|
MAKEFLAGS += -rR --no-print-directory
|
|
|
|
Makefile: ;
|
|
|
|
ifdef V
|
|
ifeq ("$(origin V)", "command line")
|
|
VERBOSE = $(V)
|
|
endif
|
|
endif
|
|
ifndef VERBOSE
|
|
VERBOSE = 0
|
|
endif
|
|
|
|
ifeq ($(VERBOSE),1)
|
|
quiet =
|
|
Q =
|
|
else
|
|
quiet=quiet_
|
|
Q = @
|
|
endif
|
|
|
|
ifneq ($(findstring s,$(MAKEFLAGS)),)
|
|
quiet=silent_
|
|
endif
|
|
|
|
export quiet Q VERBOSE
|
|
|
|
##
|
|
# Recursion helpers.
|
|
srctree := $(CURDIR)
|
|
objtree := $(CURDIR)
|
|
|
|
export srctree objtree
|
|
|
|
##
|
|
# Consult SCM for better version string.
|
|
|
|
TAGPREFIX ?= v
|
|
|
|
ifneq ($(CI_COMMIT_TAG),)
|
|
FULL_VERSION := $(CI_COMMIT_TAG)
|
|
else ifneq ($(CI_COMMIT_REF_NAME),)
|
|
# GitLab but no tag info, use the 'git describe' from environment variable
|
|
# once https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1633
|
|
# gets completed and merged upstream.
|
|
FULL_VERSION := $(VERSION)
|
|
else ifneq ($(wildcard .git),)
|
|
FULL_VERSION := $(patsubst $(TAGPREFIX)%,%,$(shell git describe))
|
|
else
|
|
FULL_VERSION := $(VERSION)
|
|
endif
|
|
|
|
RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
|
|
|
|
export FULL_VERSION RCS_FIND_IGNORE
|
|
|
|
##
|
|
# Utilities and default flags for them.
|
|
|
|
CROSS_COMPILE ?=
|
|
CC := $(CROSS_COMPILE)gcc
|
|
AR := $(CROSS_COMPILE)ar
|
|
LD := $(CROSS_COMPILE)ld
|
|
LN := ln -sf
|
|
SCDOC := scdoc
|
|
SED := sed
|
|
INSTALL := install
|
|
INSTALLDIR := $(INSTALL) -d
|
|
|
|
CFLAGS ?= -g -O2
|
|
CFLAGS_ALL := -Werror -Wall -Wstrict-prototypes -D_GNU_SOURCE -std=gnu99 -fPIC
|
|
CFLAGS_ALL += $(CFLAGS)
|
|
|
|
LDFLAGS ?= -g
|
|
LDFLAGS_ALL += $(LDFLAGS)
|
|
|
|
export CC AR LD LN SCDOC SED INSTALL INSTALLDIR CFLAGS_ALL LDFLAGS_ALL
|
|
|
|
build :=
|
|
|
|
endif
|
|
|
|
##
|
|
# Reset all variables.
|
|
ifneq ($(origin subdirs),file)
|
|
subdirs :=
|
|
endif
|
|
ifneq ($(origin targets),file)
|
|
targets :=
|
|
endif
|
|
ifneq ($(origin nontargets),file)
|
|
nontargets :=
|
|
endif
|
|
|
|
src :=
|
|
obj :=
|
|
|
|
src += $(build)
|
|
obj := $(build)
|
|
|
|
##
|
|
# Include directory specific stuff
|
|
|
|
ifneq ($(build),)
|
|
$(build)/Makefile: ;
|
|
include $(build)/Makefile
|
|
endif
|
|
|
|
##
|
|
# Rules and helpers
|
|
|
|
PHONY += all compile install clean docs FORCE
|
|
|
|
# Convinient variables
|
|
comma := ,
|
|
squote := '
|
|
empty :=
|
|
space := $(empty) $(empty)
|
|
|
|
# The temporary file to save gcc -MD generated dependencies must not
|
|
# contain a comma
|
|
depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
|
|
|
|
build-dir = $(patsubst %/,%,$(dir $@))
|
|
target-dir = $(dir $@)
|
|
|
|
##
|
|
# Build rules
|
|
|
|
ifneq ($(NOCMDDEP),1)
|
|
# Check if both arguments has same arguments. Result in empty string if equal
|
|
# User may override this check using make NOCMDDEP=1
|
|
# Check if both arguments has same arguments. Result is 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 used, if $(quiet) equals `quiet_', otherwise full one.
|
|
echo-cmd = $(if $($(quiet)cmd_$(1)),\
|
|
echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
|
|
|
|
make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
|
|
|
|
# printing commands
|
|
cmd = @$(echo-cmd) $(cmd_$(1))
|
|
|
|
# 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)
|
|
|
|
# Escape single quote for use in echo statements
|
|
escsq = $(subst $(squote),'\$(squote)',$1)
|
|
|
|
# Find any prerequisites that is newer than target or that does not exist.
|
|
# PHONY targets skipped in both cases.
|
|
local-target-prereqs = %
|
|
any-prereq = $(filter $(local-target-prereqs), $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^), $^))
|
|
|
|
# Execute command if command has changed or prerequisite(s) are updated.
|
|
#
|
|
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
|
|
@set -e; \
|
|
$(echo-cmd) $(cmd_$(1)); \
|
|
echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
|
|
|
|
# Usage: $(call if_changed_rule,foo)
|
|
# Will check if $(cmd_foo) or any of the prerequisites changed,
|
|
# and if so will execute $(rule_foo).
|
|
if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
|
|
@set -e; \
|
|
$(rule_$(1)))
|
|
|
|
#####
|
|
# Handle options to gcc.
|
|
|
|
c_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CPPFLAGS) \
|
|
$(CFLAGS_ALL) $(CFLAGS_EXTRA) $(CFLAGS_$(notdir $@))
|
|
ld_flags = $(LDFLAGS_ALL) $(LDFLAGS_EXTRA) $(LDFLAGS_$(notdir $@))
|
|
|
|
#####
|
|
# Generated targets
|
|
generate: $(addprefix $(obj)/,$(sort $(generate-y)))
|
|
|
|
#####
|
|
# Compile c-files.
|
|
quiet_cmd_cc_o_c = CC $@
|
|
|
|
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
|
|
|
|
define rule_cc_o_c
|
|
$(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
|
|
(echo 'cmd_$@ := $(call make-cmd,cc_o_c)'; echo; cat $(depfile)) \
|
|
> $(dot-target).cmd ; \
|
|
rm $(depfile)
|
|
endef
|
|
|
|
$(obj)/%.o: override local-target-prereqs=%
|
|
|
|
$(obj)/%.o: $(src)/%.c FORCE | generate
|
|
$(call if_changed_rule,cc_o_c)
|
|
|
|
#####
|
|
# Link static libraries
|
|
#
|
|
__arlibs := $(addprefix $(obj)/,$(sort $(libs-y)))
|
|
arobjs := $(addprefix $(obj)/,$(sort $(foreach m,$(libs-y),$($(m)-objs))))
|
|
|
|
# link shared library
|
|
quiet_cmd_ar = AR $@
|
|
cmd_ar = $(AR) rcs $@ $(addprefix $(obj)/,$($(@F)-objs))
|
|
|
|
$(__arlibs): override local-target-prereqs=$(addprefix $(obj)/,$($(*F)-objs))
|
|
|
|
$(__arlibs): $(obj)/%: $(arobjs) FORCE
|
|
$(call if_changed,ar)
|
|
|
|
targets += $(__arlibs) $(arobjs)
|
|
|
|
#####
|
|
# Link shared libraries
|
|
#
|
|
__shlibs := $(addprefix $(obj)/,$(sort $(shlibs-y)))
|
|
shobjs := $(addprefix $(obj)/,$(sort $(foreach m,$(shlibs-y),$($(m)-objs)))) $(sort $(foreach m,$(shlibs-y),$($(m)-libs)))
|
|
|
|
# link shared library
|
|
quiet_cmd_shlib = LD -shared $@
|
|
cmd_shlib = $(CC) $(ld_flags) -shared -o $@ \
|
|
$(addprefix $(obj)/,$($(@F)-objs)) \
|
|
$($(@F)-libs) \
|
|
$(LIBS) $(LIBS_$(@F))
|
|
|
|
$(__shlibs): override local-target-prereqs=$(addprefix $(obj)/,$($(*F)-objs)) $($(*F)-libs)
|
|
|
|
$(__shlibs): $(obj)/%: $(shobjs) FORCE
|
|
$(call if_changed,shlib)
|
|
|
|
targets += $(__shlibs) $(shobjs)
|
|
|
|
#####
|
|
# Link programs
|
|
|
|
# Link an executable based on list of .o files, all plain c
|
|
# host-cmulti -> executable
|
|
__progs := $(addprefix $(obj)/,$(sort $(progs-y)))
|
|
cobjs := $(addprefix $(obj)/,$(sort $(foreach m,$(progs-y),$($(m)-objs)))) $(sort $(foreach m,$(progs-y),$($(m)-libs)))
|
|
|
|
quiet_cmd_ld = LD $@
|
|
cmd_ld = $(CC) $(ld_flags) -o $@ \
|
|
$(addprefix $(obj)/,$($(@F)-objs)) $($(@F)-libs) \
|
|
$(LIBS) $(LIBS_$(@F))
|
|
|
|
$(__progs): override local-target-prereqs=$(addprefix $(obj)/,$($(*F)-objs)) $($(*F)-libs)
|
|
|
|
$(__progs): $(obj)/%: $(cobjs) FORCE
|
|
$(call if_changed,ld)
|
|
|
|
targets += $(__progs) $(cobjs)
|
|
|
|
#####
|
|
# Man pages
|
|
|
|
quiet_cmd_scdoc = SCDOC $@
|
|
cmd_scdoc = $(SCDOC) < $< > $@
|
|
|
|
__scdocs := $(addprefix $(obj)/,$(sort $(scdocs-y)))
|
|
nontargets += $(__scdocs)
|
|
docs += $(__scdocs)
|
|
|
|
$(__scdocs): $(obj)/%: $(src)/%.scd FORCE
|
|
$(call if_changed,scdoc)
|
|
|
|
####
|
|
# Template (.in) files
|
|
|
|
quiet_cmd_sed = SED $@
|
|
cmd_sed = $(SED) \
|
|
-e "s|@EXEC_DIR@|$(SBINDIR)|" \
|
|
-e "s|@LIB_DIR@|$(LIBDIR)|" \
|
|
-e "s|@INCLUDE_DIR@|$(INCLUDEDIR)|" \
|
|
-e "s|@VERSION@|$(VERSION)|" \
|
|
$< > $@
|
|
|
|
$(obj)/%: $(src)/%.in FORCE
|
|
$(call if_changed,sed)
|
|
|
|
|
|
nontargets += $(addprefix $(obj)/,$(sort $(generate-y)))
|
|
|
|
###
|
|
# why - tell why a a target got build
|
|
ifeq ($(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: $(arg-check), \
|
|
$(if $(filter $@, $(targets) $(nontargets)), \
|
|
- due to missing .cmd file, \
|
|
- due to $(notdir $@) not in $$(targets) or $$(nontargets) \
|
|
) \
|
|
) \
|
|
) \
|
|
), \
|
|
- due to target missing \
|
|
) \
|
|
)
|
|
|
|
echo-why = $(call escsq, $(strip $(why)))
|
|
endif
|
|
|
|
##
|
|
# Top level rules.
|
|
|
|
%/: FORCE
|
|
$(Q)$(MAKE) -f Make.rules build=$(build-dir) $(MAKECMDGOALS)
|
|
|
|
compile: generate $(targets) $(subdirs)
|
|
@:
|
|
|
|
docs: $(docs) $(subdirs)
|
|
@:
|
|
|
|
install: compile docs $(subdirs) FORCE
|
|
|
|
tag:
|
|
|
|
generate:
|
|
|
|
clean: $(subdirs)
|
|
ifeq ($(toplevelrun),yes)
|
|
$(Q)find . $(RCS_FIND_IGNORE) \
|
|
\( -name '*.[oas]' -o -name '.*.cmd' -o -name '.*.d' \) \
|
|
-type f -print | xargs rm -f
|
|
endif
|
|
$(Q)rm -rf $(addprefix $(obj)/, \
|
|
$(sort $(progs-y) $(progs-n) $(progs-) \
|
|
$(shlibs-y) $(shlibs-n) $(shlibs-) \
|
|
$(libs-y) $(libs-n) $(libs-) \
|
|
$(generate-y) $(generate-n) $(generate-) \
|
|
$(scdocs-y) $(scdocs-n) $(scdocs-)))
|
|
|
|
ifeq ($(origin VERSION),command line)
|
|
DIST_VERSION=$(VERSION)
|
|
else
|
|
DIST_VERSION=$(FULL_VERSION)
|
|
endif
|
|
|
|
dist:
|
|
git archive --format tar --prefix=$(PACKAGE)-$(DIST_VERSION)/ \
|
|
$(TAGPREFIX)$(DIST_VERSION) \
|
|
| bzip2 -9 > $(PACKAGE)-$(DIST_VERSION).tar.bz2
|
|
|
|
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)))
|
|
docs := $(wildcard $(sort $(docs)))
|
|
cmd_files := $(wildcard $(foreach f,$(targets) $(nontargets),$(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)
|