我有一个基于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
,则不会发生这种情况。这可以通过交换上面CMakeList中的文件main.cpp
和app.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_();
}
答案 0 :(得分:0)
我不知道cmake的工作原理,但我想您需要反过来做。 main可能是您的工具链中的特殊功能,并且不应存在于库中。
构建c lib时,它可能不会抱怨缺少外部组件,因为它是一个库,并非所有问题都需要解决。
此外,在app.cpp中,您需要记住的是,在Fortran中,被调用者将对参数进行堆栈,而在C中,调用者将对堆栈进行堆栈。
当被调用方拆栈时,您需要__stdcall作为声明的一部分。在较旧的MS编译器上,它以前是PASCAL。呼叫者取消堆叠后,可以选择添加__cdecl。