Как повторно использовать модули Fortran без копирования исходного кода или создания библиотек

У меня проблемы с пониманием того, можно ли / как использовать код в нескольких проектах 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.

Позже я создаю ~ / working / Sheep и использую src / Sheep.f90 в качестве программы и src / m_baa.f90 в качестве модуля m_baa. Я хочу «использовать m_graze, only: ruminate» в Sheng.f90, чтобы получить доступ к подпрограмме ruminate (). Я мог бы просто скопировать m_graze.f90, но это может привести к рассинхронизации кода и не принимать во внимание какие-либо зависимости, которые может иметь m_graze. По этим причинам я бы предпочел оставить m_graze в проекте cow и скомпилировать и связать с ним файл Sheets.f90.

Если я попытаюсь скомпилировать проект овцы, я получу ошибку вроде:

error #7002: Error in opening the compiled module file.  Check INCLUDE paths.   [M_GRAZE]

В разделе «Свойства: ссылки на проекты для овец» я могу выбрать проект «Корова». В разделе «Свойства: Fortran Build: Settings: Intel Compiler: Preprocessor» я могу добавить ~ / workspace / cow / Debug (расположение файлов модулей) в список включаемых каталогов, чтобы компилятор теперь находил модули cow и компилировал 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.f90 и m_baa.f90 и может найти модуль m_graze.mod, похоже, он не может найти символы для m_graze, хотя вся необходимая информация присутствует в системе для этого. .

Казалось бы, легко настроить компоновщик ifort, чтобы найти недостающие части и собрать их вместе, но я понятия не имею, какие волшебные слова нужно ввести, где в пользовательском интерфейсе Photran, чтобы это произошло.

Я признаю полное отсутствие интереса и компетентности в C и процессе сборки C, и я бы предпочел избежать отвлечения на создание библиотек (.a или .so), если только это не единственный способ заставить эту работу работать.

В конечном счете, я ищу решение этой проблемы на чистом языке Fortran, чтобы я мог сохранить единственную копию исходного кода и мне не приходилось вручную поддерживать кучу пользовательских файлов Makefile.

Так можно ли это сделать?

Приносим извинения, если это уже было где-то задокументировано; Google показывает мне только простые примеры сборки, как создавать модули и как связываться с существующими библиотеками. Кажется, нет (м) примеров повторного использования кода с модулями, которые не включают дублирование исходного кода.


Редактировать

Как отметили респонденты, файлы .mod необходимы, но недостаточны; либо объектный код (в форме m_graze.o), либо static или общие библиотеки должны быть указаны на этапе связывания. Файлы .mod описывают интерфейс объектного кода / библиотеки, но оба они необходимы для создания окончательного исполняемого файла.

Для такой упрощенной игрушечной задачи, как эта, этого достаточно, чтобы ответить на поставленный вопрос.

В более крупном проекте с более сложными зависимостями (в моем случае 80 + KLOC из F90, связанного с MKL-версией LAPACK95), IDE или инструментальной цепочке может не хватать достаточных средств автоматического или пользовательского интерфейса для совместного использования единого канонического набора исходных файлов. жизнеспособная стратегия. Выбор, по-видимому, стоит между риском рассинхронизации дублирующихся исходных файлов, отказом от многих преимуществ IDE (т. Е. Отказом от ручного создания файлов make / CMake / SCons) или, по всей вероятности, обоими способами. Хотя система контроля версий и хорошая организация кода могут помочь, ясно, что совместное использование единого канонического набора исходных файлов между проектами далеко не просто, учитывая текущее состояние Eclipse.


person arclight    schedule 03.05.2013    source источник
comment
Где вы связываете с m_graze.o?   -  person Vladimir F    schedule 03.05.2013
comment
Похоже, это ключ. Я не связываюсь явно с m_graze.o, и ни Photran, ни компоновщик, похоже, не могут упростить это, особенно если у m_graze много зависимостей. Не уверен, есть ли способ указать компоновщику искать здесь файлы * .o и ссылаться на то, что вам нужно, или вам нужно явно перечислить все зависимости. Если последнее, то это кажется ужасно утомительным.   -  person arclight    schedule 03.05.2013
comment
Я не могу помочь вам с проектами Photran, но могу порекомендовать SCons вместо make. У него очень хорошая поддержка Fortran, и его намного проще настроить, чем make. Он автоматически выполняет анализ зависимостей.   -  person Vladimir F    schedule 03.05.2013
comment
Я не уверен, в чем вопрос. Вам необходимо явно указать объектные файлы на этапе связывания. Если объектных файлов слишком много, поместите их в библиотеку (.a или .so). Эта часть не имеет ничего общего с C. Библиотеки - это просто контейнеры объектных файлов. Это то, что я обычно делаю для своих программ на Фортране + make. SCons тоже хорошо.   -  person milancurcic    schedule 03.05.2013


