Как связать библиотеку C ++ 17 stdc ++ fs с проектом CMake смешанного языка (C ++ и Fortran)? - PullRequest
3 голосов
/ 03 ноября 2019

Я пытаюсь добавить код на Фортране в мой проект C ++ с помощью CMake. В проекте без проблем используется библиотека файловой системы 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 (добавлен тест.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;
}

test.f90:

subroutine do_nothing()

end

командная строкаПозвоните:

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

Моя версия GCC 8.3.0.

1 Ответ

2 голосов
/ 04 ноября 2019

Это может быть следствием смешения разных версий компилятора. Вы переопределяете только компилятор C ++, но также и C и Fortran должны соответствовать ему. Я могу получить подобное сообщение об ошибке во время соединения, когда я использую gcc и gfortran из GCC 8.2, но g++ из GCC 9.2 (с 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 \
    ..
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...