Параллельная сборка CMake для Fortran-90 + с модулями

У меня проблема со сборкой нескольких исполняемых файлов Fortran-90 + с использованием CMake, когда я использую модули Fortran, которые используются всеми исполняемыми файлами, и строю параллельно с использованием make -j. Проблема, похоже, в том, что скомпилированные объектные файлы помещаются в разные подкаталоги для каждой цели, CMakeFiles/targetName.dir/src/file.f90.o, в то время как файлы модулей помещаются в один и тот же каталог для каждой цели (я могу изменить этот каталог, установив Fortran_MODULE_DIRECTORY, но он все равно будет тот же каталог для всех файлов модуля). Проблема в том, что все цели начинают писать эти файлы модулей параллельно, и я получаю Fatal Error: Can't rename module file 'module.mod0' to 'module.mod': No such file or directory при использовании gfortran (который, по-видимому, создает файл .mod0, а затем переименовывает его в .mod). Проблема не возникает, когда я запускаю make без опции -j (серийная сборка).

Я вижу два решения, но не знаю, как их реализовать. Во-первых, поместите объектные файлы для всех целей в один и тот же каталог, а не в каталоги для конкретных целей. Это может быть предпочтительным вариантом, поскольку мне не придется компилировать общие исходные файлы N раз для N целей. Затем процесс make распознает, что объектные файлы существуют, и больше не компилирует соответствующие исходные файлы, следовательно, не затрагивая файлы .mod (0) снова (мне может потребоваться сделать все следующие цели зависимыми от первого).

Второе решение - поместить файлы .mod (0) в целевые каталоги, чтобы они не перезаписывались или не удалялись другими целевыми объектами. Это решило бы мою проблему, даже если для этого потребуется больше компиляции, чем необходимо. Я понятия не имею, как реализовать любой из вариантов, поэтому любые подсказки или альтернативные решения приветствуются.


person AstroFloyd    schedule 19.04.2015    source источник


Ответы (1)


Ответ, который я искал, был дан в комментариях к вопросу @RaulLaasner:

Я бы создал дополнительную цель в виде основной библиотеки соответствующих исходных файлов, которую затем можно было бы связать со всеми исполняемыми файлами. Это должно работать параллельно. Файлы мода все еще можно поместить в один каталог.

Я использовал add_library() и target_link_libraries(), чтобы добиться этого.

Обратите внимание, что, например, Скрипты Gentoo ebuild добавляют --as-needed в компоновщик, что может вызвать неопределенные ссылки в вашей основной библиотеке, когда вы связываете ее с внешними библиотеками для формирования исполняемого файла. Чтобы предотвратить это, убедитесь, что вы сначала связали внешние библиотеки с вашей основной библиотекой. С этой целью мой CMakeListst.txt содержит:

add_library( "Core" STATIC src/functions.f90 src/routines.f90 )  # creates libCore.a
target_link_libraries( Core ${EXTERNAL_LIBRARIES} )              # link external libraries to libCore.a
...
add_executable( myProgram1 src/myProgram1.f90 )                  # creates the first executable
target_link_libraries( myProgram1 Core )                         # links libCore.a to myProgram1 

Последние две строки можно повторить для создания других исполняемых файлов (например, с помощью foreach ()).

person AstroFloyd    schedule 24.04.2015