【问题标题】:Can LNK4006 warnings be safely ignored in mixed Fortran/C++ solutions?在混合 Fortran/C++ 解决方案中可以安全地忽略 LNK4006 警告吗?
【发布时间】:2016-04-28 14:42:54
【问题描述】:

我们当前的解决方案是 Visual Studio 2013 中的混合 C++ Fortran 应用程序,每个应用程序大约有 40 个项目。

虽然我们可以很好地构建解决方案,但我们收到了大约 6000 个警告 - 其中绝大多数是 LNK4006 警告,其中一个函数正在“复制”:

warning LNK4006: _XXXXXXXXXXX@8 already defined in project1.lib(module1.obj); second definition ignored project2.lib(module1.obj)   

共同点是被复制的函数是在 Fortran 模块中定义的——其中许多只是 C++ 函数的接口:

MODULE mINTERFACES

USE ISO_C_BINDING

INTERFACE
    INTEGER(4) FUNCTION GetLastErrorCode [C, ALIAS: '_GetLastErrorCode'] (index)

        USE ISO_C_BINDING

        INTEGER(C_SIZE_T), INTENT(IN) :: index
    END FUNCTION GetLastErrorCode
END INTERFACE

END

由于这些模块在许多 Fortran 项目中使用,每个项目都有一个独立版本的接口函数 - 因此是重复的。

这一切都很有道理,但我的问题是:我可以忽略警告(即在项目配置中排除它们)吗?我看不到任何明显的方法来重组我们的代码以删除警告,我的印象是将这些接口放在一个模块中是一种很好的做法......

【问题讨论】:

  • [C, ALIAS: '_GetLastErrorCode'] 是什么语法?以及如何在 C++ 中定义函数?你用extern "C"吗?
  • 这是一个用于 C 互操作性的 Microsoft Powerstation 扩展。已经死了 20 年的编译器的语法与 Fortran 2003 的 ISO_C_BINDING 的组合正在引起我的注意。
  • Visual Studio 不附带 Fortran 编译器。您使用的是哪种特定的 Fortran 产品?这样的接口块应该只导致符号引用,而不是定义。从错误消息来看,您似乎在多个库中具有相同的目标代码 - 即您已编译 module1.f90 两次或更多次 - 是这种情况吗?
  • 这不仅仅是接口块——模块中还声明了其他函数及其主体,这些函数也会收到“重复”警告。
  • (我现在在英特尔论坛上也看到了这个问题。)您不应该将模块源代码包含在同一程序的多个项目中。这将创建多个定义,并且取决于其他细节,很可能是有问题的。一个项目应该单独编译模块的源代码,其他项目应该只引用编译的 mod 文件。在 Visual Studio 中的 Intel Fortran 集成中,通过让其他项目“依赖”具有模块源的项目,这很容易设置。

标签: c++ visual-studio linker fortran


【解决方案1】:

感谢所有在此线程中提出建设性意见的人 - 还要感谢在英特尔论坛线程 https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/628995 中提供帮助的 @IanH 和 Steve Lionel。

简而言之

(这是我自己的判断,没有其他人的判断)在这种特殊情况下,警告 是多余的,但是如果禁用它们,您将错过任何可能很重要的新警告。恕我直言,这意味着您不应禁用警告。

长答案

警告来自两个来源:

  1. 一个约定已经发展为使用模块来包含“全局”数据,但要通过与模块在相同文件中定义的“访问器函数”来访问它。这意味着当模块包含在许多不同的项目中时,访问器函数会被编译多次。
  2. 其中一些模块包含 C 接口块(这是一种很好的做法),但对于返回字符串的函数,使用的范例如 Creating a FORTRAN interface to a C function that returns a char* 中所述。虽然接口块本身没有发出重复警告,但将 C 指针转换为 Fortran 字符串的辅助函数却发出了警告。

解决方案可能是将所有这些访问器函数和辅助接口例程提取到单独的文件中,并且只编译一次,但这需要数周时间。

感谢@IanH,他指出您可以通过在单独的项目中定义所有模块来避免这种情况,然后(在 Visual Studio 中)将所有项目设置为依赖于这个新的“共享模块”项目(使用构建依赖项-> 项目依赖项)。现在编译时没有警告; VS 的“整个解决方案”搜索现在只找到每个例程一次;它可能编译得更快!总而言之,一场胜利。

【讨论】:

    猜你喜欢
    • 2011-07-12
    • 2017-04-14
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 2021-07-24
    相关资源
    最近更新 更多