【问题标题】:Makefile Mark Dependency, Compile and LinkMakefile 标记依赖、编译和链接
【发布时间】:2020-10-12 17:59:37
【问题描述】:

我有一个在 openmp 中完成的障碍的模块化实现。我有一个我想链接的测试工具。目录如下所示:

Project/
  -Tests
     -openmp_tournament
        -test_openmp_tournament.cpp
  -OpenMP
     -tournament.cpp .   //barrier implementation
     -tournament.h

现在,两个 .cpp 文件都在 Project/OpenMp/ 中包含了针对锦标赛.h 的标头。这个想法是编译两者,然后以模块化方式将它们链接在一起(因为我有各种我想测试的实现)。我的 makefile 看起来像这样:

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"

【问题讨论】:

    标签: c++ makefile linker


    【解决方案1】:

    为什么编译器找不到你的头文件?好吧,我们应该始终假设编译器是正确的,而您做错了什么:)。所以,看看有效的编译行:

    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 中没有源文件的任何目标文件。

    那么,如果您的规则不匹配怎么办?它将查看自己的内置规则,果然,有一个内置规则知道如何从当前目录中的源文件构建目标文件

    为什么会失败?它失败是因为您使用的是非标准变量,因此 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 选项...这取决于您是否要尝试梳理它)。

    【讨论】:

    • 如果这成为一个更大的项目,您可能还想看看这篇关于自动生成依赖项的替代/更好方法的帖子:make.mad-scientist.net/papers/…
    • 感谢您的精彩描述。我无法使用您的新规则编译它,但使用您应用的更改并使用 t%.o: $(PATH_TO_OPENMP)%.cpp %.d $(COMPILE_NOLINK) 我能够让它工作。但是,我确实必须注释掉 main 。链接时标记主文件是否有简单的解决方案? (提出一个愚蠢的问题)
    • 抱歉,我提供的答案与您发布的错误相符。如果您遇到不同的错误,请提出不同的问题并在此处提供完整的详细信息,包括命令行和错误消息、用于构建的规则等。您只能在所有源文件中拥有一个 main 实例你放入一个可执行文件,因为main 是操作系统决定如何启动你的程序的方式(它总是调用main 来启动你的程序......因此只能有一个)。
    猜你喜欢
    • 2012-11-19
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    相关资源
    最近更新 更多