【问题标题】:CMake + MSys2 undefined references to everything (including c++ runtime)CMake + MSys2 对所有内容的未定义引用(包括 c++ 运行时)
【发布时间】:2021-01-08 21:55:29
【问题描述】:

我正在开发一个跨平台的 C++ 项目。在 Linux 上一切正常,但在 Windows (10) + MSys2 上我遇到了一个奇怪的问题。编译工作正常(获取我的包含目录等),但链接失败,出现各种未定义的引用错误,指向我拥有的静态导入库,甚至是 C++ 运行时。

我试过设置 CMAKE_C[XX]_COMPILER、CMAKE_MAKE_PROGRAM,但是配置步骤的输出总是一样的:

$ cmake ..
-- The C compiler identification is GNU 10.2.0
-- The CXX compiler identification is GNU 10.2.0
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting C compiler ABI info
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /mingw64/bin/CC.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: <....>

如前所述,编译工作正常,但链接可执行文件失败了。这是我的最小工作示例:

$ cat ../CMakeLists.txt
project(example)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_executable(example
        main.cpp
)

这是一个输出示例(为简洁起见,其余部分省略):

C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.cpp.obj:main.cpp:(.text+0x51): undefined reference to `std::ios_base::Init::~Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.cpp.obj:main.cpp:(.text+0x81): undefined reference to `std::ios_base::Init::Init()'

在 cmake 中添加 -v 会产生以下命令。

编译:

/mingw64/bin/CC.exe   -std=gnu++17 -o CMakeFiles/example.dir/main.cpp.obj -c /home/.../Development/minex/main.cpp

链接:

/mingw64/bin/CC.exe CMakeFiles/example.dir/main.cpp.obj -o example

CC.exe 似乎关闭了......如果我设置了 CXX 编译器标志,它就会被使用......

我也尝试生成“MSYS2 Makefiles”,但也失败了(不知道生成器)。

我可以通过运行重现输出

$ CC main.cpp -o example

同时

$ g++ main.cpp -o example

工作正常。

CMake 版本为 3.18.4。

编辑:这是运行 make VERBOSE=1 的全部输出(使用 mingw64-cmake 似乎产生相同的输出,除了“进入目录”和“离开目录”路径是绝对 Windows 路径):

    $ cat log
