Skip to content

Commit 1d32e61

Browse files
committed
refactor(build): Portable bootstrap in makefiles
Avoid "target-specific variable values" (that looks like "target: variable=value") that works with GNU make only when building 'stage1flex'. A portable alternative is starting a sub-instance of 'make' with overridden variables (CC="$CC_FOR_BUILD" etc.). Make the bootstrap work even when EXEEXT and BUILD_EXEEXT might differ. The makefiles are designed that only the main instance of 'make' would handle the 'stage1bin/flex$(BUILD_EXEEXT)' so that no data contention can potentially occur.
1 parent 3691fc6 commit 1d32e61

5 files changed

Lines changed: 112 additions & 32 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Makefile
3131
/flex
3232
/flex.exe
3333
/libfl.la
34+
/stage1bin/
3435
/stage1flex
3536
/stage1flex.exe
3637
*.lo

configure.ac

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ AC_PATH_PROG([HELP2MAN], help2man, [\${top_srcdir}/build-aux/missing help2man])
127127
AC_MSG_WARN(help2man: program not found: building man page will not work)
128128
)
129129

130+
AM_CONDITIONAL([AUTO_BUILD_MAN_PAGE],
131+
[test "$HELP2MAN" != "\${top_srcdir}/build-aux/missing help2man" &&
132+
{ test "x$enable_bootstrap" = xyes || test "$cross_compiling" = no; }])
133+
130134
AC_PATH_PROGS([TEXI2DVI], [gtexi2dvi texi2dvi], [\${top_srcdir}/build-aux/missing texi2dvi])
131135
AS_IF([test "$TEXI2DVI" = "\${top_srcdir}/build-aux/missing texi2dvi"],
132136
AC_MSG_WARN(texi2dvi: program not found: building pdf version of manual will not work)

doc/.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,3 @@ flex.ps
2525
version.texi
2626
flex.html
2727
flex.t2p
28-
29-
flex
30-
flex.exe

doc/local.mk

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
if CROSS
2-
FLEX_FOR_DOC = stage1flex
2+
FLEX_FOR_DOC = stage1bin/flex
33
else
4-
FLEX_FOR_DOC = flex$(EXEEXT)
4+
FLEX_FOR_DOC = flex
55
endif
66

77
TEXI2DVI = @TEXI2DVI@ -I $(srcdir)/examples/manual/
@@ -33,16 +33,44 @@ CLEANFILES += \
3333
doc/flex
3434

3535
# Use a fixed program name, without extension (such as ".exe"), for man
36-
# page generation. 'help2man' strips directory prefix ("./") from the
37-
# usage string, but not file extensions.
36+
# page generation. 'help2man' strips directory prefix from the usage
37+
# string, but not file extensions.
38+
#
39+
# Note: Do NOT run the '$(FLEX_FOR_DOC)$(BUILD_EXEEXT)' target in
40+
# another instance of 'make'! The scanner code also depends on the
41+
# target and two 'make' instances may contest building the same file.
3842

39-
doc/flex.1: $(srcdir)/configure.ac $(srcdir)/src/cpp-flex.skl $(srcdir)/src/options.c $(srcdir)/src/options.h
40-
$(MAKE) $(AM_MAKEFLAGS) $(FLEX_FOR_DOC)
41-
$(INSTALL) -m 700 $(FLEX_FOR_DOC) doc/flex$(EXEEXT)
43+
if AUTO_BUILD_MAN_PAGE
44+
doc/flex.1: $(FLEX_FOR_DOC)$(BUILD_EXEEXT)
45+
$(MKDIR_P) doc
4246
$(HELP2MAN) \
4347
--name='$(PACKAGE_NAME)' \
4448
--section=1 \
4549
--source='The Flex Project' \
4650
--manual='Programming' \
4751
--output=$@ \
48-
doc/flex
52+
./$(FLEX_FOR_DOC)
53+
else
54+
doc/flex.1: $(srcdir)/configure.ac $(srcdir)/src/cpp-flex.skl $(srcdir)/src/options.c $(srcdir)/src/options.h
55+
@option_text=''; \
56+
{ test '$(FLEX_FOR_DOC)' = flex || \
57+
: $${option_text=" with --enable-bootstrap'"}; }; \
58+
echo "error: flex man page outdated; please install help2man and rerun 'configure'$${option_text}" 1>&2;
59+
@false
60+
endif
61+
62+
distclean-local: distclean-local-doc
63+
64+
# Clean the man page in the build directory only if it is not the
65+
# source directory.
66+
67+
distclean-local-doc:
68+
test '$(srcdir)' = . || { \
69+
if mv -f $(srcdir)/doc/flex.1 $(srcdir)/doc/flex.1.tmp; then \
70+
s=0; else s=$$? || :; fi; \
71+
rm -f doc/flex.1 || :; \
72+
test "$$s" -ne 0 || \
73+
mv -f $(srcdir)/doc/flex.1.tmp $(srcdir)/doc/flex.1; \
74+
}
75+
76+
.PHONY: distclean-local-doc

src/local.mk

Lines changed: 71 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ pkgconfigdir = @pkgconfigdir@
77
m4 = @M4@
88

99
bin_PROGRAMS = flex
10+
11+
EXTRA_PROGRAMS = stage1flex
1012
if ENABLE_BOOTSTRAP
11-
noinst_PROGRAMS = stage1flex
1213
if !CROSS
1314
noinst_DATA = src/stage2compare
1415
endif
@@ -31,24 +32,70 @@ nodist_stage1flex_SOURCES = \
3132
$(SKELINCLUDES)
3233

3334
if CROSS
34-
stage1flex_LDADD =
35+
3536
stage1flex_SOURCES += \
3637
lib/malloc.c \
3738
lib/realloc.c
38-
stage1flex_LINK = $(LIBTOOL) --tag=CC --mode=link $(CC_FOR_BUILD) \
39-
$(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@
40-
41-
$(stage1flex_OBJECTS): CC=$(CC_FOR_BUILD)
42-
$(stage1flex_OBJECTS): CFLAGS=$(CFLAGS_FOR_BUILD) -DUSE_CONFIG_FOR_BUILD
43-
$(stage1flex_OBJECTS): CPP=$(CPP_FOR_BUILD)
44-
$(stage1flex_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
45-
$(stage1flex_OBJECTS): LDFLAGS=$(LDFLAGS_FOR_BUILD)
39+
40+
stage1flex_CPPFLAGS = -DUSE_CONFIG_FOR_BUILD $(AM_CPPFLAGS)
41+
42+
# This also overrides AM_LIBTOOLFLAGS and AM_LDFLAGS
43+
stage1flex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(LIBTOOLFLAGS) \
44+
--mode=link $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) \
45+
$(LDFLAGS_FOR_BUILD) -o $@
46+
47+
stage1flex_LDADD =
48+
4649
else
50+
51+
stage1flex_CPPFLAGS = $(AM_CPPFLAGS)
52+
53+
stage1flex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(LIBTOOLFLAGS) \
54+
--mode=link $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@
55+
4756
stage1flex_LDADD = $(LDADD)
48-
stage1flex_LINK = $(LINK)
49-
stage1flex_CFLAGS = $(AM_CFLAGS)
57+
5058
endif
5159

60+
# Suppress build warnings when compiling and linking stage1flex.
61+
stage1flex_CFLAGS =
62+
63+
# Override the 'stage1flex$(EXEEXT)' target automake would generate.
64+
# If the compiler is not $(CC_FOR_BUILD) when this target is invoked,
65+
# delete the object files that would be linked to 'stage1flex' to force
66+
# rebuild all of them.
67+
68+
stage1flex$(EXEEXT): $(stage1flex_OBJECTS) $(stage1flex_DEPENDENCIES) $(EXTRA_stage1flex_DEPENDENCIES)
69+
@rm -f stage1flex$(EXEEXT)
70+
{ test 'x$(CC)' = 'x$(CC_FOR_BUILD)' && \
71+
test 'x$(CPP)' = 'x$(CPP_FOR_BUILD)'; } || \
72+
{ rm -f src/stage1flex-*.$(OBJEXT) \
73+
src/$(DEPDIR)/stage1flex-*.Po || :; }
74+
@{ test 'x$(CC)' = 'x$(CC_FOR_BUILD)' && test 'x$(CPP)' = 'x$(CPP_FOR_BUILD)'; } || { \
75+
echo 'error: stage1flex must be built with a native compiler' 1>&2; \
76+
exit 1; \
77+
}
78+
$(AM_V_CCLD)$(stage1flex_LINK) $(stage1flex_OBJECTS) $(stage1flex_LDADD) $(LIBS)
79+
80+
# The 'stage1bin/flex$(BUILD_EXEEXT)' target is not managed by
81+
# automake. We use a different file name from the automake-managed
82+
# 'stage1flex$(EXEEXT)' target to avoid clashing.
83+
84+
stage1bin/flex$(BUILD_EXEEXT):
85+
@if test 'x$(EXEEXT)' != 'x$(BUILD_EXEEXT)'; then rm -f stage1flex$(EXEEXT); else :; fi
86+
@if test 'x$(OBJEXT)' != 'x$(BUILD_OBJEXT)'; then rm -f src/stage1flex-*.$(OBJEXT); else :; fi
87+
$(MAKE) $(AM_MAKEFLAGS) \
88+
CC='$(CC_FOR_BUILD)' \
89+
CPP='$(CPP_FOR_BUILD)' \
90+
CFLAGS='$(CFLAGS_FOR_BUILD)' \
91+
CPPFLAGS='$(CPPFLAGS_FOR_BUILD)' \
92+
LDFLAGS='$(LDFLAGS_FOR_BUILD)' \
93+
EXEEXT='$(BUILD_EXEEXT)' \
94+
OBJEXT='$(BUILD_OBJEXT)' \
95+
stage1flex$(BUILD_EXEEXT)
96+
$(MKDIR_P) stage1bin
97+
$(INSTALL) -m 700 stage1flex$(BUILD_EXEEXT) $@
98+
5299
flex_SOURCES = \
53100
$(COMMON_SOURCES)
54101

@@ -108,11 +155,15 @@ EXTRA_DIST += \
108155

109156
MOSTLYCLEANFILES += \
110157
$(SKELINCLUDES) \
158+
src/stage1flex-*.$(BUILD_OBJEXT) \
111159
src/stage1scan.c \
112160
src/stage2scan.c \
113161
src/stage2compare
114162

115-
CLEANFILES += stage1flex$(EXEEXT)
163+
CLEANFILES += \
164+
stage1bin/flex$(BUILD_EXEEXT) \
165+
stage1flex$(BUILD_EXEEXT) \
166+
stage1flex$(EXEEXT)
116167

117168
SKELINCLUDES = \
118169
src/cpp-flex.h \
@@ -137,21 +188,20 @@ src/go-flex.h: src/go-flex.skl src/mkskel.sh
137188
# The input and output file names are fixed for deterministic scanner
138189
# generation. If scan.l is not modified by builders, stage1scan.c should
139190
# be bit-identical to the scan.c pregenerated on release.
140-
src/stage1scan.c: src/scan.l stage1flex$(EXEEXT)
141-
( cd $(srcdir)/src && $(abs_builddir)/stage1flex$(EXEEXT) \
191+
src/stage1scan.c: src/scan.l stage1bin/flex$(BUILD_EXEEXT)
192+
( cd $(srcdir)/src && $(abs_builddir)/stage1bin/flex$(BUILD_EXEEXT) \
142193
$(AM_LFLAGS) $(LFLAGS) -o scan.c -t scan.l ) >$@ || \
143194
{ s=$$?; rm -f $@; exit $$s; }
144195

145196
# Unlike stage1scan.c, we leave stage2scan.c intact when the generation
146197
# fails. This allow users to examine generation errors.
147-
src/stage2scan.c: src/scan.l flex$(EXEEXT) src/stage1scan.c
198+
src/stage2scan.c: src/scan.l flex$(EXEEXT)
148199
( cd $(srcdir)/src && $(abs_builddir)/flex$(EXEEXT) \
149200
$(AM_LFLAGS) $(LFLAGS) -o scan.c -t scan.l ) >$@
150201

151-
src/stage2compare: src/stage1scan.c
152-
@rm -f src/stage2scan.c; \
153-
$(MAKE) $(AM_MAKEFLAGS) src/stage2scan.c; \
154-
echo Comparing stage1scan.c and stage2scan.c; \
202+
203+
src/stage2compare: src/stage1scan.c src/stage2scan.c
204+
@echo Comparing stage1scan.c and stage2scan.c; \
155205
cmp src/stage1scan.c src/stage2scan.c || { \
156206
s=$$?; \
157207
echo "Bootstrap comparison failure!"; \
@@ -211,4 +261,4 @@ indentfiles += \
211261
src/tables_shared.h \
212262
src/tblcmp.c
213263

214-
.PHONY: dist-hook-src
264+
.PHONY: dist-hook-src src/stage2scan.c

0 commit comments

Comments
 (0)