diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-04-16 13:49:16 +0300 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-04-16 13:49:16 +0300 |
commit | af1b460033d874f1b1fd5ac248d49b0a6bb7363a (patch) | |
tree | 08cd843c3f9b035ca38190f8bd4829a095da40f8 | |
parent | 9c5200f0e19496e9f0e5248038222077c0763262 (diff) | |
download | apk-tools-af1b460033d874f1b1fd5ac248d49b0a6bb7363a.tar.gz apk-tools-af1b460033d874f1b1fd5ac248d49b0a6bb7363a.tar.bz2 apk-tools-af1b460033d874f1b1fd5ac248d49b0a6bb7363a.tar.xz apk-tools-af1b460033d874f1b1fd5ac248d49b0a6bb7363a.zip |
build: rewrite make system to something slightly similar to kbuild
Tracks now probler header file dependencies and command line parameters
used to build files. E.g. changing CFLAGS rebuild all C-files. And changing
version rebuild now the files where it's used.
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Make.rules | 269 | ||||
-rw-r--r-- | Makefile | 78 | ||||
-rw-r--r-- | src/Makefile | 57 |
4 files changed, 303 insertions, 103 deletions
@@ -1,2 +1,4 @@ apk *.o +*.d +*.cmd diff --git a/Make.rules b/Make.rules new file mode 100644 index 0000000..e633659 --- /dev/null +++ b/Make.rules @@ -0,0 +1,269 @@ +## +# A set of makefile rules loosely based on kbuild. + +all: compile + +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. + +GIT_REV := $(shell git describe || echo exported) +ifneq ($(GIT_REV), exported) +FULL_VERSION := $(patsubst $(PACKAGE)-%,%,$(GIT_REV)) +FULL_VERSION := $(patsubst v%,%,$(FULL_VERSION)) +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 +LD := $(CROSS_COMPILE)ld +INSTALL := install +INSTALLDIR := $(INSTALL) -d + +CFLAGS ?= -g +CFLAGS_ALL := -Werror -Wall -Wstrict-prototypes -D_GNU_SOURCE -std=gnu99 +CFLAGS_ALL += $(CFLAGS) + +LDFLAGS ?= -g +LDFLAGS_ALL += $(LDFLAGS) + +export CC LD INSTALL INSTALLDIR CFLAGS_ALL LDFLAGS_ALL + +build := + +endif + +## +# Reset all variables. +ifneq ($(origin targets),file) +targets := +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 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. +any-prereq = $(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) $(CFLAGS_ALL) $(CFLAGS_$(notdir $@)) +ld_flags = $(LDFLAGS_ALL) $(LDFLAGS_$(notdir $@)) + +##### +# 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 -n "\n$(obj)/" ; cat $(depfile)) \ + > $(dot-target).cmd ; \ + rm $(depfile) +endef + +$(obj)/%.o: $(src)/%.c FORCE + $(call if_changed_rule,cc_o_c) + +##### +# 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)))) + +quiet_cmd_ld = LD $@ + cmd_ld = $(CC) $(ld_flags) -o $@ \ + $(addprefix $(obj)/,$($(@F)-objs)) \ + $(LIBS) $(LIBS_$(@F)) + +$(__progs): $(obj)/%: $(cobjs) FORCE + $(call if_changed,ld) + +targets += $(__progs) $(cobjs) + +### +# 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)), \ + - due to missing .cmd file, \ + - due to $(notdir $@) not in $$(targets) \ + ) \ + ) \ + ) \ + ), \ + - 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 install:: $(targets) + +clean: $(filter %/,$(targets)) +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-))) + +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) @@ -1,74 +1,36 @@ -# Makefile - one file to rule them all, one file to bind them -# -# Copyright (C) 2007 Timo Teräs <timo.teras@iki.fi> -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 as published -# by the Free Software Foundation. See http://www.gnu.org/ for details. +## +# Building apk-tools PACKAGE := apk-tools VERSION := 2.0_pre10 -GIT_REV := $(shell git describe || echo exported) -ifneq ($(GIT_REV), exported) -ifneq ($(filter apk-tools-$(VERSION)%, $(GIT_REV)),) -FULL_VERSION := $(patsubst apk-tools-%,%,$(GIT_REV)) -else -FULL_VERSION := $(GIT_REV) -endif -else -FULL_VERSION := $(VERSION) -endif +## +# Default directories -CC=gcc -INSTALL=install -INSTALLDIR=$(INSTALL) -d +DESTDIR := +SBINDIR := /sbin +CONFDIR := /etc/apk +MANDIR := /usr/share/man +DOCDIR := /usr/share/doc/apk -CFLAGS?=-g -Werror -Wall -Wstrict-prototypes -CFLAGS+=-D_GNU_SOURCE -std=gnu99 -DAPK_VERSION=\"$(FULL_VERSION)\" +export DESTDIR SBINDIR CONFDIR MANDIR DOCDIR -LDFLAGS?=-g -LDFLAGS+=-nopie -LIBS=/usr/lib/libz.a +## +# Top-level rules and targets -ifeq ($(STATIC),yes) -CFLAGS+=-fno-stack-protector -LDFLAGS+=-static -endif +targets := src/ -DESTDIR= -SBINDIR=/sbin -CONFDIR=/etc/apk -MANDIR=/usr/share/man -DOCDIR=/usr/share/doc/apk +## +# Include all rules and stuff -SUBDIRS=src +include Make.rules -.PHONY: compile install clean all static - -all: compile - -static: - $(MAKE) $(MFLAGS) -C src apk.static - -compile install clean:: - @for i in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$i $(MAKECMDGOALS); done +## +# Top-level targets install:: $(INSTALLDIR) $(DESTDIR)$(DOCDIR) $(INSTALL) README $(DESTDIR)$(DOCDIR) -clean:: - rm -rf $(TARBALL) - -TARBALL := $(PACKAGE)-$(VERSION).tar.bz2 -dist: $(TARBALL) -$(TARBALL): - rm -rf $(PACKAGE) - git clone . $(PACKAGE) - cd $(PACKAGE) && (cd .. && git diff) | patch -p1 - tar -cjf $@ $(PACKAGE) - rm -rf $(PACKAGE) - -.EXPORT_ALL_VARIABLES: +static: + $(Q)$(MAKE) STATIC=y diff --git a/src/Makefile b/src/Makefile index d4a7244..993ca91 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,50 +1,17 @@ -# Makefile - one file to rule them all, one file to bind them -# -# Copyright (C) 2007 Timo Teräs <timo.teras@iki.fi> -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 as published -# by the Free Software Foundation. See http://www.gnu.org/ for details. +progs-y += apk +apk-objs := state.o database.o package.o archive.o \ + version.o io.o url.o gunzip.o blob.o \ + hash.o md5.o apk.o \ + add.o del.o ver.o index.o info.o search.o \ + fetch.o audit.o +CFLAGS_apk.o := -DAPK_VERSION=\"$(FULL_VERSION)\" -TARGETS = apk +progs-$(STATIC) += apk.static +apk.static-objs := $(apk-objs) +LDFLAGS_apk.static := -static -apk_OBJS = \ - state.o \ - database.o \ - package.o \ - archive.o \ - version.o \ - io.o \ - url.o \ - gunzip.o \ - blob.o \ - hash.o \ - md5.o \ - add.o \ - del.o \ - ver.o \ - index.o \ - info.o \ - search.o \ - fetch.o \ - audit.o \ - apk.o - -ALL_OBJS = $(apk_OBJS) - -all: $(TARGETS) - -apk: $(apk_OBJS) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) - -apk.static: $(apk_OBJS) - $(CC) $(LDFLAGS) -static -o $@ $^ $(LIBS) - -clean:: - @rm -f $(TARGETS) $(ALL_OBJS) +LIBS := /usr/lib/libz.a install:: $(INSTALLDIR) $(DESTDIR)$(SBINDIR) - $(INSTALL) $(TARGETS) $(DESTDIR)$(SBINDIR) - + $(INSTALL) $(obj)/apk $(DESTDIR)$(SBINDIR) |