Makefile:为每个包含的头自动编译源代码

时间:2018-01-15 15:37:41

标签: c++ c makefile automation

如果目标包含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

3 个答案:

答案 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))