覆盖 makefile 中的目标以添加更多命令?

发布于 2024-08-09 03:46:46 字数 259 浏览 2 评论 0原文

在工作中,我们使用其他 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

攒一口袋星星 2024-08-16 03:46:46

我在几家商店看到过这样做。最常见的方法是使用双冒号规则,假设您使用的是 GNU make 之类的东西。在你的通用 makefile 中,你会看到这样的内容:

clean::
        # standard cleanup, like remove all .o's:
        rm -f *.o

请注意,clean 后面有两个 冒号,而不是只有一个!

在您的另一个 makefile 中,您只需再次声明 clean 作为双冒号规则:

clean::
        # custom cleanup, like remove my special generated files:
        rm -f *.h.gen

当您调用 make clean 时,GNU make 将自动运行干净的规则:

% make clean
rm -f *.o
rm -f *.h.gen

它设置起来很简单,而且我认为它的组成相当整齐。请注意,特别是因为它是双冒号规则,所以您不会遇到为同一目标定义两个规则时通常会出现的“覆盖命令”错误。这就是双冒号规则的要点。

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:

clean::
        # standard cleanup, like remove all .o's:
        rm -f *.o

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:

clean::
        # custom cleanup, like remove my special generated files:
        rm -f *.h.gen

When you invoke make clean, GNU make will automagically run both of these "branches" of the clean rule:

% make clean
rm -f *.o
rm -f *.h.gen

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.

天赋异禀 2024-08-16 03:46:46

您可以编写自己的清理并将其作为公共清理的先决条件。

clean: myclean

myclean:
    rm whatever

你的将首先运行。如果出于某种原因您希望首先运行公共清理,那么解决方案将更加复杂。

编辑:

这是我能看到的最好的解决方案,它在本地规则之前运行通用规则:

include Makefile.common

clean:
    $(MAKE) -f Makefile.common $@
    rm whatever additional things

include 指令是必要的,因为本地 makefile 依赖于通用规则。除了干净之外。本地 clean 规则会覆盖通用 clean 规则,但会在执行其他工作之前调用通用 clean 规则。 (这种覆盖会导致一些警告,这很麻烦;我不知道有什么好方法可以让它们保持沉默。)

You can write your own clean and make it a preq of the common clean.

clean: myclean

myclean:
    rm whatever

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:

include Makefile.common

clean:
    $(MAKE) -f Makefile.common $@
    rm whatever additional things

The include directive is necessary because the local makefile relies on the common one for things other than clean. The local clean rule overrides the common clean rule, but invokes the common clean 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.)

浅浅淡淡 2024-08-16 03:46:46

使用隐式规则:

existing-target: my-extention

my-extention:
    echo running command 1
    echo running command 2

非常简单的 make 教程。

使用 :: 你可能会遇到问题,因为当你混合使用单冒号 : 和双冒号 :: 规则时 make 会抱怨:

a:
    echo a

a::
    echo aa

将导致:

. . .
*** target file `a' has both : and :: entries.  Stop.

Use implicit rules:

existing-target: my-extention

my-extention:
    echo running command 1
    echo running command 2

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:

a:
    echo a

a::
    echo aa

will result in:

. . .
*** target file `a' has both : and :: entries.  Stop.
寻梦旅人 2024-08-16 03:46:46

看起来通用 makefile 的规则应该被称为 common-clean 之类的东西。然后每个主 makefile 都会声明它们的干净规则,并且

clean: common-clean

您已设置。

如果这不是一个选项,您可以查看 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 as

clean: common-clean

and 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.

听风吹 2024-08-16 03:46:46

添加我为后人看到的另一个可能的解决方案...我知道OP对于更改通用makefile持谨慎态度,但像这样的东西是有效的并且只涉及很少的更改。

本地 makefile 1:

CLEAN=MyExe1 MyExe2
....
include /my/common/makefile

本地 makefile 2:

CLEAN=MyExe3 MyExe4
....
include /my/common/makefile

通用 makefile:

clean:
     rm -f *.dep *.o *.a $(CLEAN)

基本上,其想法是在每个本地 makefile 中定义一些变量(在本例中为 CLEAN),其中包含要删除的所有特定项目。然后,通用 makefile 对所有要删除的通用文件类型运行 rm -f ,以及通过 CLEAN 变量在每个本地 makefile 中专门标记为删除的文件。如果没有什么具体要删除的内容,只需省略变量声明或将其留空 (CLEAN=)

因此,现在如果我们对本地 makefile 1 运行 make clean,它将执行

rm -f *.dep *.o *.a MyExe1 MyExe2

如果我们为本地 makefile 2 运行 make clean,它执行

rm -f *.dep *.o *.a MyExe3 MyExe4

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:

CLEAN=MyExe1 MyExe2
....
include /my/common/makefile

local makefile 2:

CLEAN=MyExe3 MyExe4
....
include /my/common/makefile

common makefile:

clean:
     rm -f *.dep *.o *.a $(CLEAN)

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 runs rm -f on all the common file types to delete, plus whatever was specifically flagged for deletion in each local makefile via the CLEAN 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 executes

rm -f *.dep *.o *.a MyExe1 MyExe2

And if we run make clean for local makefile 2, it executes

rm -f *.dep *.o *.a MyExe3 MyExe4
流云如水 2024-08-16 03:46:46

我找到了更好的解决方案:

.PHONY: my-extra-clean

clean: my-extra-clean

my-extra-clean:
      rm <whatever-you-want>

include Makefile.common

关键行是 clean: my-extra-clean。即,您可以在不同 makefile 的单独节中添加依赖项来添加行为。 my-extra-clean 作为根 clean 目标的依赖项运行。

I've found a better solution:

.PHONY: my-extra-clean

clean: my-extra-clean

my-extra-clean:
      rm <whatever-you-want>

include Makefile.common

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.

嘿哥们儿 2024-08-16 03:46:46

对于我们来说,我们定义一个变量 EXTRAFILESTOCLEAN,然后当 clean 规则运行时,它有一个步骤来删除 EXTRAFILESTOCLEAN 变量中指定的任何内容,

clean:
    rm -f *.o
ifdef $(EXTRAFILESTOCLEAN)
    rm -f $(EXTRAFILESTOCLEAN)
endif

如果您将该变量设置为奇怪的值,可能会导致意外的问题,但您可以通过以下方式防范这些问题添加前缀或其他测试。

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

clean:
    rm -f *.o
ifdef $(EXTRAFILESTOCLEAN)
    rm -f $(EXTRAFILESTOCLEAN)
endif

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.

征棹 2024-08-16 03:46:46

它在文档中: https://www.gnu.org /software/make/manual/html_node/Overriding-Makefiles.html

因此,您使用通配符目标而不是 include Makefile 并将其转发到基本 Makefile

# -include base.Makefile <--- not this

%:
    @$(MAKE) -f base.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 base Makefile:

# -include base.Makefile <--- not this

%:
    @$(MAKE) -f base.Makefile $@
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文