【问题标题】:Hitting a LNK2019 error trying to link Boost with CMake尝试将 Boost 与 CMake 链接时遇到 LNK2019 错误
【发布时间】:2015-07-29 04:02:28
【问题描述】:

我正在制作我的第一个项目,它使用 CMake 构建系统。我还认为这是尝试将提升融入我的 C++ 技能的好时机。我已经阅读了文档并浏览了 SO 和其他网站,但我遇到了 LNK2019 错误。我读到here 这可能是由于 32/64 位项目/boost 库不匹配造成的。但是,我有理由相信我构建了正确的库。我会在下面贴出相关的cmake、代码、错误和命令

构建命令

b2.exe -a variant=debug,release link=shared,static threading=multi address-model=64

生成项目命令

cmake .. -G"Visual Studio 12 Win64"

CMake 文件

cmake_minimum_required (VERSION 2.6)
project (Thoth)

add_definitions( -DBOOST_ALL_NO_LIB )
set(Boost_USE_STATIC_LIBS OFF )
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)

configure_file (
  "${PROJECT_SOURCE_DIR}/main.h.in"
  "${PROJECT_BINARY_DIR}/main.h"
  )

set(BOOST_ROOT D:/Programs/boost_1_58_0)
set(BOOST_INCLUDEDIR ${BOOST_ROOT})
set(BOOST_LIBRARYDIR ${BOOST_ROOT}/stage/lib/)
find_package(Boost 1.58.0 COMPONENTS system filesystem REQUIRED)

include_directories("${PROJECT_BINARY_DIR}")

add_executable(Thoth main.cpp)

include_directories(${BOOST_INCLUDEDIR})
link_directories(${BOOST_LIBRARYDIR})

target_link_libraries( Thoth $(Boost_LIBRARIES))

C++ 文件

#define BOOST_LIB_DIAGNOSTIC

#include <iostream>
#include <fstream>
#include <string>
#include <boost/filesystem.hpp>

#include "main.h"

using namespace std;

int main(int argc, char *argv[]){
    string line;
    ifstream input("../images/source/balls2.nff", ios::in);
    if (!input){
        cout << "Unable to open file";
        exit(1);
    }
    else{
        while (getline(input, line)){
            cout << line << '\n';
        }

        input.close();
    }

    return 0;
}

Visual Studio 输出

------ Build started: Project: ZERO_CHECK, Configuration: Debug x64 ------
------ Build started: Project: Thoth, Configuration: Debug x64 ------
main.obj : error LNK2019: unresolved external symbol "class boost::system::error_category const & __cdecl boost::system::system_category(void)" (?system_category@system@boost@@YAAEBVerror_category@12@XZ) referenced in function "void __cdecl boost::system::`dynamic initializer for 'native_ecat''(void)" (??__Enative_ecat@system@boost@@YAXXZ)
main.obj : error LNK2019: unresolved external symbol "class boost::system::error_category const & __cdecl boost::system::generic_category(void)" (?generic_category@system@boost@@YAAEBVerror_category@12@XZ) referenced in function "void __cdecl boost::system::`dynamic initializer for 'errno_ecat''(void)" (??__Eerrno_ecat@system@boost@@YAXXZ)
C:\Users\JR\Documents\Visual Studio 2013\Projects\thoth\_build64\Debug\Thoth.exe : fatal error LNK1120: 2 unresolved externals
------ Skipped Build: Project: ALL_BUILD, Configuration: Debug x64 ------
Project not selected to build for this solution configuration 
========== Build: 1 succeeded, 1 failed, 0 up-to-date, 1 skipped ==========

希望我忽略了一些愚蠢的事情,但我一直在阅读其他人的答案,但一时没有任何进展。我想是时候寻求帮助了。

反馈后

我将在此处保留最新的 CMake 和调试输出。以便其他用户(或我)可以比较原始代码和最终代码。

CMake

cmake_minimum_required (VERSION 2.6)
project (Thoth)

set(Boost_USE_STATIC_LIBS OFF )
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)

configure_file (
  "${PROJECT_SOURCE_DIR}/main.h.in"
  "${PROJECT_BINARY_DIR}/main.h"
  )

set (Boost_DEBUG ON)
set(BOOST_ROOT D:/Programs/boost_1_58_0)
find_package(Boost 1.58.0 COMPONENTS system filesystem REQUIRED)
set(Boost_INCLUDE_DIRS ${BOOST_ROOT})
set(Boost_LIBRARY_DIRS ${BOOST_ROOT}/stage/lib/)
set(Boost_LIBRARIES ${BOOST_ROOT}/stage/lib/)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARIES})

