Использование cmake для соединения C ++ и FORTRAN (mpif90) с iso_c_binding

Я пытаюсь написать CMakeLists.txt для подключения простой программы FORTRAN, которая вызывает функцию C ++ с использованием iso_c_binding. Когда я использую 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)

Буду признателен за любую помощь по этому вопросу.


person Vahid    schedule 07.08.2014    source источник
comment
Ничего не меняя, я могу скомпилировать и запустить этот код с помощью mpif90, но для меня это бесполезно, поскольку все повторяется в зависимости от количества используемых процессоров.   -  person Vahid    schedule 07.08.2014


Ответы (1)


Проблема в том, что вы нигде не ссылаетесь на MPI. Кроме того, установка CMAKE_Fortran_compiler вручную - неправильный способ сделать это, поскольку он вообще не переносится. Вот упрощенная версия того, что у меня есть в одном из моих проектов. Обратите внимание, что я использую модуль FindMPI, который поставляется с последними версиями cmake. Я не знаю, есть ли этот модуль в 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)
person user3919474    schedule 07.08.2014
comment
Извините, я думаю, что я изначально неправильно понял то, что вы хотели. Вы же хотите избавиться от MPI, а не включать его, верно. В этом случае, я думаю, ваша проблема в том, что вы не выполнили «очистку» перед перекомпиляцией, а просто забираете старые объекты, все еще ссылающиеся на mpi. - person user3919474; 07.08.2014
comment
Большое спасибо за ответ. Я изменил файл CMakeLists.txt на основе вашего, но теперь получаю сообщение об ошибке: main.f90:5: Error: Can't open included file 'mpif.h' - person Vahid; 07.08.2014
comment
Я только что видел твой комментарий. Собственно, каждый раз, когда я очищаю и даже удаляю все файлы, созданные cmake. Я хочу иметь возможность использовать MPI, поэтому ваш первый ответ соответствует тому, что я имел в виду. - person Vahid; 07.08.2014
comment
Хорошо, это странно. Файл "Mpif.h". не должны быть нужны, потому что вы зацементировали эту линию. - person user3919474; 10.08.2014
comment
Хорошо, поскольку вы хотите использовать MPI, вам следует добавить следующую строку в свой CmakeLists.t × t сразу после findpackage: include_directories ($ {MPI_Fortran_INCLUDE_DIRS}). Это должно решить вашу проблему. - person user3919474; 10.08.2014