summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile509
1 files 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 <david@hardeman.nu>
-#
-# 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