From 30a58fdd57504b6375ffac002b575c5fba17e4e1 Mon Sep 17 00:00:00 2001 From: Przemyslaw Pawelczyk Date: Tue, 2 Feb 2016 00:16:36 +0100 Subject: Rewrite Makefile using my Almost Universal Makefile template. --- Makefile | 509 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 433 insertions(+), 76 deletions(-) diff --git a/Makefile b/Makefile index b32ae44..33e9c3d 100644 --- a/Makefile +++ b/Makefile @@ -1,108 +1,465 @@ -# -# Copyright (C) 2007 David Härdeman -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; only version 2 of the License is applicable. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -# -# Generic settings -# -PROJ_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +## Almost Universal Makefile +## Author: Przemysław Pawełczyk + +BINS := \ + metastore + +LIBS := \ + +### Directories +PROJ_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +SRCS_DIR = $(PROJ_DIR)src/ +INCS_DIR = $(PROJ_DIR)include/ +CFGS_DIR = $(PROJ_DIR)etc/ +SHRS_DIR = $(PROJ_DIR)share/ +OBJS_DIR = $(PROJ_DIR)obj/ +BINS_DIR = $(PROJ_DIR)bin/ +LIBS_DIR = $(PROJ_DIR)lib/ +DOCS_DIR = $(PROJ_DIR) +MANS_DIR = $(PROJ_DIR) + +### METASTORE_VER := $(shell "$(PROJ_DIR)"/version.sh) UNAME_S := $(shell uname -s) -CC = gcc -CFLAGS += -g -Wall -pedantic -std=c99 -D_FILE_OFFSET_BITS=64 -O2 -CFLAGS += -DMETASTORE_VER="\"$(METASTORE_VER)\"" -LDFLAGS += +### + +DOCS := \ + AUTHORS \ + FILEFORMAT \ + LICENSE.GPLv2 \ + NEWS \ + README \ + metastore.txt \ + examples \ + +metastore_COMP := CC + +metastore_SRCS := \ + metaentry.c \ + metastore.c \ + utils.c \ + +metastore_DLIBS := \ + +metastore_MANS := \ + man1/metastore.1 \ ifeq ($(findstring BSD,$(UNAME_S)),) ifneq (DragonFly,$(UNAME_S)) ifneq (Darwin,$(UNAME_S)) -LIBS += -lbsd +metastore_DLIBS += -lbsd +endif +endif +endif + +PVER := $(PROJ_DIR)Makefile.ver + +SDEP := Makefile.dep + +-include $(PVER) + +# when building from project tree, then always use the same output layout +# otherwise use current working directory +ifneq (,$(findstring ^$(realpath $(PROJ_DIR)),^$(realpath ./))) + SDEP := $(PROJ_DIR)$(SDEP) +else + OBJS_DIR := ./obj/ + BINS_DIR := ./bin/ + LIBS_DIR := ./lib/ +endif + + +# library name prefix +LIB_PRE := lib +# Dynamic Shared Object extension +DSO_EXT := .so +# Statically-Linked Library extension +SLL_EXT := .a + + +### Default target +all: libs bins + +bins: $(BINS) +libs: $(LIBS) + +### Flags +MUSTHAVE_FLAGS := \ + -DMETASTORE_VER="\"$(METASTORE_VER)\"" \ + -D_FILE_OFFSET_BITS=64 \ + -Wall -Wextra -pedantic \ + -g \ + +MUSTHAVE_CFLAGS := -std=c99 +MUSTHAVE_CXXFLAGS := -std=c++11 +OPTIONAL_FLAGS := -O2 + +### Install paths +PREFIX := /usr/local +EXECPREFIX := $(PREFIX) +BINDIR := $(EXECPREFIX)/bin +LIBDIR := $(EXECPREFIX)/lib +INCLUDEDIR := $(PREFIX)/include +SYSCONFDIR := $(PREFIX)/etc +DATAROOTDIR := $(PREFIX)/share +DATADIR := $(DATAROOTDIR) +DOCDIR := ${DATAROOTDIR}/doc/metastore +MANDIR := ${DATAROOTDIR}/man + +### Phony targets +.PHONY: \ + all bins libs \ + strip strip-bins strips-libs \ + install install-bins install-libs install-includes \ + install-configs install-docs install-mans install-shares \ + uninstall uninstall-bins uninstall-libs uninstall-includes \ + clean distclean \ + dep \ + +### Install tools +INSTALL := install +INSTALL_EXEC := $(INSTALL) -m 0755 +COPY_NODEREF := cp -P + +### Build tools +DEFCC := gcc +DEFCXX := g++ +ifeq ($(origin CC),default) +CC := $(DEFCC) +endif +ifeq ($(origin CXX),default) +CXX := $(DEFCXX) +endif +ifneq ($(origin CC),environment) +CC := $(CROSS_COMPILE)$(CC) +endif +ifneq ($(origin CXX),environment) +CXX := $(CROSS_COMPILE)$(CXX) +endif +ifneq ($(origin CCLD),environment) +CCLD := $(CC) +endif +ifneq ($(origin CXXLD),environment) +CXXLD := $(CXX) +endif +ifneq ($(origin STRIP),environment) +STRIP := $(CROSS_COMPILE)strip +endif +CC_PARAMS = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) +CXX_PARAMS = $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) + +### Helpers +comma := , + +### Final flags +ifneq ($(origin CFLAGS),environment) +CFLAGS = $(OPTIONAL_FLAGS) +endif +ifneq ($(origin CXXFLAGS),environment) +CXXFLAGS = $(OPTIONAL_FLAGS) endif +override CFLAGS += $(MUSTHAVE_FLAGS) $(MUSTHAVE_CFLAGS) \ + $(if $(INCS_DIR),-I$(INCS_DIR),) -I$(SRCS_DIR) +override CXXFLAGS += $(MUSTHAVE_FLAGS) $(MUSTHAVE_CXXFLAGS) \ + $(if $(INCS_DIR),-I$(INCS_DIR),) -I$(SRCS_DIR) +override LDFLAGS := $(subst -Wl$(comma),,$(LDFLAGS)) +ifneq ($(origin CCLDFLAGS),environment) +CCLDFLAGS := $(addprefix -Wl$(comma),$(LDFLAGS)) endif +ifneq ($(origin CXXLDFLAGS),environment) +CXXLDFLAGS := $(addprefix -Wl$(comma),$(LDFLAGS)) endif -INCLUDES = -INSTALL = install -INSTALL_PROGRAM = ${INSTALL} -c -INSTALL_DATA = ${INSTALL} -c -m 644 -COMPILE = $(CC) $(INCLUDES) $(CFLAGS) $(CPPFLAGS) -LINK = $(CC) $(CFLAGS) $(LDFLAGS) -OBJECTS = utils.o metastore.o metaentry.o -HEADERS = utils.h metastore.h metaentry.h -DOCFILES = AUTHORS FILEFORMAT LICENSE.GPLv2 NEWS README metastore.txt -MANPAGES = man1/metastore.1 +vpath %.h $(SRCS_DIR) $(INCS_DIR) +vpath %.c $(SRCS_DIR) +vpath %.cpp $(SRCS_DIR) + +### Support for hiding command-line +V ?= 0 +HIDE_0 := @ +HIDE_1 := +HIDE := $(HIDE_$(V)) + + +### Rules for directories + +$(sort $(OBJS_DIR) $(BINS_DIR) $(LIBS_DIR)): + @mkdir -p $@ -SRCS_DIR := $(PROJ_DIR)src/ -MANS_DIR := $(PROJ_DIR) -DOCS_DIR := $(PROJ_DIR) +### Templated rules -DESTDIR ?= -PREFIX = /usr/local -EXECPREFIX = $(PREFIX) -DATAROOTDIR = ${PREFIX}/share -BINDIR = ${EXECPREFIX}/bin -DOCDIR = ${DATAROOTDIR}/doc/metastore -MANDIR = ${DATAROOTDIR}/man +define BIN_template -vpath %.c $(SRCS_DIR) -vpath %.h $(SRCS_DIR) -vpath %.1 $(MANS_DIR) -$(foreach file,$(DOCFILES),$(eval vpath $(file) $(DOCS_DIR))) +$(1)_OBJS := $$(addsuffix .o,$$(basename $$($(1)_SRCS))) -# -# Targets -# +$$(BINS_DIR)$(1): \ + $$(addsuffix $$(DSO_EXT),$$(addprefix $$(LIBS_DIR)$$(LIB_PRE),$$($(1)_DEPS))) \ + $$(addsuffix $$(SLL_EXT),$$(addprefix $$(LIBS_DIR)$$(LIB_PRE),$$($(1)_DEPS))) \ + $$(addprefix $$(OBJS_DIR),$$($(1)_OBJS)) $$(SDEP) | $$(BINS_DIR) +ifeq ($$($(1)_COMP),CC) + @echo " CCLD $$@" +else + @echo " CXXLD $$@" +endif + $$(HIDE)$$($$($(1)_COMP)LD) $$($$($(1)_COMP)LDFLAGS) $$(TARGET_ARCH) \ + -o $$@ $$(filter %.o,$$^) \ + -Wl,-Bstatic $$($(1)_SLIBS) -Wl,-Bdynamic $$($(1)_DLIBS) + +$(1): $$(BINS_DIR)$(1) +.PHONY: $(1) + +SRCS += $$($(1)_SRCS) +OBJS += $$($(1)_OBJS) -all: metastore -.DEFAULT: all +CFGS += $$($(1)_CFGS) +MANS += $$($(1)_MANS) +SHRS += $$($(1)_SHRS) +endef -%.o: %.c $(HEADERS) - $(COMPILE) -o $@ -c $< +define LIB_template +$(1)_OBJS := $$(addsuffix .o,$$(basename $$($(1)_SRCS))) -metastore: $(OBJECTS) - $(LINK) -o $@ $^ $(LIBS) +$(1)_SOLINK := $$(LIB_PRE)$(1)$$(DSO_EXT) +$(1)_SONAME := $$(LIB_PRE)$(1)$$(DSO_EXT).$$($(1)_MAJV) +$(1)_SOFILE := $$(LIB_PRE)$(1)$$(DSO_EXT).$$($(1)_MAJV)$$($(1)_MINV) +$(1)_ARFILE := $$(LIB_PRE)$(1)$$(SLL_EXT) +$$(LIBS_DIR)$$($(1)_SOLINK): $$(LIBS_DIR)$$($(1)_SONAME) + @echo " LN $$@ -> $$($(1)_SONAME)" + $$(HIDE)(cd "$(LIBS_DIR)" && ln -sf $$($(1)_SONAME) $$($(1)_SOLINK)) -metastore.txt: $(MANPAGES) - groff -mandoc -Kutf8 -Tutf8 $^ | col -bx >$@ +ifneq ($$($(1)_SONAME),$$($(1)_SOFILE)) +$$(LIBS_DIR)$$($(1)_SONAME): $$(LIBS_DIR)$$($(1)_SOFILE) + @echo " LN $$@ -> $$($(1)_SOFILE)" + $$(HIDE)(cd "$$(LIBS_DIR)" && ln -sf $$($(1)_SOFILE) $$($(1)_SONAME)) +endif + +$$(LIBS_DIR)$$($(1)_SOFILE): \ + $$(addsuffix $$(DSO_EXT),$$(addprefix $$(LIBS_DIR)$$(LIB_PRE),$$($(1)_DEPS))) \ + $$(addsuffix $$(SLL_EXT),$$(addprefix $$(LIBS_DIR)$$(LIB_PRE),$$($(1)_DEPS))) \ + $$(addprefix $$(OBJS_DIR),$$($(1)_OBJS)) $$(SDEP) | $$(LIBS_DIR) +ifeq ($$($(1)_COMP),CC) + @echo " CCLD $$@" +else + @echo " CXXLD $$@" +endif + $$(HIDE)$$($$($(1)_COMP)LD) $$($$($(1)_COMP)LDFLAGS) $$(TARGET_ARCH) \ + -shared -Wl,-soname,$$($(1)_SONAME) \ + -o $$@ $$(filter %.o,$$^) \ + -Wl,-Bstatic $$($(1)_SLIBS) -Wl,-Bdynamic $$($(1)_DLIBS) +$$(LIBS_DIR)$$($(1)_ARFILE): \ + $$(addprefix $$(OBJS_DIR),$$($(1)_OBJS)) $$(SDEP) | $$(LIBS_DIR) + @echo " AR $$@" + $$(HIDE)$$(AR) r $$@ $$(filter %.o,$$^) -install: all $(DOCFILES) $(MANPAGES) - $(INSTALL) -d $(DESTDIR)$(DOCDIR)/ - $(INSTALL_DATA) $(filter-out all %.1,$^) $(DESTDIR)$(DOCDIR) - cp -rf $(DOCS_DIR)examples $(DESTDIR)$(DOCDIR) - $(INSTALL) -d $(DESTDIR)$(MANDIR)/man1/ - $(INSTALL_DATA) $(filter %.1,$^) $(DESTDIR)$(MANDIR)/man1/ - $(INSTALL) -d $(DESTDIR)$(BINDIR)/ - $(INSTALL_PROGRAM) metastore $(DESTDIR)$(BINDIR)/ +$(1): \ + $$(LIBS_DIR)$$($(1)_SOFILE) \ + $$(LIBS_DIR)$$($(1)_SOLINK) \ + $$(LIBS_DIR)$$($(1)_ARFILE) +.PHONY: $(1) +SRCS += $$($(1)_SRCS) +OBJS += $$($(1)_OBJS) -uninstall: - - rm -f $(addprefix $(DESTDIR)$(DOCDIR)/,$(DOCFILES)) - - rm -rf $(DESTDIR)$(DOCDIR)/examples - - rmdir $(DESTDIR)$(DOCDIR) - - rm -f $(addprefix $(DESTDIR)$(MANDIR)/,$(MANPAGES)) - - rm -f $(DESTDIR)$(BINDIR)/metastore +INCS += $$($(1)_INCS) +CFGS += $$($(1)_CFGS) +MANS += $$($(1)_MANS) +SHRS += $$($(1)_SHRS) +LIBS_FILES += $$($(1)_SOFILE) $$($(1)_ARFILE) +LIBS_ALL_FILES += $$($(1)_SOLINK) $$($(1)_SONAME) $$($(1)_SOFILE) \ + $$($(1)_ARFILE) + +endef + +$(foreach BIN,$(BINS),$(eval $(call BIN_template,$(BIN)))) + +$(foreach LIB,$(LIBS),$(eval $(call LIB_template,$(LIB)))) + + +### Rules for normal targets + +$(OBJS_DIR)%.o: %.c + @echo " CC $@" + $(HIDE)mkdir -p $(dir $@) + $(HIDE)$(CC) $(CC_PARAMS) -c -o $@ $< + +$(OBJS_DIR)%.o: %.cpp + @echo " CXX $@" + $(HIDE)mkdir -p $(dir $@) + $(HIDE)$(CXX) $(CXX_PARAMS) -c -o $@ $< + +$(SDEP): SRCS_PATH := $(SRCS_DIR) +$(SDEP): SRCS_DIR := ./ +$(SDEP): PROJ_DIR := ../ +$(SDEP): $(SRCS) $(PROJ_DIR)Makefile + @echo " DEPS"; + $(HIDE)echo "# This file is automatically (re)generated by make." >$(SDEP) + $(HIDE)echo >>$(SDEP) + $(HIDE)(cd "$(SRCS_PATH)" && for FILE in $(SRCS); do \ + if [ "$${FILE##*.}" = "c" ]; then \ + $(CC) $(CFLAGS) -MT "\$$(OBJS_DIR)$${FILE%.*}.o" -MM "$$FILE"; \ + else \ + $(CXX) $(CXXFLAGS) -MT "\$$(OBJS_DIR)$${FILE%.*}.o" -MM "$$FILE"; \ + fi \ + done) >>$(SDEP) + +$(DOCS_DIR)%.txt: $(MANS_DIR)/man1/%.1 + @echo " GROFF $@" + $(HIDE)groff -mandoc -Kutf8 -Tutf8 $^ | col -bx >$@ + + +### Rules for phony targets clean: - - rm -f *.o metastore + @echo " CLEAN" + $(HIDE)$(RM) $(addprefix $(BINS_DIR),$(BINS)) \ + $(addprefix $(LIBS_DIR),$(LIBS_ALL_FILES)) \ + $(addprefix $(OBJS_DIR),$(OBJS)) \ + $(SDEP) + +distclean: clean + $(HIDE)(find \ + $(OBJS_DIR) \ + $(LIBS_DIR) \ + $(BINS_DIR) \ + -type d -exec rmdir --parents {} \; \ + 2>/dev/null ; exit 0) +dep: $(SDEP) -.PHONY: install uninstall clean all +strip: strip-bins strip-libs +strip-bins: $(addprefix $(BINS_DIR),$(BINS)) +ifneq ($(strip $(BINS)),) + @echo " STRIP $^" + $(HIDE)$(STRIP) $^ +endif + +strip-libs: $(addprefix $(LIBS_DIR),$(LIBS_FILES)) +ifneq ($(strip $(LIBS)),) + @echo " STRIP $^" + $(HIDE)$(STRIP) $^ +endif + +install: install-bins install-libs install-includes \ + install-configs install-docs install-mans install-shares \ + +install-bins: $(addprefix $(BINS_DIR),$(BINS)) +ifneq ($(strip $(BINS)),) + @echo " INSTALL $^" + $(HIDE)$(INSTALL) -d $(DESTDIR)$(BINDIR) + $(HIDE)$(INSTALL_EXEC) \ + $(addprefix $(BINS_DIR),$(BINS)) \ + $(DESTDIR)$(BINDIR)/ +endif + +install-libs: $(addprefix $(LIBS_DIR),$(LIBS_ALL_FILES)) +ifneq ($(strip $(LIBS)),) + @echo " INSTALL $^" + $(HIDE)$(INSTALL) -d $(DESTDIR)$(LIBDIR) + $(HIDE)$(COPY_NODEREF) \ + $(addprefix $(LIBS_DIR),$(LIBS_ALL_FILES)) \ + $(DESTDIR)$(LIBDIR)/ +endif + +install-includes: $(addprefix $(INCS_DIR),$(INCS)) +ifneq ($(strip $(INCS)),) + @echo " INSTALL $^" + $(HIDE)$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) + $(HIDE)( cd $(INCS_DIR) && $(COPY_NODEREF) --parents \ + $(INCS) \ + $(DESTDIR)$(INCLUDEDIR)/ \ + ) +endif + +install-configs: $(addprefix $(CFGS_DIR),$(CFGS)) +ifneq ($(strip $(CFGS)),) + @echo " INSTALL $^" + $(HIDE)$(INSTALL) -d $(DESTDIR)$(SYSCONFDIR) + $(HIDE)( cd $(CFGS_DIR) && $(COPY_NODEREF) --parents \ + $(CFGS) \ + $(DESTDIR)$(SYSCONFDIR)/ \ + ) +endif + +install-docs: $(addprefix $(DOCS_DIR),$(DOCS)) +ifneq ($(strip $(DOCS)),) + @echo " INSTALL $^" + $(HIDE)$(INSTALL) -d $(DESTDIR)$(DOCDIR) + $(HIDE)( cd $(DOCS_DIR) && $(COPY_NODEREF) --parents -r \ + $(DOCS) \ + $(DESTDIR)$(DOCDIR)/ \ + ) +endif + +install-mans: $(addprefix $(MANS_DIR),$(MANS)) +ifneq ($(strip $(MANS)),) + @echo " INSTALL $^" + $(HIDE)$(INSTALL) -d $(DESTDIR)$(MANDIR) + $(HIDE)( cd $(MANS_DIR) && $(COPY_NODEREF) --parents \ + $(MANS) \ + $(DESTDIR)$(MANDIR)/ \ + ) +endif + +install-shares: $(addprefix $(SHRS_DIR),$(SHRS)) +ifneq ($(strip $(SHRS)),) + @echo " INSTALL $^" + $(HIDE)$(INSTALL) -d $(DESTDIR)$(DATADIR) + $(HIDE)( cd $(SHRS_DIR) && $(COPY_NODEREF) --parents \ + $(SHRS) \ + $(DESTDIR)$(DATADIR)/ \ + ) +endif + +uninstall: uninstall-bins uninstall-libs uninstall-includes \ + uninstall-docs uninstall-mans uninstall-shares \ + +uninstall-bins: +ifneq ($(strip $(BINS)),) + @echo " UNINST $(addprefix $(DESTDIR)$(BINDIR)/,$(BINS))" + $(HIDE)$(RM) $(addprefix $(DESTDIR)$(BINDIR)/,$(BINS)) +endif + +uninstall-libs: +ifneq ($(strip $(LIBS)),) + @echo " UNINST $(addprefix $(DESTDIR)$(LIBDIR)/,$(LIBS_ALL_FILES))" + $(HIDE)$(RM) $(addprefix $(DESTDIR)$(LIBDIR)/,$(LIBS_ALL_FILES)) +endif + +uninstall-includes: +ifneq ($(strip $(INCS)),) + @echo " UNINST $(addprefix $(DESTDIR)$(INCLUDEDIR)/,$(INCS))" + $(HIDE)$(RM) $(addprefix $(DESTDIR)$(INCLUDEDIR)/,$(INCS)) +endif + +uninstall-docs: +ifneq ($(strip $(DOCS)),) + @echo " UNINST $(addprefix $(DESTDIR)$(DOCDIR)/,$(DOCS))" + $(HIDE)$(RM) -r $(addprefix $(DESTDIR)$(DOCDIR)/,$(DOCS)) +endif + +uninstall-mans: +ifneq ($(strip $(MANS)),) + @echo " UNINST $(addprefix $(DESTDIR)$(MANDIR)/,$(MANS))" + $(HIDE)$(RM) $(addprefix $(DESTDIR)$(MANDIR)/,$(MANS)) +endif + +uninstall-shares: +ifneq ($(strip $(SHRS)),) + @echo " UNINST $(addprefix $(DESTDIR)$(DATADIR)/,$(SHRS))" + $(HIDE)$(RM) $(addprefix $(DESTDIR)$(DATADIR)/,$(SHRS)) +endif + + +### Dependencies +ifneq ($(MAKECMDGOALS),distclean) +ifneq ($(MAKECMDGOALS),clean) +-include $(SDEP) +endif +endif -- cgit v1.2.1