somake/test/empty_cmd.mf
2016-08-30 10:24:40 +02:00

115 lines
3 KiB
Plaintext

# (A)
.KEEP_STATE:
all: hello
clean:
rm foo.x foo.y
foo.x:
touch foo.x
# <- workaround: disable command dependencies
# ?touch foo.x
foo.y: foo.x
cat foo.x foo.x > foo.y
# <- workaround: disable command dependencies
# ?cat foo.x foo.x > foo.y
# (B)
include foo.y
hello:
echo hello
# The perhaps unintuitive effect of `.KEEP_STATE`
# on the generation of include files.
#
# Effects:
#
# 1) comment out the line after (A)
#
# $ somake -f empty_cmd.mf clean
# rm foo.x foo.y
# $ rm .make.state
# $ somake -f empty_cmd.mf
# touch foo.x
# cat foo.x foo.x > foo.y
# echo hello
# hello
# $ somake -f empty_cmd.mf
# echo hello
# hello
#
# -> meaning that the include file foo.y is only updated
# if it doesn't exist or foo.x is newer. This is
# the expected behavior.
#
# 2) comment in (A) and comment out (B)
#
# $ somake -f empty_cmd.mf clean
# rm foo.x foo.y
# $ rm .make.state
# $ somake -f empty_cmd.mf foo.y
# touch foo.x
# cat foo.x foo.x > foo.y
# $ somake -f empty_cmd.mf foo.y
# `foo.y' is up to date.
#
# -> again, as expected the foo.y action is only executed once.
#
# 3) comment in (A) and (B)
#
# $ somake -f empty_cmd.mf clean
# touch foo.x
# cat foo.x foo.x > foo.y
# rm foo.x foo.y
# $ rm .make.state
# $ somake -f empty_cmd.mf
# touch foo.x
# cat foo.x foo.x > foo.y
# echo hello
# hello
# $ somake -f empty_cmd.mf
# touch foo.x
# cat foo.x foo.x > foo.y
# echo hello
# hello
#
# -> this is unexpected because foo.y is generated each time.
# This is caused by an interaction between KEEP_STATE and
# include. Make reads in the `.make.state` file after
# include directives are being processed. But, as part of the
# dependency checking of the include files the usual KEEP_STATE
# logic is applied such that make assumes that the foo.y action
# command changed from '' (empty) to 'cat foo.x foo.x > foo.y'.
#
# (make basically looks up the 'old' command in an empty database)
#
# When calling make with `-d` the log contains messages like:
#
# different from empty old command
# Building foo.x because new command longer than old
# Building foo.y because new command longer than old
#
# A workaround is to disable command dependencies for the involved
# actions, i.e. `?touch foo` and `?cat foo.x foo.x > foo.y`
#
# This is a bug.
#
# Possible fix:
# i) Just don't use the make.state database before it is loaded.
# This effectively would disable command dependencies for
# generated include files. Similar effect as the described
# workaround.
# ii) or, preferably, load the make.state file before any
# processing of include directives. This would have
# the advantage that an include file is regenerated if a
# variable that is used in the generate action has
# changed (think: `generate.sh $(CC) $(LD) > tool_dependent.mf`