Makefile 在模式规则中定义先决条件的选择

Makefile 在模式规则中定义先决条件的选择,makefile,gnu-make,Makefile,Gnu Make,例如,假设我有一个编译器,可以从bar或baz源代码构建foo文件 这方面的规则可能如下所示: %.foo: %.bar # commands to # invoke compiler %.foo: %.baz # commands to # invoke compiler 然而,随着输入类型和配方命令数量的增加,这可能开始变得有点长和冗余。是否有任何语法可用于将其压缩为单个规则 %.foo: $(oneof %.bar %.baz) # comman

例如,假设我有一个编译器,可以从
bar
baz
源代码构建
foo
文件

这方面的规则可能如下所示:

%.foo: %.bar
    # commands to
    # invoke compiler

%.foo: %.baz
    # commands to
    # invoke compiler
然而,随着输入类型和配方命令数量的增加,这可能开始变得有点长和冗余。是否有任何语法可用于将其压缩为单个规则

%.foo: $(oneof %.bar %.baz)
    # commands to
    # invoke compiler

您在开始时提出的建议是正确的:makefile应该清晰简洁地描述构建规则

另一方面,您可以查看以避免重复相同的食谱:

define MAKE_FOO =
#You may use automatic variables such as $^ or $@.
mv $< $@    #In this example just a file renaming.
endef

%.foo: %.bar
    $(MAKE_FOO)

%.foo: %.baz
    $(MAKE_FOO)
定义MAKE\u FOO=
#您可以使用自动变量,如$^或$@。
mv$<$@#在本例中,只是一个文件重命名。
恩德夫
%.foo:%巴
$(MAKE_FOO)
%.foo:%.baz
$(MAKE_FOO)

罐装配方
MAKE_FOO
将扩展到您在
define
语句中编写的任何配方,就像它们是手动复制的一样。

下面是制作
.o
文件的具体问题的说明 从具有组合模式规则的
.c
文件或
.cpp
文件。 还构建了一个可执行文件来辅助说明

Makefile

.PHONY: all clean

all: test

%.o: %.c %.cpp
    gcc -c $?

test: main.o hw.o
    g++ -o $@ $^

clean:
    rm -f test *.o  
我们有:

hw.c

#include <stdio.h>

void hw(void)
{
    puts("Hello from C");
}
从清洁和运行开始制作:

$ make clean && make && ./test
rm -f test *.o
g++    -c -o main.o main.cpp
gcc -c hw.c hw.cpp
g++ -o test main.o hw.o
Hello from C++
hw.c
hw.cpp
都是按照模式规则编译的

每个编译成同一个对象文件,<代码> HW.O./COD>,第二个,C++ 编译覆盖C编译。所以C++对象文件被链接, 只是因为它是最后一个建成的。清楚你期望得到什么 当组合规则由多个先决条件触发时发生

现在让我们更新
hw.c
并重复:

$ touch hw.c
$ make && ./test
gcc -c hw.c
g++ -o test main.o hw.o
Hello from C
$ touch hw.cpp
make && ./test
gcc -c hw.cpp
g++ -o test main.o hw.o
Hello from C++
这一次,
hw.o
仅从
hw.c
编译并链接

更新
hw.cpp
并重复:

$ touch hw.c
$ make && ./test
gcc -c hw.c
g++ -o test main.o hw.o
Hello from C
$ touch hw.cpp
make && ./test
gcc -c hw.cpp
g++ -o test main.o hw.o
Hello from C++

再次,C++中的<代码> HW.O./COD>链接。 组合模式规则的关键元素是


表示比目标更新的所有先决条件

我不确定源代码在答案中添加了什么。更重要的是,如果只有一个源代码存在,会发生什么?源代码只是提供了一个工作示例,并解释了为什么会看到所看到的。如果只有一个
.c
.cpp
存在,那么就是编译的那一个。好的,但是如果答案更短,我会发现它更可读。