From 527c18b061466a7d0ebde53e761d94775ebc8324 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Tue, 24 Mar 2009 12:18:16 +0000 Subject: Split common makefiles out of {hubbub,libcss,lpu,libdom,iconv} trees svn path=/trunk/tools/buildsystem/; revision=6831 --- makefiles/Makefile.top | 378 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 makefiles/Makefile.top (limited to 'makefiles/Makefile.top') 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 +# +# +# 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: +# +# :[';']* +# +# 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 + -- cgit v1.2.3