Как повторно использовать модули Fortran без копирования исходного кода или создания библиотек
У меня проблемы с пониманием, если / как разделить код между несколькими проектами на Фортране без создания библиотек или дублирования исходного кода.
Я использую Eclipse/Photran с компилятором Intel (ifort) в системе Linux, но я полагаю, что у меня больше концептуальных проблем с модулями, чем с конкретными инструментами.
Вот простой пример: в ~/workspace/cow у меня есть исходный каталог (src), содержащий cow.f90 (ПРОГРАММА) и два модуля m_graze и m_moo в m_graze.f90 и m_moo.f90 соответственно. Этот проект правильно компилируется и создает ссылки для создания исполняемого файла "корова". Исполняемый файл и модули (m_graze.mod и m_moo.mod) хранятся в ~/workspace/cow / Debug, а объектные файлы хранятся в ~/workspace/cow / Debug / src
Позже я создаю ~ / workplace / sheep и в качестве программы используем src / sheep.f90, а в качестве модуля m_baa - src / m_baa.f90. Я хочу использовать только m_graze: ruminate в sheep.f90, чтобы получить доступ к подпрограмме ruminate (). Я мог бы просто скопировать m_graze.f90, но это может привести к нарушению синхронизации кода и не принимать во внимание любые зависимости, которые может иметь m_graze. По этим причинам я бы предпочел оставить m_graze в проекте коровы и скомпилировать и связать с ним sheep.f90.
Если я попытаюсь скомпилировать проект sheep, я получу ошибку вроде:
error #7002: Error in opening the compiled module file. Check INCLUDE paths. [M_GRAZE]
Под Свойства: Проект Ссылки для овец, я могу выбрать проект коровы. В разделе Свойства: Fortran Build: Настройки: Компилятор Intel: Препроцессор Я могу добавить ~/workspace/cow / Debug (расположение файлов модулей) в список включаемых каталогов, чтобы компилятор теперь нашел модули коровы и скомпилировал sheep.f90. Однако компоновщик умирает с чем-то вроде:
Building target: sheep
Invoking: Intel(R) Fortran Linker
ifort -L/home/me/workspace/cow/Debug -o "sheep" ./src/sheep.o
./src/sheep.o: In function `sheep':
/home/me/workspace/sheep/src/sheep.f90:11: undefined reference to `m_graze_mp_ruminate_'
Обычно это можно решить путем добавления библиотек и путей к библиотекам в настройках компоновщика, за исключением случаев, когда нет подходящих библиотек для ссылки (это Fortran, а не C.)
Проект cow прекрасно скомпилировал и связал cow.f90, m_graze.f90 и m_moo.f90 в исполняемый файл. Тем не менее, хотя проект sheep может скомпилировать sheep.f90 и m_baa.f90 и найти модуль m_graze.mod, он не может найти символы для m_graze, даже если для этого в системе имеется вся необходимая информация, необходимая для этого.,
Казалось бы, было бы легко сконфигурировать, чтобы заставить линкерную часть ifort найти недостающие фрагменты и собрать их вместе, но я понятия не имею, какие магические слова нужно ввести, где в пользовательском интерфейсе Photran, чтобы это произошло.
Я признаюсь в полном отсутствии интереса и компетентности в C и процессе сборки C, и я бы предпочел избежать отвлечения на создание библиотек (.a или.so), если только это не единственный способ заставить это работать.
В конечном счете, я ищу чистое решение этой проблемы на Фортране, чтобы я мог сохранить единственную копию исходного кода и не нуждаться в ручном обслуживании множества пользовательских Make-файлов.
Так можно ли это сделать?
Извинения, если это уже было где-то задокументировано; Google показывает только простые примеры сборки, как создавать модули и как связываться с существующими библиотеками. Кажется, нет (m) примеров повторного использования кода с модулями, которые не требуют дублирования исходного кода.
редактировать
Как указали респонденты, файлы.mod необходимы, но не достаточны; либо код объекта (в форме m_graze.o), либо статические или совместно используемые библиотеки должны быть указаны на этапе компоновки. Файлы.mod описывают интерфейс к объектному коду / библиотеке, но оба необходимы для создания окончательного исполняемого файла.
Для такой упрощенной игрушечной задачи, как эта, этого достаточно, чтобы ответить на поставленный вопрос.
В более крупном проекте с более сложными зависимостями (в моем случае 80+KLOC из F90, связанного с версией LAPACK95 для MKL), в IDE или инструментальной цепочке может не хватать достаточного количества автоматических средств или средств пользовательского интерфейса для совместного использования одного канонического набора исходных файлов. жизнеспособная стратегия. Похоже, что выбор заключается в том, чтобы не рисковать дублированием исходных файлов из-за синхронизации, отказаться от многих преимуществ IDE (то есть избежать ручного создания файлов make/CMake/SCons) или, по всей вероятности, и тем, и другим. Хотя система контроля версий и хорошая организация кода могут помочь, ясно, что совместное использование одного канонического набора исходных файлов между проектами нелегко, учитывая текущее состояние Eclipse.
2 ответа
Некоторые предыстории, о которых я подозреваю, вы уже знаете: обычно (включая ifort) компиляция исходного кода для модуля Fortran приводит к двум выводам - файлу "mod", который содержит описание сущностей Fortran, которые модуль определяет, что компилятор должен найти всякий раз, когда он видит оператор USE для модуля и объектный код для компоновщика, который реализует процедуры, хранение переменных и т. д., которые определяет модуль.
Ваша первая ошибка (та, которую вы решили) связана с тем, что компилятору не удалось найти файл мода.
Вторая ошибка связана с тем, что компоновщику не было сказано об объектном коде, который реализует то, что было в исходном файле с модулем. Я ни в коем случае не пользователь Eclipse, но способ грубой силы указать, что это просто добавить объектный файл (xxxxx/Debug/m_graze.o
) в качестве дополнительной опции компоновщика (Fortran Build > Настройки, в Intel Fortran Linker > Командная строка). (Другие цепочки инструментов имеют явные свойства "дополнительный объектный файл" для стадии связывания - вполне может быть лучший способ сделать это для цепочки Intel.)
Для более сложных примеров вы обычно создаете библиотеку из общего кода. Это не совсем специфично для C, единственный аспект Fortran заключается в том, что архив библиотек объектного кода должен быть предоставлен вместе с файлами мода, которые генерирует компилятор Fortran.
Да, код объекта должен быть предоставлен. Например, когда вы устанавливаете libnetcdf-dev в Debian (apt-get install libnetcdf-dev
), E сть /usr/include/netcdf.mod
файл, который включен.
Теперь вы можете использовать все процедуры netcdf в вашем коде Fortran. Например,
program main
use netcdf
...
end
но у вас будет ссылка на общую (или статическую) библиотеку netcdf, т.е.
gfortran -I/usr/include/ main.f90 -lnetcdff
Однако, как упомянул пользователь MSB, мод-файл может использовать только gfortran, поставляемый с дистрибутивом (apt-get install gfortran
). Если вы хотите использовать любой другой компилятор (даже другую версию, которую вы, возможно, установили самостоятельно), вам придется самостоятельно создавать netcdf с использованием этого конкретного компилятора.
Поэтому создание библиотеки не является плохим решением.