gpt4 book ai didi

c++ - Makefile 改进,依赖生成不起作用

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:20:19 25 4
gpt4 key购买 nike

我目前正在尝试构建一个合适的 Makefile。

我想要的是完全控制正在发生的事情,所以我不想要任何第三方软件。

我目前的尝试对我来说似乎是合乎逻辑的,但由于依赖项生成无效,我有点卡住了。

为了更好的可读性,完整的 Makefile 被分成了小块。如果有任何需要改进的地方,我将不胜感激。

首先,我有以下静态定义

CXX = g++
CXXFLAGS = -Wall \
-Wextra \
-Wuninitialized \
-Wmissing-declarations \
-pedantic \
-O3 \
-p -g -pg
LDFLAGS = -p -g -pg
DEPFLAGS = -MM

Afaik 这应该没问题。将分析标志设为可选是完美的,但这并不重要。

SRC_DIR = ./src
OBJ_DIR = ./obj
SRC_EXT = .cpp
OBJ_EXT = .o

TARGET = ./bin/my_target

SRCS = $(wildcard $(SRC_DIR)/*$(SRC_EXT))
OBJS = $(subst $(SRC_DIR), $(OBJ_DIR), $(SRCS:$(SRC_EXT)=$(OBJ_EXT)))
DEP = depend.main

基本上,这应该只是从子文件夹 src 中提取所有 *.cpp 文件,并另外将 ./src 替换为 ./obj.cpp.o 作为对象的名称。

.PHONY: clean all depend

all: $(TARGET)

$(TARGET): $(OBJS)
@echo "-> linking $@"
@$(CXX) $^ $(LDFLAGS) -o $@

$(OBJ_DIR)/%.$(EXT_OBJ):
@echo "-> compiling $@"
@$(CXX) $(CXXFLAGS) -c $< -o $@

Afaik,这个 block - 如果存在有效的依赖文件 - 应该进行所有必要的编译和链接。

clean:
@echo "removing objects and main file"
@rm -f $(OBJS) $(TARGET)

应该是不言自明和正确的,还是我在这里遗漏了什么?

$(SRC_DIR)/%.$(SRC_EXT): 
$(CXX) $(DEPFLAGS) -MT \
"$(subst $(SRC_DIR),$(OBJ_DIR),$(subst $(SRC_EXT),$(OBJ_EXT),$@))" \
$(addprefix ,$@) >> $(DEP);

clear_dependencies:
@echo "-> (re-)building dependencies";
@$(RM) $(DEP)

depend: clear_dependencies $(SRCS)

这是非功能部分。我打算做的是使用 g++ 编译器标志 -MM 自动创建依赖项并使用 -MT 使用与默认一个。生成的依赖项应该如下所示

./obj/main.o: ./src/main.cpp ./src/some_header_file.h

不幸的是,这永远不会被调用,我不知道为什么会这样。在 similar question ,用户 Beta 很高兴地通过添加 .Phony 提供了一个临时解决方案,但这对重建每个对象没有任何改变有副作用。

最后只有一行

-include $(DEP)

包含依赖文件,一旦创建。

非常欢迎提供有关任何部分的一些提示的任何答案。所以我的问题是:我可以做些什么更好或者“更干净”,为什么依赖项生成不起作用?

最佳答案

开始吧。


分配 simply expanded variables在可能的情况下:

SRCS := $(wildcard $(SRC_DIR)/*$(SRC_EXT))

来自 GNU Make manual :

Another disadvantage [of recursively expanded variables] is that any functions referenced in the definition will be executed every time the variable is expanded. This makes make run slower; worse, it causes the wildcard and shell functions to give unpredictable results because you cannot easily control when they are called, or even how many times.


使用substitution referencespatsubst function将源转换为对象:

OBJS := $(SRCS:$(SRC_DIR)/%$(SRC_EXT)=$(OBJ_DIR)/%$(OBJ_EXT))

在编译模式规则中指定适当的先决条件。这是强制让 Make 保持您的目标文件最新并在源更改时更新它们。

$(OBJ_DIR)/%$(OBJ_EXT) : $(SRC_DIR)/%$(SRC_EXT)
@echo "-> compiling $@"
@$(CXX) $(CXXFLAGS) -o $@ -c $<

编译源代码并同时为它们生成依赖文件。使用 -MMD -MP 标志让事情正常进行(只需将它们附加到 CXXFLAGS)。

CXXFLAGS += -MMD -MP

-include $(OBJS:$(OBJ_EXT)=.d)

来自 GCC manual :

-MD

-MD is equivalent to -M -MF file, except that -E is not implied. The driver determines file based on whether an -o option is given. If it is, the driver uses its argument but with a suffix of .d, otherwise it takes the name of the input file, removes any directory components and suffix, and applies a .d suffix.

-MMD

Like -MD except mention only user header files, not system header files.

-MP

This option instructs CPP to add a phony target for each dependency other than the main file, causing each to depend on nothing. These dummy rules work around errors make gives if you remove header files without updating the Makefile to match.

也考虑学习this article Paul Smith 的(他是 GNU Make 的维护者)。它很好地概述了不同的 autodep 生成方法。

关于c++ - Makefile 改进,依赖生成不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10455480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com