Skip to content

Commit 4732d94

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 38e1085 commit 4732d94

5 files changed

Lines changed: 102 additions & 25 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: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,67 @@ nodist_stage1flex_SOURCES = \
3131
$(SKELINCLUDES)
3232

3333
if CROSS
34-
stage1flex_LDADD =
34+
3535
stage1flex_SOURCES += \
3636
lib/malloc.c \
3737
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)
38+
39+
stage1flex_CPPFLAGS = -DUSE_CONFIG_FOR_BUILD $(AM_CPPFLAGS)
40+
41+
# This also overrides AM_LIBTOOLFLAGS and AM_LDFLAGS
42+
stage1flex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(LIBTOOLFLAGS) \
43+
--mode=link $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) \
44+
$(LDFLAGS_FOR_BUILD) -o $@
45+
46+
stage1flex_LDADD =
47+
4648
else
49+
50+
stage1flex_CPPFLAGS = $(AM_CPPFLAGS)
51+
52+
stage1flex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(LIBTOOLFLAGS) \
53+
--mode=link $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@
54+
4755
stage1flex_LDADD = $(LDADD)
48-
stage1flex_LINK = $(LINK)
49-
stage1flex_CFLAGS = $(AM_CFLAGS)
56+
5057
endif
5158

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

@@ -108,11 +151,15 @@ EXTRA_DIST += \
108151

109152
MOSTLYCLEANFILES += \
110153
$(SKELINCLUDES) \
154+
src/stage1flex-*.$(BUILD_OBJEXT) \
111155
src/stage1scan.c \
112156
src/stage2scan.c \
113157
src/stage2compare
114158

115-
CLEANFILES += stage1flex$(EXEEXT)
159+
CLEANFILES += \
160+
stage1bin/flex$(BUILD_EXEEXT) \
161+
stage1flex$(BUILD_EXEEXT) \
162+
stage1flex$(EXEEXT)
116163

117164
SKELINCLUDES = \
118165
src/cpp-flex.h \
@@ -137,8 +184,8 @@ src/go-flex.h: src/go-flex.skl src/mkskel.sh
137184
# The input and output file names are fixed for deterministic scanner
138185
# generation. If scan.l is not modified by builders, stage1scan.c should
139186
# 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) \
187+
src/stage1scan.c: src/scan.l stage1bin/flex$(BUILD_EXEEXT)
188+
( cd $(srcdir)/src && $(abs_builddir)/stage1bin/flex$(BUILD_EXEEXT) \
142189
$(AM_LFLAGS) $(LFLAGS) -o scan.c -t scan.l ) >$@ || \
143190
{ s=$$?; rm -f $@; exit $$s; }
144191

0 commit comments

Comments
 (0)