/usr/bin/cmake.exe -S/home/<...>/Development/minex -B/home/<...>/Development/minex/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake.exe -E cmake_progress_start /home/<...>/Development/minex/build/CMakeFiles /home/<...>/Development/minex/build//CMakeFiles/progress.marks
make  -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/<...>/Development/minex/build'
make  -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/depend
make[2]: Entering directory '/home/<...>/Development/minex/build'
cd /home/<...>/Development/minex/build && /usr/bin/cmake.exe -E cmake_depends "Unix Makefiles" /home/<...>/Development/minex /home/<...>/Development/minex /home/<...>/Development/minex/build /home/<...>/Development/minex/build /home/<...>/Development/minex/build/CMakeFiles/example.dir/DependInfo.cmake --color=
Dependee "/home/<...>/Development/minex/build/CMakeFiles/example.dir/DependInfo.cmake" is newer than depender "/home/<...>/Development/minex/build/CMakeFiles/example.dir/depend.internal".
Dependee "/home/<...>/Development/minex/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/<...>/Development/minex/build/CMakeFiles/example.dir/depend.internal".
Scanning dependencies of target example
make[2]: Leaving directory '/home/<...>/Development/minex/build'
make  -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/build
make[2]: Entering directory '/home/<...>/Development/minex/build'
[ 50%] Building CXX object CMakeFiles/example.dir/main.obj
/mingw64/bin/CC.exe   -std=gnu++17 -o CMakeFiles/example.dir/main.obj -c /home/<...>/Development/minex/main.cpp
[100%] Linking CXX executable example
/usr/bin/cmake.exe -E cmake_link_script CMakeFiles/example.dir/link.txt --verbose=1
/mingw64/bin/CC.exe CMakeFiles/example.dir/main.obj -o example
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x23): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x32): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x51): undefined reference to `std::ios_base::Init::~Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.text+0x81): undefined reference to `std::ios_base::Init::Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_]+0x0): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/example.dir/main.obj:main.cpp:(.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0): undefined reference to `std::cout'
collect2.exe: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/example.dir/build.make:103: example] Error 1
make[2]: Leaving directory '/home/<...>/Development/minex/build'
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/example.dir/all] Error 2
make[1]: Leaving directory '/home/<...>/Development/minex/build'
make: *** [Makefile:103: all] Error 2

解决方案:

我设置 CMAKE_CXX_COMPILER 错误:/。我是凭记忆做的,我只是做了

CMAKE_CXX_COMPILER=... cmake ..

不是

cmake .. -DCMAKE_CXX_COMPILER=...

但是! 使用CC成功编译cpp文件还是很奇怪,但是无法链接目标文件。

【问题讨论】:

    标签: cmake mingw mingw-w64


    【解决方案1】:

    您遇到这些错误是因为您尝试使用 c 编译器编译/链接 c++ 程序。例如,您提到的两个未定义引用是 libstdc++ 的一部分。使用g++ 时默认使用它,但不使用CC。如果你想使用 CC,你必须手动添加它-lstdc++

    最简单的方法是使用g++编译和链接c++程序。

    由于某种原因,/mingw64/bin/CC.exe 被视为 CXX 编译器并跳过了工作检测。为避免跳过工作检测,您可以添加set(CMAKE_CXX_COMPILER_WORKS 1)。要修改它自己的编译器,您可以按照 CMAKE_CXX_COMPILER 中的说明设置 CMAKE_CXX_COMPILER 或按照 CXX 中的说明设置 CXX。小心清理缓存。

    【讨论】:

    • 是的,但是我如何说服 CMake 使用 g++,因为它忽略了 CMAKE_CXX_COMPILER 变量?我也尝试了 enable_language(CXX) ,结果相同...
    • 您可以添加ake VERBOSE=1 的输出以查看发生了什么吗?在我的带有 msys2 和 cmake 3.17.3 的电脑中,我看到使用了 c++,而不是使用与您相同的 cmakelist 的 cc。
    • 我将完整的构建日志添加到原始问题中。
    • 谢谢。原来我只是使用错误的方式设置 CMAKE_CXX_COMPILER,但是你的回答让我看了你提供的文档,所以它刷新了我的记忆。那我应该只为 mingw 提供一个工具链文件吗?
    • 是的,mingw 的工具链文件将是一个不错的选择。
    【解决方案2】:

    如果您在MSYS2 中使用mingw64 编译器,请确保您也使用cmakemingw64 版本。 使用不与 gcc 对齐的 cmake,例如:

    MINGW64
    # which gcc
    /mingw64/bin/gcc
    
    MINGW64
    # which cmake
    /usr/bin/cmake
    

    运行cmake时会导致如下错误:

    ...
    -- The CXX compiler identification is GNU 10.2.0
    System is unknown to cmake, create:
    Platform/MINGW64_NT-10.0-19041 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
    ...
    

    和构建步骤中的链接器错误。

    所以一定要安装mingw64版本的cmake:

    MINGW64
    pacman -S mingw-w64-x86_64-cmake
    

    安装 cmake 后需要关闭终端并再次打开。然后确保您安装了对齐的 gcc 和 cmake 版本:

    MINGW64
    # which gcc
    /mingw64/bin/gcc
    
    MINGW64
    # which cmake
    /mingw64/bin/cmake
    

    现在 cmake 应该可以正常工作了。

    【讨论】:

      猜你喜欢
      • 2014-04-25
      • 2020-01-10
      • 2013-12-01
      • 2021-06-14
      • 1970-01-01
      • 2012-07-01
      • 2012-09-20
      • 2020-10-30
      • 2023-04-05
      相关资源
      最近更新 更多