CMake:如何使用LINK_INTERFACE_MULTIPLICITY?

Rau*_*ner 5 fortran cmake intel-mkl

链接到英特尔 MKL 静态库会引入循环依赖关系。当我导入库时,

set(LIBRARIES mkl_intel_lp64 mkl_sequential mkl_core)
foreach(_lib ${LIBRARIES})
  add_library(${_lib} UNKNOWN IMPORTED)
  set_target_properties(${_lib} PROPERTIES IMPORTED_LOCATION
    /opt/intel/mkl/lib/intel64/lib${_lib}.a)
endforeach()
Run Code Online (Sandbox Code Playgroud)

并链接到我的可执行文件,

target_link_libraries(main PRIVATE ${LIBRARIES})
Run Code Online (Sandbox Code Playgroud)

我得到了大量对线性代数调用的未定义引用。例如,

ztrevc3_gen.f:(.text+0x1af7): undefined reference to `mkl_blas_zdscal'
Run Code Online (Sandbox Code Playgroud)

解决这个问题的一种方法是使用适当的链接器标志:

target_link_libraries(main PRIVATE -Wl,--start-group ${LIBRARIES} -Wl,--end-group)
Run Code Online (Sandbox Code Playgroud)

另一种选择是这样做:

target_link_libraries(main PRIVATE ${LIBRARIES} ${LIBRARIES} ${LIBRARIES})
Run Code Online (Sandbox Code Playgroud)

然而,当我寻找更优雅的解决方案时,我发现了该LINK_INTERFACE_MULTIPLICITY属性。如果将此属性与导入的库位置一起设置,

set(LIBRARIES mkl_intel_lp64 mkl_sequential mkl_core)
foreach(_lib ${LIBRARIES})
  add_library(${_lib} UNKNOWN IMPORTED)
  set_target_properties(${_lib} PROPERTIES IMPORTED_LOCATION
    /opt/intel/mkl/lib/intel64/lib${_lib}.a
    LINK_INTERFACE_MULTIPLICITY 3)
endforeach()
Run Code Online (Sandbox Code Playgroud)

我得到了与以前相同的未定义引用,所以看来这不起作用。使用 LINK_INTERFACE_MULTIPLICITY 的正确方法是什么?是否有更优雅的方法来解决循环依赖?

编辑

这是一个失败的最小示例,这次使用了正确的IMPORTED_LINK_INTERFACE_MULTIPLICITY变量。

# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(test Fortran)
add_executable(main main.f90)
set(LIBRARIES mkl_intel_lp64 mkl_sequential mkl_core)
foreach(_lib ${LIBRARIES})
  add_library(${_lib} UNKNOWN IMPORTED)
  set_target_properties(${_lib} PROPERTIES IMPORTED_LOCATION
    /opt/intel/mkl/lib/intel64/lib${_lib}.a
    IMPORTED_LINK_INTERFACE_MULTIPLICITY 3)
endforeach()
list(APPEND LIBRARIES dl pthread)
target_link_libraries(main ${LIBRARIES})
#target_link_libraries(main ${LIBRARIES} ${LIBRARIES} ${LIBRARIES})

# main.f90
  call zpotrf
end program
Run Code Online (Sandbox Code Playgroud)

如果取消最后一行的注释,则构建成功。不幸的是,MKL 不是免费的(某些情况除外),但希望有人可以对此进行测试。我应该注意到,它会因某些线性代数调用而失败,而不会因其他调用而失败,例如dgemm.

Tsy*_*rev 0

属性LINK_INTERFACE_MULTIPLICITY适用于“普通”静态库。对于IMPORTED库,应使用IMPORTED_LINK_INTERFACE_MULTIPLICITY属性:

  set_target_properties(${_lib} PROPERTIES
    IMPORTED_LOCATION /opt/intel/mkl/lib/intel64/lib${_lib}.a
    IMPORTED_LINK_INTERFACE_MULTIPLICITY 3)
Run Code Online (Sandbox Code Playgroud)