C++ CMake 构建错误“未定义的参考”

Posted

技术标签:

【中文标题】C++ CMake 构建错误“未定义的参考”【英文标题】:C++ CMake Build Errors "Undefined Reference" 【发布时间】:2018-04-13 17:14:43 【问题描述】:

我对 CMake 很陌生,我正在尝试使用 VS2017 和 WSL(Linux 子系统)构建一个跨平台的 c++ 项目。不幸的是,我仍在尝试了解 CMake 如何处理依赖项和链接,因此我遇到了很多“未解析的外部符号”和“未定义的对...的引用”错误。

为了更容易理解,我创建了以下项目,我可以在其中复制我遇到的错误类型。需要一些帮助来更好地了解如何配置 CMake。

注意:我刚刚在其中包含了 opencv 文件夹,以展示我如何尝试使用 CMake 包含外部依赖项,尽管在此示例中我并没有真正使用任何 opencv 代码。

/CMakeLists.txt
cmake_minimum_required(VERSION 3.9)

project(WslSample) set (CMAKE_CXX_STANDARD 11)

include_directories(
    $PROJECT_BINARY_DIR
    $PROJECT_SOURCE_DIR/ext/opencv/include )

add_subdirectory(src)
/src/CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project (SampleApp)
set (CMAKE_CXX_STANDARD 11)

file(GLOB_RECURSE SOURCES RELATIVE $PROJECT_SOURCE_DIR "src/*.cpp")
file(GLOB_RECURSE HEADERS RELATIVE $PROJECT_SOURCE_DIR "src/*.hpp")

add_executable($PROJECT_NAME main.cpp $HEADERS $SOURCES)
target_include_directories($PROJECT_NAME PUBLIC utils)
/src/main.cpp
#include <iostream>
#include <string>
#include <log.hpp>

int main()

    log(LEVEL_INFO, "Sample App running...");
    return 0;

/utils/log.hpp
#pragma once

typedef enum

    LEVEL_DEBUG = 0,
    LEVEL_INFO = 1,
    LEVEL_WARNING = 2,
    LEVEL_ERROR = 3,
 LogLevel;

void log(const LogLevel& level, const char* str);
/utils/log.cpp
#include <iostream>
#include <log.hpp>

std::string getLogStr(const LogLevel& level)

    switch (level)
    
    case LEVEL_INFO:
        return "INFO";
    case LEVEL_DEBUG:
        return "DEBUG";
    case LEVEL_ERROR:
        return "ERROR";
    case LEVEL_WARNING:
        return "WARNING";
    default:
        return "n/a";
    


void log(const LogLevel& level, const char* str) 
    std::cout << getLogStr(level) << " " << str << std::endl;

构建输出日志
18:06:55: Copying files to remote machine...
18:06:55: Finished copying files (elapsed time 00h:00m:00s:009ms).
cd '/var/tmp/build/3df28527-45dd-1335-b3fd-743d2a9ed7dd/build/Linux-Debug';/usr/local/bin/cmake --build "/var/tmp/build/3df28527-45dd-1335-b3fd-743d2a9ed7dd/build/Linux-Debug" --target SampleApp  ;

[ 50%] Linking CXX executable SampleApp
CMakeFiles/SampleApp.dir/main.cpp.o: In function `main':
/var/tmp/src/3df28527-45dd-1335-b3fd-743d2a9ed7dd/Linux-Debug/src/main.cpp:7: undefined reference to `log(LogLevel const&, char const*)'
collect2: error: ld returned 1 exit status
src/CMakeFiles/SampleApp.dir/build.make:94: recipe for target 'src/SampleApp' failed
make[3]: *** [src/SampleApp] Error 1
CMakeFiles/Makefile2:85: recipe for target 'src/CMakeFiles/SampleApp.dir/all' failed
make[2]: *** [src/CMakeFiles/SampleApp.dir/all] Error 2
CMakeFiles/Makefile2:97: recipe for target 'src/CMakeFiles/SampleApp.dir/rule' failed
make[1]: *** [src/CMakeFiles/SampleApp.dir/rule] Error 2
Makefile:118: recipe for target 'SampleApp' failed
make: *** [SampleApp] Error 2

Build failed.

【问题讨论】:

看起来您的 SOURCES 变量没有选择 /utils/log.cpp。试试打印出来(我喜欢用message(FATAL_ERROR "$SOURCES") @Justin 这确实是与我查找文件的方式有关的错误。您的提示对我的调试帮助很大。谢谢。 【参考方案1】:

发现问题...我查找文件的方式错误,并且我使用了错误的 CMake 变量。在此特定案例的解决方案下方:

/src/CMakeLists.txt

file(GLOB_RECURSE SOURCES RELATIVE $PROJECT_SOURCE_DIR "*.cpp")
file(GLOB_RECURSE HEADERS RELATIVE $PROJECT_SOURCE_DIR "*.hpp")

【讨论】:

以上是关于C++ CMake 构建错误“未定义的参考”的主要内容,如果未能解决你的问题,请参考以下文章

CMake:未定义的引用

使用 autotools 生成未定义的参考错误,而自定义 Makefile 工作正常

未定义的参考 yaml-cpp

在 CMake 项目中从 C++ 调用 C 代码。未定义的符号。有外部 C

带有 abi:cxx11 的 GCC 未定义引用

犰狳 lapack 和 blas 未定义的参考