如何将C++17 stdc++fs库链接到混合语言(C++和Fortran)CMake项目

How to link C++17 stdc++fs library to mixed language (C++ and Fortran) CMake project?

本文关键字:C++ Fortran 项目 CMake 语言 混合 C++17 stdc++fs 链接      更新时间:2023-10-16

我正试图用CMake将一些Fortran代码添加到我的C++项目中。该项目使用C++17文件系统库没有问题,直到我将这个Fortran文件添加到可执行文件中,这似乎破坏了链接器。我已经将这个问题简化为一个最小的例子,除了产生错误之外,没有其他功能。

原始CMakeLists.txt(编译良好(:

cmake_minimum_required( VERSION 3.10.2 )
enable_language( Fortran )
project( Minimal C CXX Fortran )
# Using C++17.
set( CMAKE_CXX_STANDARD 17 )
set( CMAKE_CXX_STANDARD_REQUIRED ON )
add_executable( Executable test.cpp )
target_link_libraries( Executable stdc++fs )

修改了CMakeLists.txt(添加了test.f90,不再编译(:

cmake_minimum_required( VERSION 3.10.2 )
enable_language( Fortran )
project( Minimal C CXX Fortran )
# Using C++17.
set( CMAKE_CXX_STANDARD 17 )
set( CMAKE_CXX_STANDARD_REQUIRED ON )
add_executable( Executable test.cpp test.f90 )
target_link_libraries( Executable stdc++fs )

后者编译/链接失败,出现以下错误(与前者省略target_link_libraries行时的错误相同(:

CMakeFiles/Minimal.dir/test.cpp.o: In function `std::filesystem::__cxx11::path::path<char [5], std::filesystem::__cxx11::path>(char const (&) [5], std::filesystem::__cxx11::path::format)':
test.cpp:(.text._ZNSt10filesystem7__cxx114pathC2IA5_cS1_EERKT_NS1_6formatE[_ZNSt10filesystem7__cxx114pathC5IA5_cS1_EERKT_NS1_6formatE]+0x6d): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
collect2: error: ld returned 1 exit status
CMakeFiles/Minimal.dir/build.make:120: recipe for target 'Minimal' failed
make[2]: *** [Minimal] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/Minimal.dir/all' failed
make[1]: *** [CMakeFiles/Minimal.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

为什么会发生这种情况,我该如何解决?我试过set_property( TARGET Executable PROPERTY LINK_LANGUAGE Fortran ),但没用。

add_library( TestLibrary test.f90 )
...
target_link_libraries( Executable TestLibrary )

也不起作用。非常感谢任何指导。

完整参考:

test.cpp:

#include <filesystem>
int main()
{
std::filesystem::path test ("test");
return EXIT_SUCCESS;
}

测试f90:

subroutine do_nothing()
end

命令行调用:

cmake -DCMAKE_CXX_COMPILER=g++-8 ..
make

我的GCC版本是8.3.0。

这很可能是不同编译器版本混合的结果。您只覆盖C++编译器,而且C和Fortran编译器也应该与之一致。当我使用GCC 8.2中的gccgfortran,但使用GCC 9.2中的g++(使用CMake 3.10.2(时,我能够在链接过程中收到类似的错误消息。

这是因为CMake从C编译器获得了一些重要的路径(比如查找运行库的默认目录(。但是,如果您使用不同的C++编译器编译C++代码,它会使用后者的头,从而导致不兼容。

您应该始终使用一致的编译器集;在这种情况下:

cmake 
-D CMAKE_C_COMPILER=gcc-8 
-D CMAKE_CXX_COMPILER=g++-8 
-D CMAKE_Fortran_COMPILER=gfortran-8 
..