Skip to content
Snippets Groups Projects
rules.mk 8.9 KiB
Newer Older
Patrick Robbe's avatar
Patrick Robbe committed
BUILD_PREFIX ?=
LIBDIR_SUFFIX ?=64
FLEX ?=flex
LFLAGS ?=
CFLAGS +=-Wall -g -O3
CXXFLAGS +=-Wall -g -O3
DOCRA ?=docra
ASCIIDOCTOR ?=asciidoctor

define INST_template #file, dst, mode
INSTALL +=$(BUILD_PREFIX)$(2)/$(notdir $(1))
ifeq (,$(wildcard $(HERE)/$(1)))
# Installing using absolute path
$(BUILD_PREFIX)$(2)/$(notdir $(1)): $(1)
	@install -m 755 -d $(BUILD_PREFIX)$(2)
	install -m $(3) $$< $(BUILD_PREFIX)$(2)
else
# Installing using relative path
$(BUILD_PREFIX)$(2)/$(notdir $(1)): $(HERE)/$(1)
	@install -m 755 -d $(BUILD_PREFIX)$(2)
	install -m $(3) $$< $(BUILD_PREFIX)$(2)
endif
endef

%.out/_dir: $(HERE)/Makefile $(TOP)/rules.mk $(TOP)/flags.mk
	mkdir -p $*.out && touch $@

define ODIR_template #var, [nodefault]
ifneq ($(2),nodefault)
	DEFAULT +=$$($(1))
endif
$(1)_ODIR :=$$($(1)).out
$(1)_ODOT :=$$($(1)_ODIR)/_dir

-include $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS:.o=.d))

ODIRS +=$$($(1)_ODIR)

ifeq (,$(wildcard $(shell pwd)/Makefile))
# Out-of-tree build, external libraries are built locally
ifdef $(1)_LIBS_S
$$($(1)): $$(notdir $$($(1)_LIBS_S))
endif
else
# In-tree build, external libraries are in their source dir
$$($(1)): $$($(1)_LIBS_S)
endif

ifdef $(1)_DEPS
$$($(1)): $$($(1)_DEPS)
endif

######################
ifdef $(1)_CXXFLAGS
$(1)_CXXFLAGS +=-I$$($(1)_ODIR)

$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $(HERE)/%.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@

$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: %.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@

$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $$($(1)_ODIR)/%.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@

$$($(1)_ODIR)/%.o: %.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: %.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.o: $(HERE)/%.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: $(HERE)/%.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.o: $$($(1)_ODIR)/%.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: $$($(1)_ODIR)/%.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.o: %.c $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: %.c $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.o: $(HERE)/%.c $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: $(HERE)/%.c $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.l.cpp $$($(1)_ODIR)/%.l.hpp: $(HERE)/%.lpp $$($(1)_ODOT)
	$(FLEX) $(LFLAGS) --outfile=$$($(1)_ODIR)/$$*.l.cpp --header-file=$$($(1)_ODIR)/$$*.l.hpp $$<

$$($(1)_ODIR)/%.l.o: $$($(1)_ODIR)/%.l.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -Wno-sign-compare -c -o $$@ $$<

$$($(1)_ODIR)/%.l.pic.o: $$($(1)_ODIR)/%.l.cpp $$($(1)_ODOT)
	$$(CXX) $$($(1)_CXXFLAGS) -fPIC -Wno-sign-compare -c -o $$@ $$<

ifeq (,$(wildcard $(shell pwd)/Makefile))
# Out-of-tree build, external libraries are built locally
ifdef $(1)_LIBS_S
$$($(1)): $$(notdir $$($(1)_LIBS_S))
endif
else
# In-tree build, external libraries are in their source dir
$$($(1)): $$($(1)_LIBS_S)
endif

ifdef $(1)_DEPS
$$($(1)): $$($(1)_DEPS)
endif

ifdef $(1)_ARFLAGS
$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS))
	$(AR) $$($(1)_ARFLAGS) $$@ $$(filter %.o %.a,$$^)
else
$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS))
	$(CXX) $$($(1)_CXXFLAGS) $$(filter %.o %.a,$$^) -o $$@ $$($(1)_LDFLAGS)
endif

######################
else ifdef $(1)_CFLAGS
$(1)_CFLAGS +=-I$$($(1)_ODIR)

$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $(HERE)/%.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@

$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: %.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@

$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $$($(1)_ODIR)/%.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@

$$($(1)_ODIR)/%.o: %.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: %.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.o: $(HERE)/%.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: $(HERE)/%.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -c -o $$@ $$<

$$($(1)_ODIR)/%.pic.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -fPIC -c -o $$@ $$<

$$($(1)_ODIR)/%.l.c $$($(1)_ODIR)/%.l.h: $(HERE)/%.lpp $$($(1)_ODOT)
	$(FLEX) $(LFLAGS) --outfile=$$($(1)_ODIR)/$$*.l.c --header-file=$$($(1)_ODIR)/$$*.l.h $$<

$$($(1)_ODIR)/%.l.o: $$($(1)_ODIR)/%.l.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -fPIC -Wno-sign-compare -c -o $$@ $$<

$$($(1)_ODIR)/%.l.pic.o: $$($(1)_ODIR)/%.l.c $$($(1)_ODOT)
	$$(CC) $$($(1)_CFLAGS) -Wno-sign-compare -c -o $$@ $$<

ifdef $(1)_ARFLAGS
$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS))
	$(AR) $$($(1)_ARFLAGS) $$@ $$^
else
$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS))
	$(CC) $$($(1)_CFLAGS) $$^ -o $$@ $$($(1)_LDFLAGS)
endif

######################
else
#$$(error no compilation flags defined for target $(1))
endif