include_directories("${PROJECT_BINARY_DIR}")

add_executable(Thoth main.cpp)

if (WIN32)
    add_definitions( -DBOOST_ALL_NO_LIB )
    add_definitions( -DBOOST_ALL_DYN_LINK )
endif()

target_link_libraries( Thoth $(Boost_LIBRARIES))

启用调试的 CMake 命令输出(删除 FindBoost 的完整路径以提高可读性)

cmake .. -G"Visual Studio 12 Win64"
-- [ FindBoost.cmake:513 ] _boost_TEST_VERSIONS =
-- [ FindBoost.cmake:515 ] Boost_USE_MULTITHREADED = ON
-- [ FindBoost.cmake:517 ] Boost_USE_STATIC_LIBS = OFF
-- [ FindBoost.cmake:519 ] Boost_USE_STATIC_RUNTIME = OFF
-- [ FindBoost.cmake:521 ] Boost_ADDITIONAL_VERSIONS =
-- [ FindBoost.cmake:523 ] Boost_NO_SYSTEM_PATHS =
-- [ FindBoost.cmake:575 ] Declared as CMake or Environmental Variables:
-- [ FindBoost.cmake:577 ]   BOOST_ROOT = D:/Programs/boost_1_58_0
-- [ FindBoost.cmake:579 ]   BOOST_INCLUDEDIR =
-- [ FindBoost.cmake:581 ]   BOOST_LIBRARYDIR =
-- [ FindBoost.cmake:583 ] _boost_TEST_VERSIONS =
-- [ FindBoost.cmake:652 ] Include debugging info:
-- [ FindBoost.cmake:654 ]   _boost_INCLUDE_SEARCH_DIRS =
D:/Programs/boost_1_58_0/include;D:/Programs/boost_1_58_0;PATHS;C:/boost/include;C:/boost;/sw/local/include
-- [ C:/Program Files (x86)/CMake/share/cmake-3.0/Modules/FindBoost.cmake:656 ]   _boost_PATH_SUFFIXES =
-- [ FindBoost.cmake:676 ] location of version.hpp: D:/Programs/boost_1_58_0/boost/version.hpp
-- [ FindBoost.cmake:700 ] version.hpp reveals boost 1.58.0
-- [ FindBoost.cmake:785 ] guessed _boost_COMPILER = -vc120
-- [ FindBoost.cmake:795 ] _boost_MULTITHREADED = -mt
-- [ FindBoost.cmake:838 ] _boost_RELEASE_ABI_TAG = -
-- [ FindBoost.cmake:840 ] _boost_DEBUG_ABI_TAG = -gd
-- [ FindBoost.cmake:888 ] _boost_LIBRARY_SEARCH_DIRS = D:/Programs/boost_1_58_0/lib;D:/Programs/boost_1_58_0/stage/lib;D:/Programs/boost_1_58_0/lib;D:/Programs/boost_1_58_0/../lib;D:/Programs/boost_1_58_0/stage/lib;PATHS;C:/boost/lib;C:/boost;/sw/local/lib
-- [ FindBoost.cmake:998 ] Searching for SYSTEM_LIBRARY_RELEASE: boost_system-vc120-mt-1_58;boost_system-vc120-mt;boost_system-mt-1_58;boost_system-mt;boost_system
-- [ FindBoost.cmake:1034 ] Searching for SYSTEM_LIBRARY_DEBUG: boost_system-vc120-mt-gd-1_58;boost_system-vc120-mt-gd;boost_system-mt-gd-1_58;boost_system-mt-gd;boost_system-mt;boost_system
-- [ FindBoost.cmake:998 ] Searching for FILESYSTEM_LIBRARY_RELEASE: boost_filesystem-vc120-mt-1_58;boost_filesystem-vc120-mt;boost_filesystem-mt-1_58;boost_filesystem-mt;boost_filesystem
-- [ FindBoost.cmake:1034 ] Searching for FILESYSTEM_LIBRARY_DEBUG: boost_filesystem-vc120-mt-gd-1_58;boost_filesystem-vc120-mt-gd;boost_filesystem-mt-gd-1_58;boost_filesystem-mt-gd;boost_filesystem-mt;boost_filesystem
-- [ FindBoost.cmake:1085 ] Boost_FOUND = 1
-- Boost version: 1.58.0
-- Found the following Boost libraries:
  --   system
  --   filesystem
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/JR/Documents/Visual Studio 2013/Projects/thoth/_build64

