macOS 上的 GCC - 与自定义增强构建的动态链接失败

问题描述 投票:0回答:0

问题根源

我在 macOS 下的 CLion 中工作。我有一个使用 boost 库的项目。它是用 Homebrew 安装的。一切都工作得很好,但只有 clang 编译器。

当我尝试使用 GCC(与 Brew 一起安装)构建我的项目时,我最终得到了一堆未定义的引用:

Undefined symbols for architecture x86_64:
  "__ZN5boost15program_options11to_internalERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE", referenced from:
      __ZN5boost15program_options11to_internalINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEESt6vectorIS7_SaIS7_EERKS8_IT_SaISB_EE in options_parser.cpp.o
  "__ZN5boost15program_options19options_descriptionC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjj", referenced from:
      __ZN22command_line_options_tC2Ev in options_parser.cpp.o
      __ZN22command_line_options_tC1Ev in options_parser.cpp.o
  "__ZN5boost15program_options6detail7cmdlineC2ERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EE", referenced from:
      __ZN5boost15program_options25basic_command_line_parserIcEC1EiPKPKc in options_parser.cpp.o
  "__ZN5boost15program_optionslsERSoRKNS0_19options_descriptionE", referenced from:
      __ZN22command_line_options_t5parseEiPPc in options_parser.cpp.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

在寻找解决方案的路上。第 1 部分

我相信这是因为这些编译器的 ABI 不同。我想解决这个问题,因为我真的需要用两个编译器来构建我的项目。我决定使用 GCC 从源代码编译 boost 的第二个版本。一切正常,我安装了 GCC 构建的 boost 到

/usr/local/boost-1.81.0
.

安装后,我尝试再次使用 GCC 编译我的项目。它失败了,因为我使用 CMake 作为构建系统,默认情况下它会发现 Homebrew 安装了 boost。

CMake代码部分:

...
find_package(Boost 1.71.0 COMPONENTS program_options system REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} Boost::program_options Boost::system)
...

我通过在我的 CMake 配置文件中设置

BOOST_ROOT=/usr/local/boost-1.81.0/lib/cmake/Boost-1.81.0/
解决了这个问题。

在寻找解决方案的路上。第 2 部分

现在,一切都用 gcc 编译。但是有一个主要问题。当我尝试运行我的程序时,链接器给我一个错误,指出找不到符号,请参阅:

dyld[22954]: Symbol not found: __ZN5boost15program_options11to_internalERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
  Referenced from: <85A6D422-44D6-33CA-9638-632EA8C0103B> /Users/andrew/Documents/... (path hidden)
  Expected in:     <FC9A85A4-F878-30AA-AA7C-3BDE86D000BC> /usr/local/Cellar/boost/1.81.0_1/lib/libboost_program_options.dylib

我相信发生这种情况是因为它试图从安装的 Homebrew 加载 boost 动态库。我通过这条线知道这一点:

Expected in:     <FC9A85A4-F878-30AA-AA7C-3BDE86D000BC> /usr/local/Cellar/boost/1.81.0_1/lib/libboost_program_options.dylib

/usr/local/Cellar/boost/1.81.0_1/
是 Homebrew 的 boost 安装路径。我试图通过将
DYLD_LIBRARY_PATH
显式设置为我的自定义 boost 安装路径来解决这个问题,该路径包含使用 GCC 构建的动态库:

export DYLD_LIBRARY_PATH=/usr/local/boost-1.81.0/lib:$DYLD_LIBRARY_PATH          

再次,一切正常。

问题

这是我的问题:因为我不想每次都设置这个环境变量,有没有解决这个问题的方法,不涉及修改 CMakeLists.txt 或显式设置

DYLD_LIBRARY_PATH

我试过在互联网上搜索,但没有找到有用的东西。我不明白的是为什么链接器默认在 Homebrew 安装中搜索动态库,即使 CMake 在 GCC 安装的明确指定路径中找到 boost 库并将其链接到可执行文件

target_link_libraries(${PROJECT_NAME} Boost::program_options Boost::system)
?

澄清

我真的很想在不破坏系统或修改一些环境变量的情况下让这两个编译器都能工作。这对我来说非常不方便,因为我正在检查学生的实验室并且我必须使用不同的编译器构建很多。抱歉,如果我对问题的解释或我要实现的目标有点令人困惑。无论如何请随时问我。

macos gcc boost clion dynamic-linking
© www.soinside.com 2019 - 2024. All rights reserved.