简体   繁体   English

Makefile中的“可选”对象文件目标?

[英]“Optional” object file target in Makefile?

I have some code that is "optional": the rest of the program can be linked without it. 我有一些“可选”的代码:程序的其余部分可以在没有它的情况下链接。
How do I properly create a Makefile that excludes it as a dependency if there is an error when creating the object file? 如果在创建目标文件时出错,如何正确创建将其排除为依赖项的Makefile?

So far I have something like this: 到目前为止,我有这样的事情:

OUT=my_program
OBJS=$(subst .cc,.o,$(wildcard *.cc))

all: $(OUT)
$(OUT): $(OBJS)

my_optional_file.o: other_target

.IGNORE: my_optional_file.o

The good: When processing the rule my_optional_file.o , this correctly ignores all errors. 好处:处理规则my_optional_file.o ,这正确地忽略了所有错误。

The bad: When linking the output, my_optional_file.o is specified as an argument to the linker despite the fact that it was not built, making the linker fail because it was given a nonexistent file as input! 坏处:链接输出时, my_optional_file.o被指定为链接器的参数, 尽管它没有构建,导致链接器失败,因为它被赋予了一个不存在的文件作为输入!

How do I exclude my_optional_file.o when there is an error in building it? 如何在构建错误时排除my_optional_file.o

Use $(shell find . -maxdepth 1 -iname "*.o") with an explicit call to the linker. 使用$(shell find . -maxdepth 1 -iname "*.o")并显式调用链接器。

Like : 喜欢 :

$(OUT): $(OBJS)
    $(CXX) $(LDFLAGS) $(shell find . -maxdepth 1 -iname "*.o") $(LDLIBS) -o $@

The reason is that when implicitly called, the linker command is called like this : 原因是当隐式调用时,链接器命令被调用如下:

$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@

With $^ expanding to the content of $(OBJS) . 随着$^扩展到$(OBJS)的内容。 You need an explicit call to use specific files instead. 您需要显式调用才能使用特定文件。


The $(wildcard *.o) function cannot be used because it is executed before the files are created so it is always empty. 无法使用$(wildcard *.o)函数,因为它在创建文件之前执行,因此它始终为空。

Assuming your make is GNU make , here is one way of doing this. 假设你的make是GNU make ,这是一种方法。

Say my program prog has three source files main.c , necessary.c , optional.c such that I want to link prog from all three .o files, if they get built ( = a maximal build ), but I will settle for main.o and necessary.o ( = a minimal build ). 假设我的程序prog有三个源文件main.cnecessary.coptional.c这样我想从所有三个.o文件链接prog ,如果它们被构建(= 最大构建 ),但我会满足于main.onecessary.o (= 最小版本 )。 (I waive the rationale for this). (我放弃了这个理由)。

A makefile to the purpose is: 用于此目的的makefile是:

.phony: all clean make_prog

max_objs=$(subst .c,.o,$(wildcard *.c))

all: make_prog

make_prog: $(max_objs)
    $(MAKE) prog

prog: $(wildcard *.o)
    gcc -o $@ $^

clean:
    rm -f prog *.o

.IGNORE: optional.o 

To make prog I first make the phony target, make_prog , whose prerequisites are all three .o files, but I ignore failure to make optional.o . 为了制作prog我首先制作假目标make_prog ,其先决条件是所有三个.o文件,但我忽略了使optional.o失败。 Then I make prog for real, and to do that I just link whatever .o files I've got at this point. 然后我做了真实的prog ,为此我只是链接我在这一点上得到的任何.o文件。 If optional.o isn't there, it doesn't matter. 如果不存在optional.o ,则无关紧要。

To be clear about the behaviour of this:- 要清楚这种行为: -

  • If, initially, I have a maximal build of prog , then make a change that breaks optional.c and re-make, no .o is re-made, so prog is not re-made. 如果,最初,我有一个最大的prog ,然后进行一个更改,打破optional.c并重新制作,没有.o重新制作,所以prog不会重新制作。 It stays maximal. 它保持最大化。

  • If, initially, I have a minimal build of prog , then make a change that fixes optional.c and re-make, optional.o is re-made, so prog is re-made. 如果一开始,我有一个最小的构建prog ,然后进行, 修复改变optional.c并重新作出, optional.o被重新制作,所以prog重新制作。 It becomes maximal. 它变得最大。

Failure to make optional.o excludes prog 's dependency on it and introduces no new ones. 未能使optional.o排除了prog对它的依赖,并且没有引入新的。 So if all other dependencies are satisfied, there's no need to remake prog . 因此,如果满足所有其他依赖关系,则无需重新prog

Now it might be the case that you actually want failure to make optional.o to introduce a dependency on the failure to make optional.o , in the sense that it would force prog to be rebuilt minimally . 现在,它可能是你真正想要的故障的情况下作出optional.o引进依赖的失败,使 optional.o ,在某种意义上说,它会迫使prog是重建最小

A simple way to achieve that is by adding the line: 实现这一目标的一种简单方法是添加以下行:

.INTERMEDIATE: optional.o

to the makefile, which will force optional.o always to be deleted at the end of a make. 到makefile,它会强制在make的末尾删除optional.o This has the cost that optional.c will always be compiled, and consequently a maximal build will always be re-linked. 这具有将始终编译optional.c的成本,因此将始终重新链接最大构建。

Lastly, someone might wonder why the makefile couldn't more simply be: 最后,有人可能想知道为什么makefile不能简单地:

.phony: all clean

objs=$(subst .c,.o,$(wildcard *.c))

all: prog

prog: $(objs)
    gcc -o $@ $(wildcard *.o)

clean:
    rm -f prog *.o

.IGNORE: optional.o

Well if we do a make from clean with that, the output is: 好吧,如果我们用干净的那个做一个make,输出是:

cc    -c -o main.o main.c
cc    -c -o necessary.o necessary.c
cc    -c -o optional.o optional.c
gcc -o prog 
gcc: fatal error: no input files
compilation terminated.
make: *** [prog] Error 4

That's because $(wildcard *.o) is expanded when the makefile is parsed, and at that point no .o files exist. 这是因为在解析makefile时会扩展$(wildcard *.o) ,并且此时不存在.o文件。 We need to be parsing the makefile again when we expand this, having already made all the .o files we can. 我们需要在扩展它时再次解析makefile,我们已经创建了所有.o文件。

GNU make does not have optional dependencies. GNU make没有可选的依赖项。 You can simulate that by not returning failure when it fails to build and filtering out non-existent objects when linking. 您可以通过在链接时无法构建和过滤掉不存在的对象时不返回失败来模拟它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM