我们有一个具有如下模块结构的项目:
- Project
- mod1
- mod1.cpp
- mod1.h
- main.cpp
- mod2
- mod2.cpp
- mod2.h
- main.cpp
- more modules
每个模块中的main.cpp文件实例化并测试该模块 . 一个模块可以包括并使用另一个模块 . 因此,例如,模块1可以包括模块2并且最终包括其他模块 .
我们想要创建一个makefile,它编译并包含正确的模块和main.cpp文件 . 因此,如果我写“make module2”,makefile将编译mod2.cpp,main.cpp(在模块2中)并包含mod2.h.如果我写“make module1”,makefile将编译mod2.cpp,mod1.cpp main.cpp(在模块1中)并包含mod1.h和mod2.h.
我对makefile的体验很谦虚,而且我已经用了几天没有成功 . 使其成为通用的将是更可取的,因此添加新模块不需要对makefile进行重大更改 .
我得到的最接近的解决方案是:
.PHONY: clean
FLAGS=-std=c++11 -g -I"$(SYSTEMC_PATH)/include" -I"$(SYSTEMC_PATH)" -L"$(SYSTEMC_PATH)/lib-linux64" -lsystemc $(addprefix -I, $(wildcard src/*))
SRCS_WITHOUT_MAIN= $(filter-out %main.cpp, $(shell find src -name '*.cpp'))
TARGET_OBJS=$(subst src, .build/obj, $(subst .cpp,.o,$(SRCS_WITHOUT_MAIN)))
all: $(filter-out unit_test, $(subst src/, ,$(wildcard src/*)))
.SECONDARY:
.build/obj/%.o: src/%.cpp
@mkdir -p $(shell dirname $@)
g++ $(FLAGS) $^ -c -o $@
clean:
@rm -r .build
%: $(TARGET_OBJS) .build/obj/%/main.o
@mkdir -p $(shell dirname .build/bin/$@)
g++ $(FLAGS) $^ -o .build/bin/$@
SRCS_WITHOUT_MAIN包含除主文件之外的所有模块的所有cpp文件 . TARGET_OBJS是对应文件的对应列表 . %目标匹配,例如“mod1”编译所有cpp文件和mod1的main.cpp .
问题是,我们偶尔会在编译后运行时遇到段错误,我们需要做一个“make clean && make”让它再次运行 . 有一天我用了4个小时来调试我的代码只是为了找出makefile是某种破坏 . 现在项目中的每个人都在使用“make clean && make”,因为害怕和我一样经历...
有谁知道一个聪明的方法来做到这一点?顺便说一句:这是一个SystemC项目 .
2 回答
这是一个原始但有效的makefile,它将完成这项工作:
注意:
它将所有目标文件(例如mod1.o)放在父目录中,这是我认为makefile所在的位置 .
它命名两个"main"目标文件"main1.o"和"main2.o" . 在同一个代码库中拥有两个具有相同名称的文件只会引发麻烦 .
可以进一步改进;这是为了简单而设计的 .
使用GNU make可能无法使用模式规则来匹配彼此依赖的模块名称的策略 . 来自GNU make 3.82手册(0.71版)
(我发现对此here的一些讨论 - 在以后的版本中可能会有所不同 . )
因此,如果module3依赖于module2,而module2依赖于module1,如果我们运行模式规则来构建module3,那么我们就不能使用相同的规则来构建module2 .
可以使用静态模式规则来解决此问题,其中指定了规则匹配的目标列表 . 我编辑了我的答案来使用它们 .
您可以根据您的问题调整以下内容 . 每个子目录都有许多“* .in”文件,当子目录构建时,会创建带有相应“* .out”文件的文件 . 模块本身相互依赖:在这种情况下,mod3取决于mod2,而mod2又取决于mod1 . 例如,更新文件“mod1 / file.in”,运行“make mod3”会导致重建mod1,mod2和mod3 .
.SECONDEXPANSION
目标并使用$$
而不是$
允许访问TARGET_OBJS
宏中的$@
变量 .要以不同的方式处理模块,无论它们是作为程序还是库构建,您可以有两个单独的规则,它们以不同的方式搜索它们的来源:
这将被调用,例如,“make mod3_AS_PROGRAM” .