[英]Makefile Mark Dependency, Compile and Link
我有一个在 openmp 中完成的障碍的模块化实现。 我有一个我想链接的测试工具。 该目录如下所示:
Project/
-Tests
-openmp_tournament
-test_openmp_tournament.cpp
-OpenMP
-tournament.cpp . //barrier implementation
-tournament.h
现在,两个 .cpp 文件在 Project/OpenMp/ 中都有一个包含为比赛.h 的头文件。 这个想法是编译两者,然后以模块化方式将它们链接在一起(因为我有各种要测试的实现)。 我的生成文件如下所示:
PATH_TO_OPENMP = ../../OpenMP/
#OpenMP Flags Etc.
OMPFLAGS = -fopenmp -DLEVEL1_DCACHE_LINESIZE=`getconf LEVEL1_DCACHE_LINESIZE`
OMPLIBS = -lgomp
CC = g++
CPPFLAGS = -MMD -MP # enables automatic dependency tracking
CFLAGS = -Wall -Wextra -I$(PATH_TO_OPENMP) $(OMPFLAGS) -std=c++11
LDLIBS = $(OMPLIBS)
COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDLIBS) -o $@
COMPILE_NOLINK = $(CC) -c $(CPPFLAGS) $(CFLAGS) $< $(LDLIBS) -o $@
all: tournament_openmp.a
# link all files into one binary
tournament_openmp.a: tournament.o test_openmp_tournament.o
$(COMPILE)
# compile only each source file and mark as dependent
%.o: $(PATH_TO_OPENMP)%.cpp %.d
$(COMPILE_NOLINK)
# Empty pattern rule to match dependency (*.d) files (i.e. makefiles),
# so make won't fail if dependency doesn't exist
%.d: ;
# Mark dependency files as precious so they won't be deleted as intermediates
.PRECIOUS: %.d
# The list of all source files I want to track dependencies for
SOURCES=$(wildcard *.cpp)
# Include any dependency files that exist, and
# suppress error message for ones that don't yet (via hyphen)
-include $(SOURCES:.cpp=.d)
.PHONY: clean
clean:
rm -rf *.o *.d *.a *_openmp *_mpi
当我运行 Make 时,出现以下错误,我不确定如何解决它。 它找不到 test_openmp_tournament.cpp 文件的锦标赛.h:
a@ubuntu:~/Documents/Project/Tests/openmp_tournament$ make all
g++ -c -MMD -MP -Wall -Wextra -I../../OpenMP/ -fopenmp -DLEVEL1_DCACHE_LINESIZE=`getconf LEVEL1_DCACHE_LINESIZE` -std=c++11 ../../OpenMP/tournament.cpp -lgomp -o tournament.o
g++ -MMD -MP -c -o test_openmp_tournament.o test_openmp_tournament.cpp
test_openmp_tournament.cpp:51:10: fatal error: tournament.h: No such file or directory
51 | #include "tournament.h"
为什么编译器找不到你的头文件? 好吧,我们应该始终假设编译器是正确的,而您做错了 :)。 所以,看看有效的编译行:
g++ -c -MMD -MP -Wall -Wextra -I../../OpenMP/ -fopenmp ...
那么失败的那个:
g++ -MMD -MP -c ...
很明显为什么编译器找不到你的头文件,对吧? 因为,你没有给它正确的编译器标志。
那么问题来了,为什么 make 不运行我们期望的编译命令呢? make 这样做的唯一原因是它使用两个不同的规则来构建两个目标。 那么让我们来看看你的规则:
%.o: $(PATH_TO_OPENMP)%.cpp %.d
$(COMPILE_NOLINK)
好吧,这告诉 make 如何从文件../../OpenMP/xxx.cpp
为任何xxx
构建文件xxx.o
。 这对../../OpenMP
目录中的源文件../../OpenMP
,但当然这个规则不能用于构建../../OpenMP
没有源文件的任何目标文件。
那么,如果您的规则不匹配,该怎么办? 它将查看自己的内置规则,果然,有一个内置规则知道如何从当前目录中的源文件构建目标文件。
为什么这会失败? 它失败是因为您使用的是非标准变量,因此 make 使用的内置规则没有使用您的自定义变量。
特别是, CPPFLAGS
变量旨在保存 C/C++ 预处理器标志,因此从技术上讲-I
选项(这是一个预处理器选项)应该出现在该变量中。 其次,C++ 编译器的标准变量是CXX
用于编译器(不是CC
,它是 C 编译器)和CXXFLAGS
是标志(不是CFLAGS
,它是用于 C 编译器)。
因此,您应该至少执行以下一项操作,也可能同时执行两项操作:
将您的变量名称修复为标准名称:
CXX = g++
CPPFLAGS = -MMD -MP -I$(PATH_TO_OPENMP)
CXXFLAGS = -Wall -Wextra $(OMPFLAGS) -std=c++11
创建一个规则来构建本地对象而不是默认规则:
%.o: %.cpp %.d
$(COMPILE_NOLINK)
(精明会注意到OMPFLAGS
包含在其中的预处理标志以及:在-D
选项...你是否想尝试取笑说出来它是不是由你)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.