2013-03-20 3 views
1

Я работаю в проекте кода FORTRAN, где решения по сборке принимаются в двух файлах: файл заголовка (definitions.h), который входит в соответствующие файлы FORTRAN, и makefile. Например, в makefile выбраны компилятор, несколько наборов библиотек и разрешенная параллелизация (MPI, OpenMP или none), а включение некоторых частей кода контролируется директивами #define в заголовке.Сосуществование параметров Makefile и заголовков

  1. Мне не нравится редактировать два разных файла для настройки компиляции. Есть ли лучший подход?

  2. Кроме того, как файлы makefile, так и файлы definitions.h находятся под контролем редакции. Это означает, что мои неосторожные разработчики фиксируют и нажимают новые версии обоих файлов, где они только меняют параметры компиляции, поэтому загрязняют историю контроля версий. В идеале, по крайней мере, самый большой файл (makefile) не нужно будет редактировать, чтобы задать параметры компиляции.

  3. В некоторых случаях возникают несоответствия. Как правило, некоторые комбинации библиотек, выбранные в makefile, несовместимы с некоторыми разделами кода, выбранными директивами #define. Есть ли способ проверить это правильно?

    Например, для того, чтобы остановить компиляцию, если LIB1=LIBFOOmakefile) и bar определяется 1 (в заголовках файлов), я пытался следующий фрагмент кода в makefile

    ifeq ($(LIB1), LIBFOO) 
        bar_status:=`grep -i '^[[:space:]]*\#define[[:space:]]*bar[[:space:]]*[[:digit:]]' definitions.h | tail -n1 | grep -ic '^[[:space:]]*#define[[:space:]]*bar[[:space:]]*1[[:space:]]*'` 
    ifeq ($(bar_status), 1) 
        $(error ERROR: You are trying to compile the code with bar enabled in definitions.h, but this is incompatible with the library LIBFOO selected in the makefile) 
    endif 
    endif 
    

    но (а) это крайне уродливо, и (б) очевидно, что он вообще не работает. Как это можно зафиксировать?


Я работал на 3., и я думаю, что-то есть ответ на это: добавить новую .PHONY цель, ini_check, что является необходимым условием для других соответствующих целей, и читает

ifeq ($(LIB1), LIBFOO) 
    bar_value:=$(shell echo bar | cat definitions.h - | gcc -E -undef - 2>/dev/null | tail -n1) 
endif 

ini_check: 
ifeq ($(LIB1), LIBFOO) 
ifeq ($(bar_value), 1) 
    $(error ERROR: You are trying to compile the code with bar enabled in definitions.h, but this is incompatible with the library LIBFOO selected in the makefile) 
endif 
endif 
    @echo "Done with the initial check, starting compilation..." 

Обратите внимание, что теперь я использую препроцессор C, чтобы получить значение переменной bar после разбора заголовка.

+0

Я не знаю Фортран, поэтому я просто прокомментирую. Make может принимать параметры командной строки, чтобы определить некоторые из этих вариантов (или использовать наиболее часто используемые параметры по умолчанию). Если директивы '# define' несовместимы с некоторыми библиотеками, вы должны получить ошибки компилятора; если вы этого не сделаете, вы должны отредактировать библиотеки до тех пор, пока не сделаете это. – Beta

+0

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

ответ

0

Если это ваша политика для запуска сделать без флагов и аргументов, вы можете сэкономить некоторое горе, поставив соответствующие переключатели в качестве адъюнкт-файл (не под контролем версий), который Makefile будет include.

Анализ исходных файлов с помощью Make, как вы пытались сделать, как вы говорите, и уродливые, и сложные. И это кошмар для поддержания. Я рекомендую хранить две версии definitions.h под управлением версий в разных каталогах; та же самая логика Make, которая выбирает библиотеки, может выбрать файл заголовка.

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

И, наконец, если «несколько минут» слишком долго ждать такой ошибки компилятора, то вы должны делать такие ошибки довольно часто - вам может понадобиться изучить ваши процедуры. (Кроме того, если вы изменили только один или два файла, сборка не должна занимать так много времени - ежедневная сборка, да, но не та, которую вы делаете несколько раз в час.)

+0

Благодарим вас за ответ. Да, реализация полна плохих практик. – ripero

+0

Например, некоторые опции препроцессора в 'define.h' требовали компиляции OpenMP, но было возможно скомпилировать код с ними и без OpenMP включен в' makefile'. Кроме того, у нас было много подпрограмм вне любого модуля, и несколько модулей, которые мы использовали, использовались почти везде, поэтому добавление новой переменной, которая должна была быть разделена между несколькими подпрограммами, закончилась полной перекомпиляцией кода. Я начал перегруппировку кода, но geez, когда я пытался использовать разные варианты компиляции, я тратил слишком много времени на бессмысленные или неправильные! – ripero

Смежные вопросы