Ответ 1
Ваша попытка использовать известный рецепт строчки препроцессора С, а именно:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
не удается по двум причинам, каждый из которых достаточен сам по себе.
Первый и самый простой, исходный файл, в котором вы пытаетесь использовать его, по-видимому,
имеет расширение .f90
. Что это расширение означает gfortran
(и
драйвер компилятора GCC, любым другим именем): Свободный формат исходного кода Fortran, который не должен быть предварительно обработан.
Аналогично .f95
, .f03
и .f08
. Если вы хотите gfortran
сделать вывод, что источник
файл содержит свободную форму кода Fortran, который должен быть предварительно обработан, дать ему один из
расширения .f90
, .f95
, .f03
или .f08
. См. документацию GCC о
эти пункты
Однако, если вы делаете эту простую вещь, вторая причина укусов.
Использование препроцессора C для препроцессора источника Fortran является таким же старым, как C
(который, хотя старый, намного моложе Фортрана). gfortran
обязан не
разрушить древний рабочий код; поэтому, когда он вызывает препроцессор С,
он вызывает его в традиционном режиме. Традиционный режим препроцессора C
это способ, которым препроцессор вел себя до первой стандартизации
языка C (1989), поскольку это нестандартное поведение может быть закреплено. В традиционных
режиме, препроцессор не распознает оператор стробирования '#', который был
введенный первым стандартом C. Вы можете проверить это, вызвав препроцессор
прямо как:
cpp -traditional test.c
где test.c
содержит некоторую попытку использовать рецепт строения.
попытка не удалась.
Вы не можете самостоятельно коаксировать gfortran
для работы рецепта строения.
Но есть обходное решение. Вы можете напрямую ссылаться на cpp
, не обремененный традиционным режимом,
для предварительной обработки источника Fortran, в котором вы хотите выполнить стрификацию, и передать ее
выводить на gfortran
. Если вы уже знаете это и искали a gfortran
-alone
вам не нужно читать дальше.
Выполнение строкой в вашем тестовом источнике будет выглядеть так:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' '-DMYMACRO=STRINGIFY(hello)' test.f90
Результат:
# 1 "test.f90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.f90"
program test
implicit none
character (len=:), allocatable :: astring
astring = "hello"
write (*, *) astring
end program test
И этот вывод - это то, что вы хотите скомпилировать. Вы также можете выполнить это:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 > /tmp/test.f90 \
&& gfortran -o test /tmp/test.f90
Затем вы обнаружите, что существует ./test
, и что его выполнение выводит hello
.
Вы можете удалить промежуточный временный файл с дальнейшим уточнением. Ваш источник F90
код будет компилироваться как F95, так как последний является консервативным из первых. Таким образом, вы можете
преимущество того, что GCC будет компилировать исходный код на стандартный вход, если
вы говорите, какой язык вы используете, используя его опцию -x
.
Набранные диалекты Fortran, которые вы можете указать таким образом, это f77
, f77-cpp-input
, f95
и f95-cpp-input
, где префикс -cpp-input
означает, что
источник должен быть предварительно обработан, а его отсутствие означает, что это не так. Таким образом,
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 | gfortran -x f95 -o test -
работает так же, как и предыдущее решение, за вычетом временного файла и испускает безобидное предупреждение:
Warning: Reading file '<stdin>' as free form
(Запомните и сохраните окончательный -
в командной строке. Это то, что сообщает gfortran
скомпилируйте стандартный ввод.). Значение -x f95
приводит к дополнительному
экономика, что источник, который предварительно обрабатывается cpp
, не обрабатывается предварительно
снова компилятором.
Использование опции -std=c89
при вызове cpp
вызывает предостережение
объяснение. Это приводит к тому, что cpp
соответствует самому раннему стандарту C.
Это близко к -traditional
, как мы можем получить, все еще пользуясь
#
-оператор, от которого зависит рецепт строения, но с этим вы обнимаете
возможность взломать некоторый код Fortran, если вы его предварительно обработаете;
иначе gfortran
сам не обеспечивал бы -traditional
. В случае
ваша тестовая программа, вы можете спокойно опустить -std=c89
, позволяя cpp
соответствовать
к стандарту C по умолчанию, когда он был построен. Но если вы разрешаете или направляете это
для соответствия -std=c99
или более позднему, тогда стандарт будет выдавать мандат
из //
в качестве начала однострочного комментария (согласно С++), с помощью которого любая строка
Fortran, который содержит оператор конкатенации, будет усечен на
первое вхождение.
Естественно, если вы используете make
или другую систему сборки для создания
код, в котором вы хотите получить строчные макросы, у вас будет способ сообщить
система сборки, какие действия составляют компиляцию определенного класса компилируемых
файлы. Для любого исходного файла Fortran fsrc
, который вы хотите скомпилировать с помощью
преамбула стробирования, действия для указания будут в вене:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' fsrc.f90 | gfortran -x f95 -c -o fsrc.o -