Параллельная сборка 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) в директории, предназначенные для конкретных целей, чтобы они не перезаписывались и не удалялись другими целями. Это решило бы мою проблему, даже если это потребовало бы больше компиляции, чем необходимо. Я понятия не имею, как выполнить какой-либо из вариантов, поэтому приветствуется любая подсказка или альтернативное решение.
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()).