Skip to content

Commit

Permalink
refactor(build): Portable bootstrap in makefiles
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Explorer09 committed May 13, 2024
1 parent 38e1085 commit 4732d94
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Makefile
/flex
/flex.exe
/libfl.la
/stage1bin/
/stage1flex
/stage1flex.exe
*.lo
Expand Down
4 changes: 4 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ AC_PATH_PROG([HELP2MAN], help2man, [\${top_srcdir}/build-aux/missing help2man])
AC_MSG_WARN(help2man: program not found: building man page will not work)
)

AM_CONDITIONAL([AUTO_BUILD_MAN_PAGE],
[test "$HELP2MAN" != "\${top_srcdir}/build-aux/missing help2man" &&
{ test "x$enable_bootstrap" = xyes || test "$cross_compiling" = no; }])

AC_PATH_PROGS([TEXI2DVI], [gtexi2dvi texi2dvi], [\${top_srcdir}/build-aux/missing texi2dvi])
AS_IF([test "$TEXI2DVI" = "\${top_srcdir}/build-aux/missing texi2dvi"],
AC_MSG_WARN(texi2dvi: program not found: building pdf version of manual will not work)
Expand Down
3 changes: 0 additions & 3 deletions doc/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,3 @@ flex.ps
version.texi
flex.html
flex.t2p

flex
flex.exe
44 changes: 36 additions & 8 deletions doc/local.mk
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
if CROSS
FLEX_FOR_DOC = stage1flex
FLEX_FOR_DOC = stage1bin/flex
else
FLEX_FOR_DOC = flex$(EXEEXT)
FLEX_FOR_DOC = flex
endif

TEXI2DVI = @TEXI2DVI@ -I $(srcdir)/examples/manual/
Expand Down Expand Up @@ -33,16 +33,44 @@ CLEANFILES += \
doc/flex

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

doc/flex.1: $(srcdir)/configure.ac $(srcdir)/src/cpp-flex.skl $(srcdir)/src/options.c $(srcdir)/src/options.h
$(MAKE) $(AM_MAKEFLAGS) $(FLEX_FOR_DOC)
$(INSTALL) -m 700 $(FLEX_FOR_DOC) doc/flex$(EXEEXT)
if AUTO_BUILD_MAN_PAGE
doc/flex.1: $(FLEX_FOR_DOC)$(BUILD_EXEEXT)
$(MKDIR_P) doc
$(HELP2MAN) \
--name='$(PACKAGE_NAME)' \
--section=1 \
--source='The Flex Project' \
--manual='Programming' \
--output=$@ \
doc/flex
./$(FLEX_FOR_DOC)
else
doc/flex.1: $(srcdir)/configure.ac $(srcdir)/src/cpp-flex.skl $(srcdir)/src/options.c $(srcdir)/src/options.h
@option_text=''; \
{ test '$(FLEX_FOR_DOC)' = flex || \
: $${option_text=" with --enable-bootstrap'"}; }; \
echo "error: flex man page outdated; please install help2man and rerun 'configure'$${option_text}" 1>&2;
@false
endif

distclean-local: distclean-local-doc

# Clean the man page in the build directory only if it is not the
# source directory.

distclean-local-doc:
test '$(srcdir)' = . || { \
if mv -f $(srcdir)/doc/flex.1 $(srcdir)/doc/flex.1.tmp; then \
s=0; else s=$$? || :; fi; \
rm -f doc/flex.1 || :; \
test "$$s" -ne 0 || \
mv -f $(srcdir)/doc/flex.1.tmp $(srcdir)/doc/flex.1; \
}

.PHONY: distclean-local-doc
75 changes: 61 additions & 14 deletions src/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,67 @@ nodist_stage1flex_SOURCES = \
$(SKELINCLUDES)

if CROSS
stage1flex_LDADD =

stage1flex_SOURCES += \
lib/malloc.c \
lib/realloc.c
stage1flex_LINK = $(LIBTOOL) --tag=CC --mode=link $(CC_FOR_BUILD) \
$(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@

$(stage1flex_OBJECTS): CC=$(CC_FOR_BUILD)
$(stage1flex_OBJECTS): CFLAGS=$(CFLAGS_FOR_BUILD) -DUSE_CONFIG_FOR_BUILD
$(stage1flex_OBJECTS): CPP=$(CPP_FOR_BUILD)
$(stage1flex_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
$(stage1flex_OBJECTS): LDFLAGS=$(LDFLAGS_FOR_BUILD)

stage1flex_CPPFLAGS = -DUSE_CONFIG_FOR_BUILD $(AM_CPPFLAGS)

# This also overrides AM_LIBTOOLFLAGS and AM_LDFLAGS
stage1flex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(LIBTOOLFLAGS) \
--mode=link $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) \
$(LDFLAGS_FOR_BUILD) -o $@

stage1flex_LDADD =

else

stage1flex_CPPFLAGS = $(AM_CPPFLAGS)

stage1flex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@

stage1flex_LDADD = $(LDADD)
stage1flex_LINK = $(LINK)
stage1flex_CFLAGS = $(AM_CFLAGS)

endif

# Suppress build warnings when compiling and linking stage1flex.
stage1flex_CFLAGS =

# Override the 'stage1flex$(EXEEXT)' target automake would generate.
# If the compiler is not $(CC_FOR_BUILD) when this target is invoked,
# delete the object files that would be linked to 'stage1flex' to force
# rebuild all of them.

stage1flex$(EXEEXT): $(stage1flex_OBJECTS) $(stage1flex_DEPENDENCIES) $(EXTRA_stage1flex_DEPENDENCIES)
@rm -f stage1flex$(EXEEXT)
@{ test 'x$(CC)' = 'x$(CC_FOR_BUILD)' && test 'x$(CPP)' = 'x$(CPP_FOR_BUILD)'; } || { \
rm -f src/stage1flex-*.$(OBJEXT); \
echo 'error: stage1flex must be built with a native compiler' 1>&2; \
false; \
}
$(AM_V_CCLD)$(stage1flex_LINK) $(stage1flex_OBJECTS) $(stage1flex_LDADD) $(LIBS)

# The 'stage1bin/flex$(BUILD_EXEEXT)' target is not managed by
# automake. We use a different file name from the automake-managed
# 'stage1flex$(EXEEXT)' target to avoid clashing.

stage1bin/flex$(BUILD_EXEEXT):
@if test 'x$(EXEEXT)' != 'x$(BUILD_EXEEXT)'; then rm -f stage1flex$(EXEEXT); else :; fi
@if test 'x$(OBJEXT)' != 'x$(BUILD_OBJEXT)'; then rm -f src/stage1flex-*.$(OBJEXT); else :; fi
$(MAKE) $(AM_MAKEFLAGS) \
CC='$(CC_FOR_BUILD)' \
CPP='$(CPP_FOR_BUILD)' \
CFLAGS='$(CFLAGS_FOR_BUILD)' \
CPPFLAGS='$(CPPFLAGS_FOR_BUILD)' \
LDFLAGS='$(LDFLAGS_FOR_BUILD)' \
EXEEXT='$(BUILD_EXEEXT)' \
OBJEXT='$(BUILD_OBJEXT)' \
stage1flex$(BUILD_EXEEXT)
$(MKDIR_P) stage1bin
$(INSTALL) -m 700 stage1flex$(BUILD_EXEEXT) $@

flex_SOURCES = \
$(COMMON_SOURCES)

Expand Down Expand Up @@ -108,11 +151,15 @@ EXTRA_DIST += \

MOSTLYCLEANFILES += \
$(SKELINCLUDES) \
src/stage1flex-*.$(BUILD_OBJEXT) \
src/stage1scan.c \
src/stage2scan.c \
src/stage2compare

CLEANFILES += stage1flex$(EXEEXT)
CLEANFILES += \
stage1bin/flex$(BUILD_EXEEXT) \
stage1flex$(BUILD_EXEEXT) \
stage1flex$(EXEEXT)

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

Expand Down

0 comments on commit 4732d94

Please sign in to comment.