如果目标包含foo/bar.cpp
,我是否可以自动编译和链接#include "foo/bar.hpp"
来配置我的makefile?
详细信息:我有一个类似于以下项目的makefile:
src/
|-- program1/
| |-- main.cpp
| |-- makefile
|-- modules/
| |-- module1/
| | |-- foo.cpp
| | |-- foo.hpp
| |-- module1/
| | |-- bar.cpp
| | |-- bar.hpp
目前我的program1的makefile包含了它所使用的所有模块的所有* .cpp文件的列表,这些文件很难维护并且容易与我的包含保持同步。
但是,在我的代码中,遵循#include
命令将提供精确的依赖树。对于每个* .hpp,都需要编译和链接相应的* .cpp。
这个编译过程可以通过makefile自动化吗?可能自动依赖会帮助我吗?
有问题的makefile:
# compiler settings
CXX = g++
CXXFLAGS = -std=c++14
# object file generation path
tmpDir = .objs
# modules path
modPath = ../modules
# Names of modules and files to be compiled
names := \
main.o \
module1/foo.o \
module2/bar.o
# prepend tmpDir
names := $(addprefix $(tmpDir)/, $(names))
# Linking
main: $(names)
$(CXX) $(CXXFLAGS) -o main $^
# Rule for main file
$(tmpDir)/main.o: main.cpp
@mkdir -p $(tmpDir)
$(CXX) $(CXXFLAGS) -c main.cpp -o $@ -I "$(modPath)"
# rules for module files
$(tmpDir)/%.o: $(modPath)/%.cpp
mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -rf *.o main $(tmpDir)
我想避免手动设置names
。
答案 0 :(得分:1)
自动生成文件名的常用方法是使用$(wildcard ...)
或某些$(shell ...)
命令扫描目录。
根据您链接的Makefile
,我认为您可以使用GCC
跟踪-MMD -MP
标记的依赖项,如下所示:
# compiler settings
CXX = g++
# use flags to generate dependency files
CXXFLAGS = -std=c++14 -MMD -MP
# object file generation path
tmpDir = .objs
# modules path
modPath = ../modules
# Names of modules and files to be compiled
names := main.o
names += $(patsubst $(modPath)/%.cpp,%.o,$(shell find $(modPath) -iname "*.cpp"))
# prepend tmpDir
names := $(addprefix $(tmpDir)/, $(names))
# there should be a dep file for every object file
deps := $(patsubst %.o,%.d,$(names))
all: main
# Linking
main: $(names)
$(CXX) $(CXXFLAGS) -o main $^
# Rule for main file
$(tmpDir)/main.o: main.cpp
@mkdir -p $(tmpDir)
$(CXX) $(CXXFLAGS) -c main.cpp -o $@ -I "$(modPath)"
# rules for module files
$(tmpDir)/%.o: $(modPath)/%.cpp
mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) -c $< -o $@
# include the dependencies if they exist
-include $(deps)
clean:
rm -rf *.o main $(tmpDir) $(deps)
每个使用-MMD -MP
标志的编译命令都会生成一个与输出文件对应的依赖文件(扩展名为.d
除外)。
答案 1 :(得分:0)
regarding: *Currently my makefile for program1 contains a list of all the *.cpp files of all the modules it uses, which is kind of hard and error-prone to maintain and to keep in sync with my includes.
However, in my code, following the #include commands would provide an exact dependency-tree. For every *.hpp there is a corresponding *.cpp that I need to compile and link.
Can this process of compilation be automated via the makefile? May auto-dependencies help me out?*
In the makefile, you could use the output of a call to the find
command to obtain a list of all the (for instance) *.cpp files in the directories below the modules
directory rather than hard-coding the list.
答案 2 :(得分:0)
我稍微改进了Galik的答案。现在它的行为与我正在搜索的内容非常相似。
我没有手动定义names
,而是调用文件搜索。然后,结果将过滤以仅匹配具有相同名称的* .hpp文件的* .cpp文件。这会忽略包含测试的所有文件:
# find *.hpp files
names := $(shell find $(modPath) -iname "*.hpp")
# replace extension .hpp -> .cpp
names := $(patsubst %,%.cpp,$(basename $(names)))
# filter nonexistent *.cpp files
names := $(wildcard $(names))