【问题标题】:Using cmake for coupling C++ and FORTRAN (mpif90) with iso_c_binding使用 cmake 将 C++ 和 FORTRAN (mpif90) 与 iso_c_binding 耦合
【发布时间】:2014-10-01 00:05:53
【问题描述】:

我正在尝试编写 CMakeLists.txt 来耦合一个简单的 FORTRAN 程序,该程序使用 iso_c_binding 调用 C++ 函数。当我使用 gfortran 作为 FORTRAN 编译器时,代码运行良好,但是当我切换到 openMPI (mpif90) 而不是 gfortran 时,我得到了错误:

CMakeFiles/test.exe.dir/main.f90.o: In function `MAIN__':
main.f90:(.text+0x2d): undefined reference to `mpi_init_'
main.f90:(.text+0x47): undefined reference to `mpi_comm_size_'
main.f90:(.text+0x61): undefined reference to `mpi_comm_rank_'
main.f90:(.text+0x1c3): undefined reference to `mpi_finalize_'
collect2: ld returned 1 exit status
make[2]: *** [test.exe] Error 1
make[1]: *** [CMakeFiles/test.exe.dir/all] Error 2
make: *** [all] Error 2

我附上了 gfortran 版本(工作)。为了切换到 mpif90,我只是取消注释 main.f90 中的注释行:

program main
   use iso_c_binding
   implicit none
!   include 'mpif.h'

   interface
      function func (n,x) bind (C, name="func")
         import
         integer(c_int):: func
         integer(c_int):: n
         real(c_double), dimension(1:n), intent(in):: x
      end function func
   end interface

   integer(c_int):: n
   real(c_double), dimension(:), allocatable:: x
   integer(c_int):: result
!   integer, parameter:: master = 0
!   integer:: numtasks, taskid, ierr, dest
!   integer  status(mpi_status_size)

!   call mpi_init(ierr)
!   call mpi_comm_size(mpi_comm_world, numtasks, ierr)
!   call mpi_comm_rank(mpi_comm_world, taskid, ierr)
!   if (taskid .eq. master) then
      n = 3
      allocate(x(1:n))
      x = (/1., 2., 3./)
      result = func(n,x)
      deallocate(x)
!   end if
!   call mpi_finalize(ierr)
end program main

func.c:

#include <iostream>
using namespace std;
#ifdef __cplusplus
  extern"C" {
#endif
int func(int& n, double x[]) {
   std::cout << x[0] << "  " << x[1] << "  " << x[2] << std::endl;
   return 0;
}
#ifdef __cplusplus
  }
#endif

CMakeLists.txt:

PROJECT(test)
cmake_minimum_required(VERSION 2.6)
enable_language(C Fortran)
# -------------------------
# Setting the compilers
# -------------------------
#set (CMAKE_Fortran_COMPILER /usr/local/openmpi/bin/mpif90)
set (CMAKE_Fortran_COMPILER /usr/bin/gfortran)
set (CMAKE_C_COMPILER /usr/bin/g++)
# -------------------------
# Setting the flags
# -------------------------
set_source_files_properties(main.f90 func.cpp PROPERTIES COMPILE_FLAGS "-c -lstdc++")
# -------------------------
# Making the executable
# -------------------------
ADD_EXECUTABLE(test.exe main.f90 func.cpp)

我将不胜感激有关此问题的任何帮助。

【问题讨论】:

  • 在不做任何改变的情况下,我可以使用 mpif90 编译和运行这段代码,但这对我来说没用,因为所有内容都会根据使用的 CPU 数量重复。

标签: c++ cmake fortran openmpi fortran-iso-c-binding


【解决方案1】:

问题是您没有在任何地方链接到 MPI。 此外,手动设置 CMAKE_Fortran_compiler 是错误的方法,因为它根本不可移植。这是我在一个项目中的简化版本。 请注意,我使用的是最新版本的 cmake 附带的 FindMPI 模块。我不知道cmake 2.6版是否有那个模块,但是你可以很容易地在网上找到它。

cmake_minimum_required (VERSION 2.8)
project(DYNAMO Fortran C)
find_package(MPI REQUIRED)
set(DYNAMO_LINK_LIBRARIES ${MPI_Fortran_LIBRARIES})
set(DYNAMO_SRCS main.f90)
add_executable(dynamo ${DYNAMO_SRCS})
set_target_properties(dynamo PROPERTIES COMPILE_FLAGS "${MPI_Fortran_COMPILE_FLAGS}")
set_target_properties(dynamo PROPERTIES LINK_FLAGS "${MPI_Fortran_LINK_FLAGS}")
target_link_libraries(dynamo ${DYNAMO_LINK_LIBRARIES})
install(TARGETS dynamo RUNTIME DESTINATION bin)

【讨论】:

  • 对不起,我想我一开始就误解了你想要的东西。你想要的是摆脱 MPI,而不是包含它,对吧。在这种情况下,我认为您的问题是您在重新编译之前没有执行“make clean”,而只是拾取仍然引用 mpi 的旧对象。
  • 非常感谢您的回复。我已经根据您的修改了 CMakeLists.txt,但现在出现错误:main.f90:5: Error: Can't open included file 'mpif.h'
  • 我刚看到你的评论。实际上,每次我做清理,甚至删除所有由cmake创建的文件。我希望能够使用 MPI,所以你的第一个答案就是我的意思。
  • 好吧,这很奇怪。文件'Mpif.h'。应该不需要,因为你巩固了那条线。
  • 好的,因为你想使用 MPI,你应该在你的 CmakeLists.t×t 后面添加下面的行:include_directories (${MPI_Fortran_INCLUDE_DIRS})。这应该可以解决您的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 1970-01-01
  • 2014-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多