覆盖 makefile 中的目标以添加更多命令?
在工作中,我们使用其他 makefile 包含的通用 makefile(通过 include 语句),并且它有一个通用的“干净”目标,可以杀死一些常见文件。我想在新的 makefile 中添加该目标,这样我就可以删除一些特定的文件,但如果我在 makefile 中添加一个干净的目标,它只会覆盖旧的目标。
我知道我可以用新名称创建一个新目标并让它调用 clean,然后执行其他操作,但为了保持一致性,我希望能够只调用 make clean 并让它执行所有操作。
这可能吗?
At work we use a common makefile that other makefiles include (via the include statement) and it has a generic "clean" target that kills some common files. I want to add on to that target in my new makefile so I can delete some specific files, but if I add a clean target in my makefile, it just overrides the old one.
I know I can just make a new target with a new name and have it call clean, and then do other stuff, but for sake of consistency I'd like to be able to just call make clean and have it do everything.
Is that possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我在几家商店看到过这样做。最常见的方法是使用双冒号规则,假设您使用的是 GNU make 之类的东西。在你的通用 makefile 中,你会看到这样的内容:
请注意,
clean
后面有两个 冒号,而不是只有一个!在您的另一个 makefile 中,您只需再次声明
clean
作为双冒号规则:当您调用
make clean
时,GNU make 将自动运行干净的规则:它设置起来很简单,而且我认为它的组成相当整齐。请注意,特别是因为它是双冒号规则,所以您不会遇到为同一目标定义两个规则时通常会出现的“覆盖命令”错误。这就是双冒号规则的要点。
I've seen this done at several shops. The most common approach is to use double-colon rules, assuming you're using something like GNU make. In your common makefile you would have something like this:
Note that there are two colons following
clean
, not just one!In your other makefile you just declare
clean
again, as a double-colon rule:When you invoke
make clean
, GNU make will automagically run both of these "branches" of the clean rule:It's simple to set up and it composes quite neatly I think. Note that specifically because it is a double-colon rule, you don't get the "overriding commands" errors you normally get when you define two rules for the same target. That's sort of the point of double-colon rules.
您可以编写自己的清理并将其作为公共清理的先决条件。
你的将首先运行。如果出于某种原因您希望首先运行公共清理,那么解决方案将更加复杂。
编辑:
这是我能看到的最好的解决方案,它在本地规则之前运行通用规则:
include
指令是必要的,因为本地 makefile 依赖于通用规则。除了干净
之外。本地clean
规则会覆盖通用clean
规则,但会在执行其他工作之前调用通用clean
规则。 (这种覆盖会导致一些警告,这很麻烦;我不知道有什么好方法可以让它们保持沉默。)You can write your own clean and make it a preq of the common clean.
Yours will run first. If for some reason you want the common clean to run first then the solution will be more complicated.
EDIT:
Here is the best solution I can see which runs the common rule before the local one:
The
include
directive is necessary because the local makefile relies on the common one for things other thanclean
. The localclean
rule overrides the commonclean
rule, but invokes the commonclean
rule before doing the additional work. (This overriding will cause some warnings, which is a nuisance; I don't know a good way to silence them.)使用隐式规则:
非常简单的 make 教程。
使用 :: 你可能会遇到问题,因为当你混合使用单冒号 : 和双冒号 :: 规则时 make 会抱怨:
将导致:
Use implicit rules:
Very simple make tutorial to ramp up.
When using :: you can run into issues since make complains when you mix single colon : and double colon :: rules:
will result in:
看起来通用 makefile 的规则应该被称为
common-clean
之类的东西。然后每个主 makefile 都会声明它们的干净规则,并且您已设置。
如果这不是一个选项,您可以查看 double冒号规则,但这些引入了一系列需要考虑的其他问题。
It seems like the common makefile's rule should be called something like
common-clean
. Then each main makefile would declare their clean rule asand you're set.
If that isn't an option, you could take a look at double colon rules, but those introduce a whole other set of issues to consider.
添加我为后人看到的另一个可能的解决方案...我知道OP对于更改通用makefile持谨慎态度,但像这样的东西是有效的并且只涉及很少的更改。
本地 makefile 1:
本地 makefile 2:
通用 makefile:
基本上,其想法是在每个本地 makefile 中定义一些变量(在本例中为
CLEAN
),其中包含要删除的所有特定项目。然后,通用 makefile 对所有要删除的通用文件类型运行 rm -f ,以及通过CLEAN
变量在每个本地 makefile 中专门标记为删除的文件。如果没有什么具体要删除的内容,只需省略变量声明或将其留空 (CLEAN=
)因此,现在如果我们对本地 makefile 1 运行
make clean
,它将执行如果我们为本地 makefile 2 运行
make clean
,它执行Adding another possible solution I've seen for posterity... I know the OP was wary about changing the common makefile, but something like this works and involves minimal changes.
local makefile 1:
local makefile 2:
common makefile:
Basically the idea is to define some variable (in this case
CLEAN
) in each local makefile with all the specific items you want to delete. Then the common makefile runsrm -f
on all the common file types to delete, plus whatever was specifically flagged for deletion in each local makefile via theCLEAN
variable. If there's nothing specific to delete, simply omit the variable declaration or leave it empty (CLEAN=
)So now if we run
make clean
for local makefile 1, it executesAnd if we run
make clean
for local makefile 2, it executes我找到了更好的解决方案:
关键行是
clean: my-extra-clean
。即,您可以在不同 makefile 的单独节中添加依赖项来添加行为。 my-extra-clean 作为根 clean 目标的依赖项运行。I've found a better solution:
The key line is
clean: my-extra-clean
. Ie, you can add dependencies in separate stanzas in different makefiles to add behaviour. my-extra-clean is run as a dependency of the root clean target.对于我们来说,我们定义一个变量 EXTRAFILESTOCLEAN,然后当 clean 规则运行时,它有一个步骤来删除 EXTRAFILESTOCLEAN 变量中指定的任何内容,
如果您将该变量设置为奇怪的值,可能会导致意外的问题,但您可以通过以下方式防范这些问题添加前缀或其他测试。
For ours, we define a variable, EXTRAFILESTOCLEAN, then when the clean rule runs, it has a step to remove anything specified in the EXTRAFILESTOCLEAN variable
That can cause unexpected problems if you set that variable to weird values, but you could guard against those by adding prefixes or other tests.
它在文档中: https://www.gnu.org /software/make/manual/html_node/Overriding-Makefiles.html
因此,您使用通配符目标而不是
include Makefile
并将其转发到基本Makefile
:It's in the docs: https://www.gnu.org/software/make/manual/html_node/Overriding-Makefiles.html
So instead of
include Makefile
you use a wildcard target and forward it to the baseMakefile
: