summaryrefslogtreecommitdiff
path: root/rules
diff options
context:
space:
mode:
authorThomas Miedema <thomasmiedema@gmail.com>2015-06-05 22:12:34 +0200
committerThomas Miedema <thomasmiedema@gmail.com>2015-06-06 15:15:53 +0200
commit328c212b1db4d439fc693216495515bce162ef6e (patch)
tree265a617f06bd726cf8ded4729935a895a446e485 /rules
parentae83a81ad6b6185f5b754c1819cb78399da86d84 (diff)
downloadhaskell-328c212b1db4d439fc693216495515bce162ef6e.tar.gz
Fix the sdist build
Since commit 824e34e30338b4b1de0ab5467ffd29da4c7c805a, building ghc from a source distribution doesn't work. The error is: make[3]: *** No rule to make target 'utils/genprimopcode/dist/build/Lexer.hs', needed by 'utils/genprimopcode/dist/build/Lexer.o'. Stop. This commit fixes that. See note [Implicit rule search algorithm]. Differential Revision: https://phabricator.haskell.org/D959
Diffstat (limited to 'rules')
-rw-r--r--rules/hs-suffix-way-rules.mk82
1 files changed, 80 insertions, 2 deletions
diff --git a/rules/hs-suffix-way-rules.mk b/rules/hs-suffix-way-rules.mk
index f9ecf6e99a..4735182017 100644
--- a/rules/hs-suffix-way-rules.mk
+++ b/rules/hs-suffix-way-rules.mk
@@ -29,6 +29,86 @@ $1/$2/build/%.$$(dyn_osuf)-boot: $1/$2/build/%.$$(v_hisuf)-boot
fi
else
+# Note [Implicit rule search algorithm]
+#
+# The order in which implicit rules are defined can influence a build.
+#
+# Case study: genprimpos/Lexer.hs
+#
+# We have two implicit rules for creating .o files, which after instantiating
+# with a specific directory ($1=utils/genprimops) and distdir ($2=dist) look
+# like this:
+#
+# utils/genprimops/dist/build/%.o : utils/genprimops/dist/build/%.hs
+# <recipe1>
+# utils/genprimops/dist/build/%.o : utils/genprimops/./%.hs
+# <recipe2>
+#
+# The first rule is defined in hs-suffix-way-rules.mk (this file), the other
+# in hs-suffix-way-rules-srcdir.mk.
+#
+# Assume for rest of this story that %=Lexer.
+#
+# In a normal repository checkout, neither Lexer.hs exists, but we have a rule
+# to generate the one in the build directory by running alex on Lexer.x (the
+# rule for that operation is defined in hs-suffix-rules-srcdir.mk). Since make
+# needs to make a choice which of the above two implicit rules to follow (it
+# never runs 2 recipes for the same target, unless double colon rules are
+# used, which we don't), logically it will choose the first rule: Lexer.o will
+# depend on Lexer.hs in the build directory, that file will be build, and then
+# Lexer.o can be build.
+#
+# In an sdist however, Lexer.hs is present in the source directory. It was
+# copied there during the creation of the sdist by a rule in
+# sdist-ghc-file.mk. And this time we *don't* know how to generate the
+# Lexer.hs in the build directory, because 1) alex is not installed when
+# building from sdist and 2) the sdist creation process renamed Lexer.x to
+# Lexer.x.source. So normally make would now choose the second rule: Lexer.o
+# will depend on Lexer.hs in the source directory, for which nothing needs to
+# be done, and then Lexer.o can be build.
+#
+# There is however another actor in play, a rule in sdist-ghc-file.mk, which
+# after after instantiating with the same directory ($1=utils/genprimops) and
+# distdir ($2=dist) looks like this:
+#
+# sdist_utils/genprimops_dist_Lexer : utils/genprimops/dist/build/Lexer.hs
+#
+# Note that this is not an implicit rule, there aren't any %'s. This rule
+# *explicitly* depends on Lexer.hs in the build directory. What follows is the
+# following:
+#
+# * make thinks Lexer.hs in the build directory "ought to exist" [1],
+# because it is an explicit dependency of /some/ target.
+#
+# * this puts our two implicit rules on equal footing: one depends on a
+# file that exists, the other on a file that ought to exist. Make's
+# implicit rule search algorithm doesn't distinguish between these two
+# cases [1].
+#
+# * to break the tie, make chooses the rule that is defined first. Lexer.o
+# will depend on Lexer.hs in the build directory, which doesn't exist,
+# and which make doesn't know how to build, causing a build failure.
+#
+# To prevent this from happening we define rules for haskell source files in
+# the source directory before those in the distdir.
+#
+# Alternative solutions:
+#
+# * Don't include the explicit rule above when not creating an sdist, as
+# that is the only time when it is needed.
+#
+# * Merge the two implicit rules, with help from $1_$2_HS_SRCS from
+# hs-sources.mk, which is sdist aware.
+#
+# * Require alex and happy to be installed when building from an sdist,
+# simplifying all this drastically.
+#
+# [1] https://www.gnu.org/software/make/manual/make.html#Implicit-Rule-Search
+
+$$(foreach dir,$$($1_$2_HS_SRC_DIRS),\
+ $$(eval $$(call hs-suffix-way-rules-srcdir,$1,$2,$3,$$(dir))))
+
+
ifneq "$$(BINDIST)" "YES"
$1/$2/build/%.$$($3_hcsuf) : $1/$2/build/%.hs $$(LAX_DEPS_FOLLOW) $$$$($1_$2_HC_DEP)
@@ -45,8 +125,6 @@ $1/$2/build/%.$$($3_osuf) : $1/$2/build/autogen/%.hs $$(LAX_DEPS_FOLLOW) $$$$($1
endif
-$$(foreach dir,$$($1_$2_HS_SRC_DIRS),\
- $$(eval $$(call hs-suffix-way-rules-srcdir,$1,$2,$3,$$(dir))))
endif