Ошибка компоновщика при выполнении исполняемых ссылок C ++ в библиотеке Fortran и основной в библиотеке C ++ - PullRequest
3 голосов
/ 04 октября 2019

У меня есть проект на основе CMake, состоящий из трех целей:

  • Статическая библиотека FortLib, написанная на Фортране.
  • Статическая библиотека LibWithMain, написанная наC ++ и содержит определение int main().
  • Исполняемый файл App, который связывает обе вышеуказанные библиотеки.

Это содержимое CMakeList:

cmake_minimum_required(VERSION 3.7.2)
project(Mcve LANGUAGES C CXX Fortran)

add_library(FortLib STATIC fort.f90)
target_compile_options(FortLib PRIVATE /names:lowercase /assume:underscore /iface:cref)

add_library(LibWithMain STATIC main.cpp)

add_executable(App app.cpp)
target_link_libraries(App PRIVATE FortLib LibWithMain)

(Содержимое исходных файлов, которые можно использовать для воспроизведения проблемы, см. Ниже)

Моя проблема заключается в том, что связывание App приводит к следующей ошибке компоновщика:

libifcoremdd.lib(for_main.obj) : error LNK2019: unresolved external symbol MAIN__ referenced in function main

Обратите внимание, что эта ссылка взята из libifcoremdd.lib, библиотеки Intel Fortran, которая, очевидно, неявно связана с ней.

Этого не происходит, если определена функция mainпрямо в App. Это можно показать путем обмена файлами main.cpp и app.cpp в CMakeList выше (так что main определено внутри приложения). Тогда все строит и ссылки успешно. Тот факт, что определение main взято из LibWithMain, каким-то образом запутывает компоновщик.

В моем реальном коде LibWithMain - это Boost.Test, поэтому удаление основного из него не оченьвариант для меня.

Порядок статических библиотек не имеет значения: ошибка присутствует независимо от того, какая библиотека следует за какой на линии связи.

Мой набор инструментов - Visual Studio 2017 и IntelFortran 18, моей платформой является Win64 ("x64" в терминологии Visual Studio). На данный момент больше не требуется поддержка других компиляторов / платформ.

Я разработчик на C ++ и почти ничего не знаю о Fotran или экосистеме Intel Fortran, поэтому я понятия не имею, что может быть причиной этого или какреши это. Поэтому это мой вопрос:

Что вызывает ошибку компоновщика и как я могу ее исправить?


Эти простые файлы, используемые в CMakeList выше, достаточно, чтобы воспроизвести проблему:

fort.f90

integer function fortfunc
  implicit none
  fortfunc = 42
end function

main.cpp

#include <iostream>

int work();

int main()
{
  std::cout << work() << std::endl;
  return 0;
}

app.cpp

extern "C" int fortfunc_();

int work()
{
  return fortfunc_();
}

1 Ответ

0 голосов
/ 05 октября 2019

Я не знаю, как работает cmake, но я предполагаю, что вам нужно сделать это наоборот. Возможно, что main - это специальная функция в вашем наборе инструментов, и она не должна существовать в библиотеке.

  1. build the fortran lib
  2. build c lib без main (app.cpp)
  3. сборка основного с использованием c lib и fortran lib.

Вероятно, при сборке c lib не будет жаловаться на отсутствие внешних элементов, потому что это библиотека, и не все должно бытьresolved.

Кроме того, в app.cpp вам нужно помнить, что в Fortran вызываемый абонент развертывает аргументы, а в C вызывающий снимает стекинг.

Когда вызываемый абонент выполняет стекнужно __stdcall как часть декларации. Раньше это был extern PASCAL на старых компиляторах MS. Когда вызывающий абонент снимает стеки, вы можете добавить __cdecl.

...