当Fortran库中的C ++可执行文件链接到C ++库中的main库时,链接器错误

时间:2019-10-04 14:26:58

标签: c++ cmake linker fortran intel

我有一个基于CMake的项目,包含三个目标:

  • 用Fortran编写的静态库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,则不会发生这种情况。这可以通过交换上面CMakeList中的文件main.cppapp.cpp来显示(以便在应用程序内部定义main)。然后,一切都建立并成功链接。事实是main的定义来自LibWithMain,从而使链接程序感到困惑。

在我的真实代码中,LibWithMain是Boost.Test,因此将main移出它并不是我的选择。

静态库的顺序无关紧要:无论哪个lib在链接行后面,都会出现错误。

我的工具链是Visual Studio 2017和Intel Fortran 18,我的平台是Win64(在Visual Studio术语中为“ x64”)。此时不需要其他编译器/平台。

我是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 :(得分:0)

我不知道cmake的工作原理,但我想您需要反过来做。 main可能是您的工具链中的特殊功能,并且不应存在于库中。

  1. 构建fortran库
  2. 不使用main(app.cpp)构建c库
  3. 同时使用c lib和fortran lib构建主版本。

构建c lib时,它可能不会抱怨缺少外部组件,因为它是一个库,并非所有问题都需要解决。

此外,在app.cpp中,您需要记住的是,在Fortran中,被调用者将对参数进行堆栈,而在C中,调用者将对堆栈进行堆栈。

当被调用方拆栈时,您需要__stdcall作为声明的一部分。在较旧的MS编译器上,它以前是PASCAL。呼叫者取消堆叠后,可以选择添加__cdecl。

相关问题