【问题讨论】:

  • 在 find_package(Boost) 之前设置变量 Boost_DEBUG 并验证 Boost_INCLUDE_DIRSBoost_LIBRARY_DIRSBoost_LIBRARIES 变量的打印值是预期的。顺便说一句,最好在find_package(Boost) 调用之后使用这些变量(以Boost_) 为前缀,而不是预先分配的变量(以BOOST_ 为前缀)。
  • 我尽我所能听从了您的建议。 (我还根据另一个 SO 用户的建议移动了我的添加定义)。我仍然收到 LNK2019 错误。通过查看调试输出,我发现它正在搜索权限目录。似乎找到了合适的 Boost 库。我的下一个假设是我误用了 LINK_DIRECTORIES 或 TARGET_LINK_LIBRARIES 命令。有什么想法吗?
  • 另外,关于设置 Boost_* 或 BOOST_* 变量,我看到其他 SO 用户使用其中任何一个,没有任何解释。将一个置于另一个之上的原因是什么?
  • BOOST_* 和 Boost_* 变量的区别在于第一个是find_package(Boost)输入参数,而第二个是输出。有时输出参数只是输入参数的副本,但并非总是如此。此外,使用输出参数不太容易出错:即使您决定将来不定义某些输入参数,输出参数仍然保持定义。在您的 After Feedback 变体中,output 变量被重置 after find_package - 这是不正确的,您应该使用 find_package 调用返回的变量。
  • 我发现Boost_DEBUG 不打印所有输出变量。虽然version.h 文件被正确找到,但最好检查输出变量的值,在我的第一条评论中列出:只需通过message(STATUS) 打印它们。

标签: c++ boost visual-studio-2013 cmake


【解决方案1】:

这里有两个相当琐碎的问题,希望很容易解决。

首先是find_package(Boost ...) 可能正确地完成了它的工作,即它为Boost_INCLUDE_DIRSBoost_LIBRARY_DIRSBoost_LIBRARIES 设置了良好的值。但是,您可以通过调用三个set 命令立即覆盖这些变量!所以你应该删除这三个命令。

另一个问题是在您的 target_link_libraries 调用中 - 您在尝试取消引用 Boost_LIBRARIES 时不小心使用了括号而不是大括号 - 即将 $(Boost_LIBRARIES) 更改为 ${Boost_LIBRARIES}


顺便说一句,还有一些与该问题无关的其他点:

  1. 您通常不应该像在 CMakeLists.txt 中那样设置 BOOST_ROOT。它实际上是通过在命令行(或通过 CMake GUI)上将其作为 -D arg 传递来设置的,这样它就不会被硬编码为特定于您自己机器的值。

  2. 您不需要link_directories 电话。它的own documentation 不鼓励使用它:

    请注意,很少需要此命令。 find_package()find_library() 返回的库位置是绝对路径。将这些绝对库文件路径直接传递给target_link_libraries() 命令。 CMake 将确保链接器找到它们。

【讨论】:

  • 我将您的标记为答案。由于……睡眠不足,我的定义也放错了地方(即文件末尾)?如果您不介意,我有两个后续问题。 1)查看帮助文件,我看到 -D 用于“创建 cmake 缓存条目”。我不确定如何完成设置 BOOST_ROOT。 2)我没有对此进行广泛的搜索,但我不得不将我需要的两个 dll 复制到带有我的 exe 文件的目录中。这方面的最佳做法是什么?
  • 1) 在命令行上,你会运行类似cmake . -DBOOST_ROOT=D:/Programs/boost_1_58_0 的东西。这将设置并缓存该值(类似于调用set(... CACHE ...) - 请参阅the docs)。 2)这是一个很大的话题!我自己的偏好总是通过使用静态库来避免 DLL Hell。看起来您已经在构建 Boost 库的静态版本 - 您只需通过将 Boost_USE_STATIC_LIBS 更改为 ON 来告诉 CMake 使用它们。
  • 太棒了!感谢您对第 2 点的建议。在第 1 点上,我太从字面上理解了(尝试设置 -D D:/path
猜你喜欢
  • 2015-11-23
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多