ifdef $(1)_INSTALL
ifdef $(1)_ARFLAGS
$$(eval $$(call INST_template,$($(1)),$($(1)_INSTALL),644))
else
$$(eval $$(call INST_template,$($(1)),$($(1)_INSTALL),755))
endif
endif
endef

define HDRS_template #var
	$(foreach hdr,$($(1)_HDRS),$(eval $(call INST_template,$(hdr),$($(1)_HDRS_INSTALL),644)))
endef

define COPY_template #var, chmod
	$(foreach hdr,$($(1)),$(eval $(call INST_template,$(hdr),$($(1)_INSTALL),$(2))))
endef

define LINK_template #var
INSTALL +=$(BUILD_PREFIX)$($(1)_INSTALL)/$($(1))
$(BUILD_PREFIX)$($(1)_INSTALL)/$($(1)): $(BUILD_PREFIX)$($(1)_LINK)
	@install -m 755 -d $(BUILD_PREFIX)$($(1)_INSTALL)
	ln -s $($(1)_LINK) $$@
endef

define DEP_template #file
DEP_DIRS +=$(dir $(1))

ifeq (,$(wildcard $(shell pwd)/Makefile))
# Out-of-tree build, all targets go to the local folder
DEFAULT +=$(notdir $(1))
$(notdir $(1)):
	$(MAKE) $(notdir $(1)) -f $(dir $(1))Makefile
.PHONY: $(notdir $(1))
else
# In-tree build, each target goes into its source folder
DEFAULT +=$(1)
$(1):
	$(MAKE) $(notdir $(1)) -C $(dir $(1))
.PHONY: $(1)
endif
endef

define MAN_template #var, mansection
$(1)_ODIR :=$$($(1)).out
$(1)_ODOT :=$$($(1)_ODIR)/_dir
$(1)_MAN.ADOC :=$$($(1)_ODIR)/$$(patsubst %.dcrt,%.adoc,$$(notdir $$($(1)_MAN_DCRT)))
$(1)_MAN :=$$($(1)_ODIR)/$$($(1)).$(2)
$(1)_MAN.GZ :=$$($(1)_ODIR)/$$($(1)).$(2).gz

MAN +=$$($(1)_MAN.GZ)

ifeq ($(ENABLE_DOCRA), true)
$$($(1)_MAN.ADOC): $$($(1)_ODOT)
	docra -l 0 -o $$($(1)_ODIR) $$($(1)_MAN_FLAGS) $$(dir $$($(1)_MAN_DCRT)) $$($(1)_MAN_DCRT)

$$($(1)_MAN): $$($(1)_MAN.ADOC)
	$(ASCIIDOCTOR) -b manpage $$<

$$($(1)_MAN.GZ): $$($(1)_MAN)
	gzip -f $$^

ifdef $(1)_MAN_INSTALL
MANINSTALL +=$(BUILD_PREFIX)$($(1)_MAN_INSTALL)/man$(2)/$$($(1)).$(2).gz
$(BUILD_PREFIX)$$($(1)_MAN_INSTALL)/man$(2)/$$($(1)).$(2).gz: $$($(1)_MAN.GZ)
	@install -m 755 -d $(BUILD_PREFIX)$$($(1)_MAN_INSTALL)/man$(2)
	@cp -v $$< $$@
endif

endif

.PHONY: $$($(1)_MAN.ADOC) $$($(1)_MAN) $$($(1)_MAN.GZ)
endef

define ALIAS_template #aliasvar, var, mansection

ifdef $(2)_INSTALL
INSTALL +=$(BUILD_PREFIX)$($(2)_INSTALL)/$($(1))
$(BUILD_PREFIX)$$($(2)_INSTALL)/$($(1)):
	@install -m 755 -d $(BUILD_PREFIX)$$($(2)_INSTALL)
	ln -s $$($(2)_INSTALL)/$$($(2)) $$@
endif

ifdef $(2)_MAN_INSTALL
MANINSTALL +=$(BUILD_PREFIX)$($(2)_MAN_INSTALL)/man$(3)/$($(1)).$(3).gz
$(BUILD_PREFIX)$$($(2)_MAN_INSTALL)/man$(3)/$$($(1)).$(3).gz:
	@install -m 755 -d $(BUILD_PREFIX)$$($(2)_MAN_INSTALL)/man$(3)
	ln -s $$($(2)_MAN_INSTALL)/man$(3)/$$($(2)).$(3).gz $$@
endif

endef

#dg`make.sub` Each subfolder containing a ``Makefile`` can be build individually by simply issuing ``make`` from there. Dependencies on targets built in other subfolders will be built automatically. This can be used during development to quickly iterate on a single subproject.
# By default, a sub-project ``Makefile`` implements at least the following targets: _
# *default*::
# Builds all library and executable targets.
# *install*::
# Copies installable files to their destination.
# *uninstall*::
# Removes files copied by both *install* and *maninstall*.
# *man*::
# Builds man pages.
# *maninstall*::
# Installs man pages under ``$(PREFIX)/share/man``.
# *clean*::
# Cleans build directory and deletes final targets.
# *depclean*::
# Makes the *clean* target in every dependency of this subproject.

define DEFAULT_template
default: $$(DEFAULT)

install: $$(INSTALL)

uninstall:
	$$(RM) $$(INSTALL) $$(MANINSTALL)

man: $$(MAN)

maninstall: $$(MANINSTALL)

clean:
	$(RM) -r *.out/ $(ODIRS)
	$(RM) $(DEFAULT)

depclean:
	for dep_dir in ${DEP_DIRS}; do $(MAKE) -C $$$${dep_dir} clean; done

.PHONY: install uninstall man maninstall clean depclean
endef

default:

.PHONY: default