c++ - 有什么方法可以在 GNU Make 中使用变量作为规则和先决条件?
问题描述
我正在尝试以这样一种方式设置我的 Makefile,以便我可以在某些变量中定义所有输入和输出,因此我只需要编写一个规则来编译项目。这使我可以最小化 Makefile 代码,并且仍然可以控制我的项目中的内容。这是相关的代码片段:
ROOT_OBJS= \
$(B)/main.o \
$(B)/src1.o
ROOT_SRC= \
$(SRC)/main.cpp \
$(SRC)/src1.cpp
$(TARGET) : $(ROOT_OBJS)
$(LD) $(LD_FLAGS) $^ -o $@
$(ROOT_OBJS) : $(ROOT_SRC)
$(CXX) $(CFLAGS) $< -o $@
$<
除了第二条规则中的部分之外,这大部分都有效,它总是使用 main.cpp。有什么解决办法吗?或者我是不是走错了路?
编辑:为澄清起见,这是我期望的输出:
g++ main.cpp -o main.o
g++ src1.cpp -o src1.o
这是我得到的输出:
g++ main.cpp -o main.o
g++ main.cpp -o src1.o
我知道这是因为$<
需要第一个依赖项,我认为 make 会足够聪明地弄清楚它,因为 .o 行为是我想要的。
$^
不是我要找的。我希望 gcc 为每个 cpp 文件创建一个单独的目标文件。
解决方案
$<
总是以第一个前提为前提。由于您的规则扩展到
$(B)/main.o $(B)/src1.o : $(SRC)/main.cpp $(SRC)/src1.cpp
$(CXX) $(CFLAGS) $< -o $@
$(SRC)/main.cpp
始终是第一个先决条件。就和而言之间 没有 神奇 的 联系$(B)/main.o
$(SRC)/main.cpp
make
.
如果您希望您的规则建立这种联系,您必须将其编码到规则中。有几种方法可以做到这一点。最直接的方法是为每个目标编写单独的规则:
$(B)/main.o : $(SRC)/main.cpp
$(CXX) $(CFLAGS) $< -o $@
$(B)/src1.o : $(SRC)/src1.cpp
$(CXX) $(CFLAGS) $< -o $@
您还可以使用这样的模式规则:
$(B)/%.o : $(SRC)/%.cpp
$(CXX) $(CFLAGS) $< -o $@
在这里,$<
做正确的事是因为$(SRC)/%.cpp
用模式参数化了,所以它会扩展为正确的源文件。
您拥有的最大的武器是生成个人规则:
STEMS := main src1
$(foreach stem,$(STEMS), \
$(eval $(B)/$(stem).o: $(SRC)/$(stem).cpp ; $(CXX) $(CFLAGS) $< -o $@))
$(STEMS)
在这里,我使用内部函数调用遍历所有单词,并使用$(foreach)
函数调用每次迭代生成一个规则$(eval)
。这只是 GNU Make 语法,其他make
实现可能没有这些特性。然而,这是最通用和最灵活的方式来告诉make
你该做什么。GNU Make 的函数调用语法是图灵完备的,因此您可以执行任何需要的计算来得出正确的规则。但是,可读性会受到影响,因此请谨慎使用。
推荐阅读
- bash - shell脚本,如何总是在默认位置打印换行符?
- python - Python自动舍入数字的问题
- javascript - 发出http请求的最佳方式,然后可能是另一个
- python-3.x - 如何在 Python Pandas 中比较包含列表值的多个列?
- java - 无法将 JWT 令牌附加到 RestTemplate
- node.js - TypeORM 迁移:运行不工作 errno:-3008,getaddrinfo ENOTFOUND
- wordpress - 如何在 onclick href 中调用简码(在 Html 小部件中)?
- python - Flask, SQLAlchemy, SQLite - 查询今天提交的日期时间列
- ajax - Woocommerce 如何使用自定义 html 单选按钮而不是下拉菜单对可变产品的添加到购物车按钮进行 ajaxify - 无插件
- java - 为什么 BufferedImage 不被识别为有效符号?