在模式规则中定义先决条件的选择
Define a choice of prerequisites in a pattern rule
例如,假设我有一个编译器,可以从 bar
或 baz
源构建 foo
文件。
此规则可能如下所示:
%.foo: %.bar
# commands to
# invoke compiler
%.foo: %.baz
# commands to
# invoke compiler
但是,随着输入类型和配方命令数量的增加,这可能开始变得有点冗长和多余。是否有任何语法可用于将其压缩为单个规则?
%.foo: $(oneof %.bar %.baz)
# commands to
# invoke compiler
您一开始提出的建议是正确的:Makefile 在构建规则方面应该清晰简洁。
另一方面,您可以看看 Canned Recipes 以尽量避免一次又一次地重复相同的食谱:
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_FOO
将扩展为您在 define
语句中编写的任何食谱,就好像它们是手动复制的一样。
这是制作.o
文件的具体问题的说明
来自 .c
文件或具有组合模式规则的 .cpp
文件。
还构建了一个可执行文件来帮助说明。
生成文件
.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");
}
hw.cpp
#include <iostream>
extern "C" void hw()
{
std::cout << "Hello from C++" << std::endl;
}
和:
main.cpp
extern "C" void hw(void);
int main(void)
{
hw();
return 0;
}
由干净的 运行:
$ 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
、与第二个,C++
编译覆盖 C 编译。所以链接了 C++ 目标文件,
仅仅因为它是最后建造的。明确你的期望
当 多个先决条件 .
触发组合规则时发生
现在让我们更新 hw.c
并重复:
$ touch hw.c
$ make && ./test
gcc -c hw.c
g++ -o test main.o hw.o
Hello from C
这一次,hw.o
仅从 hw.c
编译并链接。
更新 hw.cpp
并重复:
$ touch hw.cpp
make && ./test
gcc -c hw.cpp
g++ -o test main.o hw.o
Hello from C++
再次链接了来自 C++ 的 hw.o
。
组合模式规则的关键元素是$?
,它
表示所有比目标更新的先决条件
例如,假设我有一个编译器,可以从 bar
或 baz
源构建 foo
文件。
此规则可能如下所示:
%.foo: %.bar
# commands to
# invoke compiler
%.foo: %.baz
# commands to
# invoke compiler
但是,随着输入类型和配方命令数量的增加,这可能开始变得有点冗长和多余。是否有任何语法可用于将其压缩为单个规则?
%.foo: $(oneof %.bar %.baz)
# commands to
# invoke compiler
您一开始提出的建议是正确的:Makefile 在构建规则方面应该清晰简洁。
另一方面,您可以看看 Canned Recipes 以尽量避免一次又一次地重复相同的食谱:
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_FOO
将扩展为您在 define
语句中编写的任何食谱,就好像它们是手动复制的一样。
这是制作.o
文件的具体问题的说明
来自 .c
文件或具有组合模式规则的 .cpp
文件。
还构建了一个可执行文件来帮助说明。
生成文件
.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");
}
hw.cpp
#include <iostream>
extern "C" void hw()
{
std::cout << "Hello from C++" << std::endl;
}
和:
main.cpp
extern "C" void hw(void);
int main(void)
{
hw();
return 0;
}
由干净的 运行:
$ 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
、与第二个,C++
编译覆盖 C 编译。所以链接了 C++ 目标文件,
仅仅因为它是最后建造的。明确你的期望
当 多个先决条件 .
现在让我们更新 hw.c
并重复:
$ touch hw.c
$ make && ./test
gcc -c hw.c
g++ -o test main.o hw.o
Hello from C
这一次,hw.o
仅从 hw.c
编译并链接。
更新 hw.cpp
并重复:
$ touch hw.cpp
make && ./test
gcc -c hw.cpp
g++ -o test main.o hw.o
Hello from C++
再次链接了来自 C++ 的 hw.o
。
组合模式规则的关键元素是$?
,它
表示所有比目标更新的先决条件