允许Makefile追加并覆盖目标

时间:2017-06-13 16:57:39

标签: makefile gnu-make

我的所有服务都有基础Makefile,在某些情况下我想使用我的默认"测试"目标,在其他情况下,我想覆盖\添加它。这些是我到目前为止的文件(显然它没有按预期工作......)。

MakefileBase

test:
    ./.../run-tests.sh

生成文件

BASE_FILE := /path/to/MakefileBase
include ${BASE_FILE}
test:
    @$(MAKE) -f $(BASE_FILE) test # un/comment this line in order to run the default tests.
#   echo "custom test"

当我在第一行注释时运行测试时,我得到以下内容

Makefile:10: warning: overriding commands for target `test'
/.../MakefileBase:63: warning: ignoring old commands for target `test'
echo "no tests"
no tests

除了警告它按预期工作,问题是当我尝试使用父函数时,我得到以下错误:

Makefile:9: warning: overriding commands for target `test'
/.../MakefileBase:63: warning: ignoring old commands for target `test'
make[1]: test: No such file or directory
make[1]: *** No rule to make target `test'.  Stop.
make: *** [test] Error 2

3 个答案:

答案 0 :(得分:2)

实际上,到目前为止,两个答案都是错误的或不完整的:

规则中的

exit 0只会退出当前shell(仅运行exit 0命令,因此在这种情况下为空操作)。所以这不会覆盖。

在没有警告的情况下您不能覆盖命令是不正确的。如果不需要两个目标都具有相同的名称,则可以执行以下操作:

MakefileBase

.PHONY: test-base
test-base:
    echo base

%: %-base  # handles cases where you don't want to override

Makefile1

include MakefileBase

.PHONY: test
test:
    echo override

Makefile

include MakefileBase

.PHONY: test
test: test-base
    echo append

与双冒号规则一样,必须考虑每个目标(彼此)的影响,尤其是当您远离.PHONY时(例如,文件被认为是最新的,因为另一个规则刚刚更新了它们。)

顺便说一句,我没有看到您的方法出现问题(除了警告)。对我来说,它工作正常。

答案 1 :(得分:0)

这是double-colon rules的用途:

test::
        ./.../run-tests.sh

BASE_FILE := /path/to/MakefileBase
include ${BASE_FILE}

test::
        @$(MAKE) -f $(BASE_FILE) test

这将"添加到"现有目标。在没有发出警告的情况下,无法使用不同的配方覆盖目标。

如果您想这样做,唯一的方法是使用变量来保存配方,然后覆盖变量值。例如:

test_recipe = ./.../run-tests.sh

test:
        $(test_recipe)

BASE_FILE := /path/to/MakefileBase
include ${BASE_FILE}

test_recipe = @$(MAKE) -f $(BASE_FILE) test

答案 2 :(得分:0)

很麻烦,但是您可以添加,还有一种有限形式的替代,它永远不能比一个替代更深。两者都使用双冒号规则。

添加:在两个规则上都使用双冒号

覆盖:在两个规则上都使用双冒号,将命令exit 0附加到最后一个规则

# "addcmd" echoes "BA", "overridecmd" echoes "B"

addcmd ::
  echo "A"

addcmd ::
  echo "B"

overridecmd ::
  echo "A"

overridecmd ::
  echo "B"
  exit 0