C++ &引用;“可选”;Makefile中的对象文件目标?

C++ &引用;“可选”;Makefile中的对象文件目标?,c++,makefile,C++,Makefile,我有一些代码是“可选的”:程序的其余部分可以在没有它的情况下链接。 如果在创建对象文件时出现错误,如何正确地创建将其作为依赖项排除的Makefile 到目前为止,我有这样的想法: OUT=my_program OBJS=$(subst .cc,.o,$(wildcard *.cc)) all: $(OUT) $(OUT): $(OBJS) my_optional_file.o: other_target .IGNORE: my_optional_file.o 好处:当处理规则my_opt

我有一些代码是“可选的”:程序的其余部分可以在没有它的情况下链接。
如果在创建对象文件时出现错误,如何正确地创建将其作为依赖项排除的Makefile

到目前为止,我有这样的想法:

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

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

my_optional_file.o: other_target

.IGNORE: my_optional_file.o
好处:当处理规则
my_optional_file.o
时,这会正确地忽略所有错误

坏消息:链接输出时,
my_optional_file.o
被指定为链接器的参数,尽管它不是构建的,这使得链接器失败,因为它被提供了一个不存在的文件作为输入


当生成文件时出错时,如何排除
my_optional_file.o

GNU make没有可选的依赖项。您可以通过在构建失败时不返回failure并在链接时过滤掉不存在的对象来模拟这种情况。

使用
$(shell find.-maxdepth 1-iname“*.o”)
,并显式调用链接器

比如:

$(OUT): $(OBJS)
    $(CXX) $(LDFLAGS) $(shell find . -maxdepth 1 -iname "*.o") $(LDLIBS) -o $@
原因是隐式调用时,链接器命令的调用方式如下:

$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
通过
$^
扩展到
$(OBJS)
的内容。您需要显式调用来使用特定文件



无法使用
$(通配符*.o)
函数,因为它是在创建文件之前执行的,所以它总是空的。

假设您的
make
是GNU
make
,下面是一种方法

假设我的程序
prog
有三个源文件
main.c
required.c
optional.c
这样,我想从所有三个
.o
文件链接
prog
,如果它们 构建(=最大构建),但我会满足于
main.o
required.o
(=最小构建)。(我放弃这样做的理由)

用于以下目的的生成文件:

.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 
要制作
prog
我首先制作假目标,
make_prog
,其 先决条件是所有三个
.o
文件,但我忽略了生成的失败
可选.o
。然后我真的做了
prog
,为了做到这一点,我只需要 链接我现在得到的
.o
文件。如果
可选。o
没有,没关系

要了解这种情况,请执行以下操作:-

  • 如果一开始,我有一个
    prog
    的最大构建,那么进行一个中断的更改
    optional.c
    和re-make,不重新生成
    .o
    ,因此不重新生成
    prog
    。信息技术 保持最大值

  • 如果一开始我有一个最小的
    prog
    ,那么做一个修改来修复这个问题
    optional.c
    并重新生成,
    optional.o
    被重新生成,因此
    prog
    被重新生成。信息技术 变得最大

未能将
设置为可选。o
排除
prog
对它的依赖,并引入 没有新的。因此,如果满足了所有其他依赖项,就没有必要这样做 重新制作
prog

现在,您可能真的希望将
设置为可选.o
失败 在中引入对未能使
可选.o
的依赖项 感觉到它将迫使
prog
以最小的速度重建

实现这一目标的简单方法是添加以下行:

.INTERMEDIATE: optional.o
到makefile,这将强制在make结束时始终删除
optional.o
。 这样做的代价是,
optional.c
将始终被编译,因此最大构建将始终被重新链接

最后,有人可能会想,为什么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
如果我们用它来做一个make from clean,输出是:

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
这是因为在生成文件时,
$(通配符*.o)
是展开的 已解析,此时不存在
.o
文件。我们需要进行语法分析 当我们展开此文件时,会再次调用makefile,因为已经完成了所有
我们可以使用
.o
文件。

+1,但“这需要花费
optional.c
始终被编译”。。。没有办法避免这种情况吗?实际上,我在尝试此路由时遇到了这个问题,但不确定如何修复它…我根本没有手动调用链接器,我认为它是隐式调用的。应该吗?这里没有隐式调用。我知道你没有隐式调用它,我想说的是,我的Makefile中肯定没有显式调用,但它仍然在被调用。你是说这不应该发生吗?因为你发布的Makefile不是你使用的完整的Makefile,我想,我只能说你提供了什么。在这个特定的设置中,使用
make
时不会隐式调用它。看我的编辑。+1你让我找到了正确的答案。我没有意识到显式调用链接器工作得这么好。现在很好用了,谢谢。