ifeq ("$(origin CC)", "default")
CC := cc
endif
+.ONESHELL:
+.SHELLFLAGS := -ec
+
+# Recipes which redirect stdout to the target of the rule (i.e., constructs
+# like cmd > $@) create empty or incomplete output files if the command fails,
+# for example when cmd was not found. Since the target exists and is uptodate
+# in this case, this may lead to all sorts of problems. The following target
+# makes sure that such files are removed.
+.DELETE_ON_ERROR:
PREFIX ?= /usr/local
M4 := m4
GROFF := groff
CP := cp
INSTALL := install
+GZIP := gzip -fn9
+ZCAT := zcat
-DATE := $(shell date '+%B %Y')
-GIT_VERSION := $(shell ./version-gen.sh)
+CC += -ffile-prefix-map=$(CURDIR)=.
+
+dummy != $(M4) /dev/null || printf 'failed'
+ifeq ($(dummy), failed)
+$(error m4 is required to build this package)
+endif
+dummy != printf '%%%%\n' | $(LEX) -o /dev/null || printf 'failed'
+ifeq ($(dummy), failed)
+$(error (f)lex is required to build this package)
+endif
-m4_man_pages := lopsub-suite.5 lopsub.7
-all := $(m4_man_pages) liblopsub.a lopsubgen lopsubgen.1 \
- lopsubex lopsubex.1
+DATE_FMT := +%B %Y
+# To get a reproducible build, we use $(SOURCE_DATE_EPOCH) instead of the
+# current time if this variable is set.
+ifdef SOURCE_DATE_EPOCH
+ DATE := $(shell LC_ALL=C date -u -d '@$(SOURCE_DATE_EPOCH)' \
+ '$(DATE_FMT)' 2>/dev/null || LC_ALL=C date -u '$(DATE_FMT)')
+else
+ DATE := $(shell date '$(DATE_FMT)')
+endif
+GIT_VERSION := $(shell ./version-gen.sh)
+PLAIN_VERSION := $(firstword $(subst -, , $(GIT_VERSION)))
+MAJOR_VERSION := $(firstword $(subst ., , $(PLAIN_VERSION)))
+SONAME := liblopsub.so.$(MAJOR_VERSION)
+REALNAME := liblopsub.so.$(PLAIN_VERSION)
+LINKERNAME:=liblopsub.so
+
+m4_man_pages := lopsub-suite.5.gz lopsub.7.gz
+all := $(m4_man_pages) $(REALNAME) lopsubgen lopsubgen.1.gz \
+ lopsubex lopsubex.1.gz
all: $(all)
# deps
gendoc := gendoc/gendoc.m4
%.h: %.h.m4 $(gendoc)
$(M4) -DOUTPUT_MODE=C $(gendoc) $< > $@
-$(m4_man_pages): %: %.m4 version.c
- $(M4) -DGIT_VERSION=$(GIT_VERSION) -DDATE="$(DATE)" $< > $@
+$(m4_man_pages): %.gz: %.m4 version.c
+ $(M4) -DGIT_VERSION=$(GIT_VERSION) -DDATE="$(DATE)" $< | $(GZIP) > $@
# flex
%.c: %.l
./lopsubgen --gen-c < $<
%.lsg.h: %.suite lopsubgen
./lopsubgen --gen-header < $<
-%.1: %.suite lopsubgen
- ./lopsubgen --gen-man=$@ --version-string $(GIT_VERSION) < $<
+%.1.gz: %.suite lopsubgen
+ ./lopsubgen --gen-man=${@:.gz=} --version-string $(GIT_VERSION) < $<
+ $(GZIP) ${@:.gz=}
# compiling
lsg1_objs := lopsubgen.o lsg1.o version.o
lsg_objs := lopsubgen.o lsg.o lopsubgen.lsg.o lopsub.o version.o
liblopsub_objs := config_file.o lopsub.o version.o
-lopsubex_objs := lopsubex.o lopsubex.lsg.o version.o
+lopsubex_objs := lopsubex.o lopsubex.lsg.o $(liblopsub_objs)
+
+LLS_CFLAGS := -g -fPIC
+STRICT_CFLAGS := -Wall
+STRICT_CFLAGS += -Werror-implicit-function-declaration
$(lsg_objs) $(liblopsub_objs) $(lopsubex_objs): %.o: %.c
lopsubgen.o config_file.o:
- $(CC) -g -c -o $@ ${@:.o=.c}
+ $(CC) $(CPPFLAGS) $(LLS_CFLAGS) $(CFLAGS) -c -o $@ ${@:.o=.c}
lsg1.o: lsg.c lsg.h
- $(CC) -g -DSTAGE1 -Wall -g -c $< -o $@
+ $(CC) $(CPPFLAGS) $(LLS_CFLAGS) $(STRICT_CFLAGS) $(CFLAGS) -DSTAGE1 -c -o $@ $<
%.o: %.c
- $(CC) -Wall -I. -g -c -o $@ $<
+ $(CC) -I. $(CPPFLAGS) $(LLS_CFLAGS) $(STRICT_CFLAGS) $(CFLAGS) -c -o $@ $<
# linking
lopsubgen-stage1: $(lsg1_objs)
$(CC) -Wall -g $(lsg1_objs) -o $@
lopsubgen: $(lsg_objs)
$(CC) -Wall -g -o $@ $(lsg_objs)
-liblopsub.a: $(liblopsub_objs)
- $(AR) -rcs $@ $^
-lopsubex: $(lopsubex_objs) liblopsub.a
- $(CC) -Wall -g -o $@ $^
+$(REALNAME): $(liblopsub_objs)
+ $(CC) --shared -Wl,-soname,liblopsub.so.$(MAJOR_VERSION) -o $@ $^
+lopsubex: $(lopsubex_objs) $(REALNAME)
+ $(CC) -Wall -g -o $@ $(lopsubex_objs)
# web
html := $(addprefix web/, $(addsuffix .html, \
- index lopsub-api lopsubgen.1 lopsubex.1 $(m4_man_pages)))
-$(html): $(addprefix web/, $(addsuffix .html, header footer))
-
+ index lopsub-api lopsubgen.1 lopsubex.1 $(m4_man_pages:.gz=)))
www: $(html)
-
-web/lopsub-api.html: lopsub.h.m4
+web/lopsub-api.html: lopsub.h.m4 web/header.html web/footer.html
$(M4) -DOUTPUT_MODE=HTML web/header.html $(gendoc) \
$< web/footer.html > $@
web/index.html: web/lopsub.7.html
$(LN) -s $(notdir $<) $@
-web/%.html: %
+web/%.html: %.gz web/header.html
$(CP) web/header.html $@
- $(GROFF) -m man -Thtml $< | sed -e '1,/^<body>/d' >> $@
-
-install: liblopsub.a lopsub.7
- $(INSTALL) -d $(PREFIX)/lib $(PREFIX)/include $(PREFIX)/man/man1 \
- $(PREFIX)/man/man5 $(PREFIX)/man/man7 $(PREFIX)/bin
- $(INSTALL) -m 755 liblopsub.a $(PREFIX)/lib
- $(INSTALL) -m 755 lopsubgen $(PREFIX)/bin
- $(INSTALL) -m 644 lopsub.h $(PREFIX)/include
- $(INSTALL) -m 644 lopsub-internal.h $(PREFIX)/include
- $(INSTALL) -m 644 lopsubgen.1 $(PREFIX)/man/man1
- $(INSTALL) -m 644 lopsub-suite.5 $(PREFIX)/man/man5
- $(INSTALL) -m 644 lopsub.7 $(PREFIX)/man/man7
+ $(ZCAT) $< | $(GROFF) -m man -Thtml | sed -e '1,/^<body>/d' >> $@
+
+install: $(all)
+ $(INSTALL) -d $(DESTDIR)$(PREFIX)/lib $(DESTDIR)$(PREFIX)/include \
+ $(DESTDIR)$(PREFIX)/share/man/man1 $(DESTDIR)$(PREFIX)/share/man/man5 \
+ $(DESTDIR)$(PREFIX)/share/man/man7 $(DESTDIR)$(PREFIX)/bin
+ $(INSTALL) -m 644 $(REALNAME) $(DESTDIR)$(PREFIX)/lib
+ $(LN) -s $(REALNAME) $(DESTDIR)$(PREFIX)/lib/$(SONAME)
+ $(LN) -s $(SONAME) $(DESTDIR)$(PREFIX)/lib/$(LINKERNAME)
+ $(INSTALL) -m 755 lopsubgen $(DESTDIR)$(PREFIX)/bin
+ $(INSTALL) -m 644 lopsub.h $(DESTDIR)$(PREFIX)/include
+ $(INSTALL) -m 644 lopsub-internal.h $(DESTDIR)$(PREFIX)/include
+ $(INSTALL) -m 644 lopsubgen.1.gz $(DESTDIR)$(PREFIX)/share/man/man1
+ $(INSTALL) -m 644 lopsub-suite.5.gz $(DESTDIR)$(PREFIX)/share/man/man5
+ $(INSTALL) -m 644 lopsub.7.gz $(DESTDIR)$(PREFIX)/share/man/man7
clean:
- $(RM) $(all) $(html) *.o *.man *.lsg.c *.lsg.h \
- lopsubgen.c config_file.c lopsubgen-stage1 \
+ $(RM) $(all) $(html) *.o *.man
+distclean: clean
+ $(RM) *.lsg.c *.lsg.h lopsubgen.c config_file.c lopsubgen-stage1 \
lopsub.h lopsub.7 lopsub-suite.5 version.c