diff options
author | John Mark Bell <jmb@netsurf-browser.org> | 2009-03-24 12:18:16 +0000 |
---|---|---|
committer | John Mark Bell <jmb@netsurf-browser.org> | 2009-03-24 12:18:16 +0000 |
commit | 527c18b061466a7d0ebde53e761d94775ebc8324 (patch) | |
tree | ccb277c2caa98ac0e8235823609fe0ed26a1d229 /makefiles | |
download | buildsystem-527c18b061466a7d0ebde53e761d94775ebc8324.tar.gz buildsystem-527c18b061466a7d0ebde53e761d94775ebc8324.tar.bz2 |
Split common makefiles out of {hubbub,libcss,lpu,libdom,iconv} trees
svn path=/trunk/tools/buildsystem/; revision=6831
Diffstat (limited to 'makefiles')
-rw-r--r-- | makefiles/Makefile.subdir | 94 | ||||
-rw-r--r-- | makefiles/Makefile.top | 378 |
2 files changed, 472 insertions, 0 deletions
diff --git a/makefiles/Makefile.subdir b/makefiles/Makefile.subdir new file mode 100644 index 0000000..7f8d27e --- /dev/null +++ b/makefiles/Makefile.subdir @@ -0,0 +1,94 @@ +# Child makefile fragment +# +# Inputs (reset on exit) +# +# DIR_SOURCES List of source files in this directory +# DIR_TEST_SOURCES List of test source files in this directory +# DIR_INSTALL_ITEMS Items to install in form <destination>:<file1>;<file2> +# +# Toolchain is provided by top-level makefile +# +# Variables provided by top-level makefile +# +# BUILDDIR The location of the build tree root +# COMPONENT The name of the component +# CURDIR The location of the source tree root +# EXPORTDIR The location of the export directory +# +# do_include Canned command sequence to include a child makefile +# +# Variables provided by parent makefile: +# +# DIR The name of the directory we're in, relative to CURDIR +# +# Variables we can manipulate: +# +# CLEAN_ITEMS The list of items to remove for "make clean" +# DISTCLEAN_ITEMS The list of items to remove for "make distclean" +# TEST_SOURCES The list of sources to build for "make test" +# TEST_TARGETS The list of target names to run for "make test" +# INSTALL_ITEMS The list of items to (un)install +# +# SOURCES The list of sources to build for $(COMPONENT) +# +# Plus anything from the toolchain + +# Push parent directory onto the directory stack +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(DIR) + +# Manipulate include paths +CFLAGS := $(CFLAGS) -I$(d) + +# Sources +SRCS_$(d) := $(DIR_SOURCES) +TEST_SRCS_$(d) := $(DIR_TEST_SOURCES) +INSTALL_ITEMS_$(d) := $(DIR_INSTALL_ITEMS) + +# Append to sources for component +SOURCES := $(SOURCES) $(addprefix $(d), $(SRCS_$(d))) + +# Test sources +ifeq ($(MAKECMDGOALS),test) + ifneq ($(DIR_TEST_SOURCES),) + TEST_SOURCES := $(TEST_SOURCES) $(addprefix $(d), $(TEST_SRCS_$(d))) + + TEST_TARGETS := $(TEST_TARGETS) test_$(d) + + # Target for tests in this directory + test_$(d): $(d) $(addprefix $(BUILDDIR)/, \ + $(subst /,_,$(addprefix $(d), \ + $(basename $(TEST_SRCS_$(d)))))) + $(Q)$(TESTRUNNER) $(BUILDDIR) $(CURDIR)/$< $(EXEEXT) + endif +endif + +# Install items +ifneq ($(DIR_INSTALL_ITEMS),) + # Extract the destination directory from the variable + dest_dir_$(d) = $(firstword $(subst :, ,$(INSTALL_ITEMS_$(d)))) + # Extract the list of files to install + file_list_$(d) = $(lastword $(subst :, ,$(INSTALL_ITEMS_$(d)))) + # Split file list into words + files_$(d) = $(subst ;, ,$(file_list_$(d))) + + # Append items to install (along with install location), prepending $(d) + # to each item in the file list + INSTALL_ITEMS := $(INSTALL_ITEMS) $(dest_dir_$(d)):$(foreach FILE, \ + $(files_$(d)),$(addprefix $(d),$(FILE))); +endif + +# Reset the inputs +DIR_SOURCES := +DIR_TEST_SOURCES := +DIR_INSTALL_ITEMS := + +# Now include any children we may have +MAKE_INCLUDES := $(wildcard $(d)*/Makefile) +$(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) + +# Pop off the directory stack +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) + diff --git a/makefiles/Makefile.top b/makefiles/Makefile.top new file mode 100644 index 0000000..aa8bf6f --- /dev/null +++ b/makefiles/Makefile.top @@ -0,0 +1,378 @@ +# Top-level Makefile fragment +# +# Expected inputs: +# +# BUILD Type of build to perform: +# release - Release build +# debug - Debug build (default) +# COMPONENT Name of the component (sans leading "lib" iff a library) +# COMPONENT_TYPE Type of component: +# binary - Executable binary +# lib-static - Static library +# lib-shared - Shared library +# TARGET Target platform identifier +# +# Optional inputs: +# +# BUILDDIR Directory to build into +# (defaults to build-$(HOST)-$(TARGET)-$(BUILD)) +# CC_CAN_BUILD_AND_DEP Flag whether $(CC) is capable of calculating dependency +# information at the same time as compiling sources. +# Set to "yes" if it can. +# DESTDIR Sandboxed FS root (e.g. for packaging) +# HOST Host platform identifier +# PREFIX Absolute installation path prefix +# (defaults to /usr/local) +# +# The client may also override all toolchain settings, including: +# +# ARFLAGS Archiver flags for the current compilation +# CFLAGS C compiler flags for the current compilation +# LDFLAGS Linker flags for the current compilation +# +# TESTCFLAGS Any test-specific CFLAGS +# TESTLDFLAGS Any test-specific LDFLAGS +# +# TESTRUNNER Test runner invocation command +# The test runner takes a command line in the form +# <build dir> <test dir> <exeext> +# +# Targets provided: +# +# all Default target. Builds component using current settings +# test Build and run test suite, using current settings. +# coverage Determine test suite coverage (requires lcov) +# profile Build with profiling support enabled (requires gprof) +# docs Produce documentation (requires doxygen) +# clean Clean the build +# distclean Remove distribution files, too +# install Install component into prefix. +# uninstall Remove component from prefix. + +############################################################################### +# Sanity checks +############################################################################### + +# Name of component must be defined by client +ifeq ($(COMPONENT),) + $(error COMPONENT not defined) +endif + +# As must the component type +ifeq ($(COMPONENT_TYPE),) + $(error COMPONENT_TYPE not defined) +endif + +# Target platform must be defined by the client +ifeq ($(TARGET),) + $(error TARGET not defined) +endif + +# Default build type +ifeq ($(BUILD),) + BUILD := debug +endif + +############################################################################## +# Tool defaults +############################################################################## + +ifeq ($(BUILD),release) + CFLAGS ?= -O2 +else + CFLAGS ?= -g -O0 + LDFLAGS ?= -g +endif + +ECHO ?= echo + +GENHTML ?= genhtml + +INSTALL ?= install + +LCOV ?= lcov + +MKDIR ?= mkdir +MKDIRFLAGS ?= -p + +PKGCONFIG ?= pkg-config + +SED ?= sed + +TOUCH ?= touch + +############################################################################## +# Makefile variables +############################################################################## + +Q ?= @ +VQ ?= @ + +############################################################################## +# Build environment +############################################################################## + +# Build directory +BUILDDIR ?= build-$(HOST)-$(TARGET)-$(BUILD) + +# Build tree subdirs +COVERAGEDIR := $(BUILDDIR)/coverage +DOCDIR := $(BUILDDIR)/docs + +# Default prefix +PREFIX ?= /usr/local + +# List of items to delete on clean +CLEAN_ITEMS := +# List of items to delete on distclean +DISTCLEAN_ITEMS := + +# List of sources to build for testing +TEST_SOURCES := +# List of targets to run for testing +TEST_TARGETS := + +# List of items to (un)install +INSTALL_ITEMS := + +# Source files +SOURCES := + +# Include configuration Makefile fragment +-include Makefile.config + +# Include Makefile fragments in subdirectories + +define do_include +DIR := $$(dir $(1)) +include $(1) + +endef + +MAKE_INCLUDES := $(wildcard */Makefile) +$(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) + +# Calculate objects to build +OBJECTS := $(addprefix $(BUILDDIR)/,$(subst /,_,$(subst .c,.o,$(SOURCES)))) + +TEST_OBJECTS := $(addprefix $(BUILDDIR)/,$(subst /,_, \ + $(subst .c,.o,$(TEST_SOURCES)))) +TEST_BINARIES := $(addprefix $(BUILDDIR)/,$(subst /,_, \ + $(basename $(TEST_SOURCES)))) + +# And the output filename +ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) + OUTPUT := $(BUILDDIR)/lib$(COMPONENT)$(LIBEXT) +else + OUTPUT := $(BUILDDIR)/$(COMPONENT)$(EXEEXT) +endif + +############################################################################### +# Build targets +############################################################################### + +.PHONY: all test coverage profile docs clean distclean install uninstall + +# Default target +all: $(OUTPUT) + +# Build and execute testsuite +test: $(OUTPUT) $(TEST_BINARIES) $(TEST_TARGETS) + $(VQ)$(ECHO) $(ECHOFLAGS) " TEST: Testing complete" + +# Compute coverage +coverage: clean + $(Q)$(LCOV) --directory . --zerocounters + $(Q)$(MAKE) test CFLAGS="$(CFLAGS) -fprofile-arcs -ftest-coverage" \ + LDFLAGS="$(LDFLAGS) -lgcov" + $(Q)$(LCOV) --directory $(BUILDDIR) --base-directory $(CURDIR) \ + --capture --output-file $(COVERAGEDIR)/$(COMPONENT)_tmp.info + $(Q)$(LCOV) --extract $(COVERAGEDIR)/$(COMPONENT)_tmp.info \ + "$(CURDIR)/src*" -o $(COVERAGEDIR)/$(COMPONENT).info + $(Q)$(RM) $(RMFLAGS) $(COVERAGEDIR)/$(COMPONENT)_tmp.info + $(Q)$(GENHTML) -o $(COVERAGEDIR) --num-spaces 2 \ + $(COVERAGEDIR)/$(COMPONENT).info + +# Build for profiling +profile: clean + $(Q)$(MAKE) test CFLAGS="$(CFLAGS) -pg" LDFLAGS="-pg $(LDFLAGS)" + +# Compile documentation +docs: $(BUILDDIR)/stamp + $(Q)$(DOXYGEN) build/Doxyfile + +# Clean build tree +clean: + -$(Q)$(RM) $(RMFLAGS) $(CLEAN_ITEMS) + -$(Q)$(RM) $(RMFLAGS) gmon.out + -$(Q)$(RM) $(RMFLAGS) -r $(BUILDDIR) + +# Remove auto-generated non-build-tree items +distclean: clean + -$(Q)$(RM) $(RMFLAGS) $(DISTCLEAN_ITEMS) + +# The installation target, and associated canned command sequences. +# For reference, the syntax of INSTALL_ITEMS is: +# +# <destination>:<file>[';'<file>]* +# +# We also permit a trailing ';' in the file list. + +# Install a pkg-config control file ($1) to the specified location ($2) +define install_pkgconfig + $(Q)$(SED) -e 's#PREFIX#$(PREFIX)#' $1 >$(BUILDDIR)/$(1:.in=) + $(INSTALL) $(INSTALLFLAGS) -m 644 $(BUILDDIR)/$(1:.in=) $2 + +endef + +# Install a file ($1) to the specified location ($2) +define install_file + $(if $1, \ + $(if $(findstring .pc.in,$1), \ + $(call install_pkgconfig,$1,$2), \ + $(INSTALL) $(INSTALLFLAGS) -m 644 $1 $2)) + +endef + +# Install a list of files ($2) to the specified location ($1) +# We create the installation location if it doesn't already exist +define install_to_dest + $(Q)$(MKDIR) $(MKDIRFLAGS) $(DESTDIR)$(PREFIX)$1 + $(foreach FILE,$(strip $(subst ;, ,$2)), \ + $(call install_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) + +endef + +install: $(OUTPUT) + $(foreach ITEM,$(INSTALL_ITEMS), \ + $(call install_to_dest,$(firstword $(subst :, ,$(ITEM))), \ + $(lastword $(subst :, ,$(ITEM))))) + +# Uninstallation + +# Uninstall a file ($1) from the specified location ($2) +define uninstall_file + $(if $1, \ + $(if $(findstring .pc.in,$1), \ + $(RM) $(RMFLAGS) $2/$(notdir $(1:.in=)), \ + $(RM) $(RMFLAGS) $2/$(notdir $1))) + +endef + +# Uninstall a list of files ($2) from the specified location ($1) +# TODO: Come up with a safe way of removing directories, too +define uninstall_from_dest + $(foreach FILE,$(strip $(subst ;, ,$2)), \ + $(call uninstall_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) + +endef + +uninstall: + $(foreach ITEM,$(INSTALL_ITEMS), \ + $(call uninstall_from_dest,$(firstword $(subst :, ,$(ITEM))), \ + $(lastword $(subst :, ,$(ITEM))))) + +############################################################################### +# Actual rules +############################################################################### + +$(BUILDDIR)/stamp: + $(Q)$(MKDIR) $(MKDIRFLAGS) $(BUILDDIR) + $(Q)$(MKDIR) $(MKDIRFLAGS) $(COVERAGEDIR) + $(Q)$(MKDIR) $(MKDIRFLAGS) $(DOCDIR) + $(Q)$(TOUCH) $(BUILDDIR)/stamp + +$(OUTPUT): $(BUILDDIR)/stamp $(OBJECTS) +ifeq ($(COMPONENT_TYPE),lib-static) + $(VQ)$(ECHO) $(ECHOFLAGS) " AR: $@" + $(Q)$(AR) $(ARFLAGS) $@ $(OBJECTS) +else + $(VQ)$(ECHO) $(ECHOFLAGS) " LINK: $@" + $(Q)$(LD) -o $@ $(OBJECTS) $(LDFLAGS) +endif + +############################################################################### +# Autogenerated, implied rules +############################################################################### + +DEPFILES := + +ifeq ($(CC_CAN_BUILD_AND_DEP),yes) + # C compiler can compile and dep simultaneously + + define dep_c + $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 + + DEPFILES += $$(BUILDDIR)/$2 + + endef + + define build_c + $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 + $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" + $$(Q)$$(CC) -MMD -MP $($3) -o $$@ -c $1 + + endef +else + # C compiler must calculate dependencies first, then compile (default) + + define dep_c + $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 + $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" + $$(Q)$$(RM)$($@) + $$(Q)$$(CC) $($3) -MM $1 > $$@ + $$(Q)$$(SED) $$(SEDFLAGS) -i 's,^.*:,$$@ $$(@:.d=.o):,' $$@ + + DEPFILES += $$(BUILDDIR)/$2 + + endef + + define build_c + $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 + $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" + $$(Q)$$(CC) $($3) -o $$@ -c $1 + + endef +endif + +# Generate dependency rules +$(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ + $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),CFLAGS))) + +# Generate compilation rules +$(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ + $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),CFLAGS))) + +# Similarly for test sources +ifeq ($(MAKECMDGOALS),test) + TESTCFLAGS := $(TESTCFLAGS) $(CFLAGS) + TESTLDFLAGS := $(TESTLDFLAGS) $(LDFLAGS) + + ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) + TESTLIB := $(OUTPUT) + TESTLDFLAGS := $(TESTLDFLAGS) -L$(BUILDDIR)/ -l$(COMPONENT) + endif + + define link_test + $2: $($3) $1 + $$(VQ)$$(ECHO) $$(ECHOFLAGS) " LINK: $2" + $$(Q)$$(CC) -o $$@ $1 $($4) + + endef + +$(eval $(foreach SOURCE,$(filter %.c,$(TEST_SOURCES)), \ + $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),TESTCFLAGS))) + +$(eval $(foreach SOURCE,$(filter %.c,$(TEST_SOURCES)), \ + $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),TESTCFLAGS))) + +$(eval $(foreach BINARY,$(TEST_BINARIES), \ + $(call link_test, \ + $(addsuffix .o,$(BINARY)),$(BINARY),TESTLIB,TESTLDFLAGS))) +endif + +# Include dependency makefiles +ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) +-include $(sort $(DEPFILES)) +endif + |