Merge branch 't/build-improvements' master pu
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 9 May 2021 14:47:26 +0000 (16:47 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 9 May 2021 14:47:26 +0000 (16:47 +0200)
The build system fails in unexpected ways when required programs like
m4 or flex are not installed. One particular problem is a construct
of the form

    $(M4) ... > $@

in the recipe of the lopsub.h target. If m4 is not installed, this
results in an empty lopsub.h file, which is considered up-to-date
by subsequent runs of make(1). The subsequent compilation of lsg.c
succeeds despite of the empty lopsub.h, but the resulting executable
segfaults.

The reason is that lsg1.c includes lopsub.h to declare lls_version(),
but due to lopsub.h being empty, the declaration is missing and the
compiler implicitly assumes an int return value rather than char *.

This patch series addresses this problem in several ways. With the
series applied:

* the build fails early if m4 or flex are not installed,
* missing function declarations are considered errors rather than warnings,
* incompletely written targets are removed by make(1).

Makefile

index 230a966..548c96f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,13 @@ 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
 LN := ln -f
@@ -21,6 +28,15 @@ INSTALL := install
 GZIP := gzip -fn9
 ZCAT := zcat
 
+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
+
 DATE_FMT := +%B %Y
 # To get a reproducible build, we use $(SOURCE_DATE_EPOCH) instead of the
 # current time if this variable is set.
@@ -79,13 +95,17 @@ 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 $(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 -fPIC -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 -fPIC -o $@ $<
+       $(CC) -I. $(CPPFLAGS) $(LLS_CFLAGS) $(STRICT_CFLAGS) $(CFLAGS) -c -o $@ $<
 
 # linking
 lopsubgen-stage1: $(lsg1_objs)