Ответы (2)


Некоторые предыстории, которые, как я подозреваю, вы уже знаете: обычно (включая ifort) компиляция исходного кода для модуля Fortran приводит к двум выходным данным - «файл мода», содержащий описание сущностей Fortran, которые модуль определяет компилятор необходимо найти всякий раз, когда он видит инструкцию USE для модуля и объектный код для компоновщика, который реализует процедуры, хранилище переменных и т. д., которые определяет модуль.

Ваша первая ошибка (та, которую вы решили) заключается в том, что компилятор не смог найти файл мода.

Вторая ошибка связана с тем, что компоновщику не сообщили об объектном коде, реализующем то, что было в исходном файле с модулем. Я ни в коем случае не являюсь пользователем Eclipse, но я могу указать это методом грубой силы, просто чтобы добавить объектный файл (xxxxx/Debug/m_graze.o) в качестве дополнительной опции компоновщика (Fortran Build> Settings, в Intel Fortran Linker> Command Line). (Другие цепочки инструментов имеют явные свойства «дополнительного объектного файла» для стадии связывания - вполне может быть лучший способ сделать это для цепочки Intel.)

Для более сложных примеров вы обычно создаете библиотеку из общего кода. Это не совсем C, единственный аспект Fortran - это то, что архив библиотек объектного кода должен быть предоставлен вместе с файлами мода, которые генерирует компилятор Fortran.

person IanH    schedule 03.05.2013
comment
Верно, поэтому по аналогии файлы .mod действуют как файлы заголовков C, описывая вызывающий интерфейс для промежуточного кода (объектные файлы и библиотеки). - person arclight; 04.05.2013
comment
Лучшей аналогией с заголовочными файлами C является исходный код Fortran, содержащий модуль. Компилятор создает из него файл .mod и использует его для выполнения своей работы, например, для проверки согласованности аргументов между вызовом и реальной процедурой. Файлы .mod зависят от компилятора и даже могут изменяться с версией компилятора ... в отличие от исходного кода, из которого они были созданы. Файлы .mod выходят за рамки языкового стандарта. - person M. S. B.; 04.05.2013
comment
Спасибо; это объясняет отсутствие общей документации по файлам .mod. Я многому научился, пытаясь решить этот вопрос, и ничто из этого не сулит ничего хорошего для надежной разработки программного обеспечения. Кажется, нет хорошего способа избежать дублирования исходных файлов в Eclipse (или, возможно, в любой IDE.): / - person arclight; 04.05.2013
comment
Я не знаю об аспектах IDE. Я использую модули Fortran между несколькими проектами и не дублирую файлы исходного кода. У меня просто несколько команд компиляции используют один и тот же файл. Что вы делаете с файлом заголовка C, используемым в нескольких проектах? - person M. S. B.; 04.05.2013
comment
Нет необходимости дублировать исходный код или даже этап компиляции. Вам просто нужно предоставить ссылку на каталог, содержащий файлы мода, и ссылку на объектные файлы. Если у вас есть несколько объектных файлов, объединение их в библиотеку упрощает это. mod файлы в некоторой степени эквивалентны предварительно скомпилированным файлам заголовков в C. - person IanH; 05.05.2013

Да, объектный код должен быть предоставлен. Например, когда вы устанавливаете libnetcdf-dev в Debian (apt-get install libnetcdf-dev), включается /usr/include/netcdf.mod файл.

Теперь вы можете использовать все процедуры netcdf в своем коде на Фортране. Например.,

program main
use netcdf
...
end 

но у вас будет ссылка на общую (или статическую) библиотеку netcdf, т.е.

gfortran -I/usr/include/ main.f90 -lnetcdff

Однако, как упомянул пользователь MSB, файл мода может использоваться только gfortran, входящим в состав дистрибутива (apt-get install gfortran). Если вы хотите использовать любой другой компилятор (даже другую версию, которую вы, возможно, установили самостоятельно), вам придется самостоятельно собрать netcdf, используя этот конкретный компилятор.

Так что создание библиотеки - неплохое решение.

person stali    schedule 04.05.2013