Spec-Zone.ru › GCC 12

3.20 Определение подпроцессов и переключателей, передаваемых им

gcc — это программа-драйвер. Она выполняет свою работу, вызывая последовательность других программ для выполнения задач компиляции, сборки и компоновки. GCC интерпретирует параметры командной строки и использует их для определения, какие программы следует вызвать и какие параметры командной строки следует поместить в их командные строки. Это поведение контролируется *строками спецификаций*. В большинстве случаев для каждой программы, которую может вызвать GCC, существует одна строка спецификаций, но некоторые программы имеют несколько строк спецификаций для управления их поведением. Строки спецификаций, встроенные в GCC, могут быть переопределены с помощью переключателя командной строки -specs= для указания файла спецификаций.

Файлы спецификаций — это обычные текстовые файлы, используемые для создания строк спецификаций. Они состоят из последовательности директив, разделённых пустыми строками. Тип директивы определяется первым символом, отличным от пробела, в строке, который может быть одним из следующих:

%command

Вызывает команду в обработчик файла спецификаций. Команды, которые могут здесь появиться:

%include <file>

Ищет файл и вставляет его текст в текущую точку в файле спецификаций.

%include_noerr <file>

То же, что и ‘%include’, но не генерирует сообщение об ошибке, если файл включения не найден.

%rename old_name new_name

Переименовывает строку спецификаций old_name в new_name.

*[spec_name]:

Это сообщает компилятору создать, переопределить или удалить строку спецификации с заданным именем. Все строки после этой директивы до следующей директивы или пустой строки считаются текстом для строки спецификаций. Если это приводит к пустой строке, то спецификация удаляется. (Или, если спецификация не существовала, ничего не происходит.) В противном случае, если спецификация в настоящее время не существует, создаётся новая спецификация. Если спецификация существует, её содержимое переопределяется текстом этой директивы, если первый символ этого текста — символ ‘+’, в этом случае текст добавляется к спецификации.

[suffix]:

Создаёт новую пару «[суффикс] спецификация». Все строки после этой директивы и до следующей директивы или пустой строки считаются составляющими строку спецификации для указанного суффикса. Когда компилятор встречает входной файл с указанным суффиксом, он обрабатывает строку спецификаций, чтобы выяснить, как скомпилировать этот файл. Например:

.ZZ:
z-compile -input %i

Это означает, что любой входной файл, имя которого заканчивается на ‘.ZZ’, должен быть передан программе ‘z-compile’, которая должна быть вызвана с переключателем командной строки -input и с результатом выполнения подстановки ‘%i’. (См. ниже.)

В качестве альтернативы предоставлению строки спецификаций, текст, следующий за директивой суффикса, может быть одним из следующих:

@language

Это означает, что суффикс является псевдонимом известного языка. Это аналогично использованию переключателя командной строки -x в GCC для явного указания языка. Например:

.ZZ:
@c++

Указывает, что файлы .ZZ фактически являются исходными файлами C++.

#name

Это вызывает сообщение об ошибке, которое гласит:

name compiler not installed on this system.

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

GCC имеет следующие встроенные строки спецификаций. Файлы спецификаций могут переопределять эти строки или создавать свои собственные. Обратите внимание, что отдельные целевые платформы также могут добавлять свои собственные строки спецификаций в этот список.

asm          Options to pass to the assembler
asm_final    Options to pass to the assembler post-processor
cpp          Options to pass to the C preprocessor
cc1          Options to pass to the C compiler
cc1plus      Options to pass to the C++ compiler
endfile      Object files to include at the end of the link
link         Options to pass to the linker
lib          Libraries to include on the command line to the linker
libgcc       Decides which GCC support library to pass to the linker
linker       Sets the name of the linker
predefines   Defines to be passed to the C preprocessor
signed_char  Defines to pass to CPP to say whether char is signed
             by default
startfile    Object files to include at the start of the link

Вот небольшой пример файла спецификаций:

%rename lib                 old_lib

*lib:
--start-group -lgcc -lc -leval1 --end-group %(old_lib)

В этом примере спецификация, называемая ‘lib’, переименовывается в ‘old_lib’, а затем предыдущее определение ‘lib’ переопределяется новым. Новое определение добавляет некоторые дополнительные параметры командной строки перед включением текста старого определения.

Строки спецификаций представляют собой список параметров командной строки, которые необходимо передать соответствующей программе. Кроме того, строки спецификаций могут содержать последовательности, начинающиеся с ‘%’, для подстановки переменного текста или условной вставки текста в командную строку. С помощью этих конструкций можно генерировать довольно сложные командные строки.

Вот таблица всех определённых последовательностей ‘%’ для строк спецификаций. Обратите внимание, что пробелы автоматически не генерируются вокруг результатов расширения этих последовательностей. Поэтому вы можете конкатенировать их вместе или комбинировать их с постоянным текстом в одном аргументе.

%%

Замещает один символ ‘%’ в имени программы или аргументе.

%"

Замещает пустой аргумент.

%i

Замещает имя входного файла, который обрабатывается.

%b

Замещает базовое имя (basename) для выходных данных, связанных с обрабатываемым входным файлом. Это часто подстрока до (но не включая) последней точки и не включая директорию, но, если %w не активен, она расширяется до базового имени для вспомогательных выходных данных, которые могут быть повлияны явным именем файла вывода и различными другими параметрами, которые управляют тем, как называются вспомогательные выходные данные.

%B

Это то же самое, что и ‘%b’, но включает в себя расширение файла (текст после последней точки). Без %w, оно расширяется до базового имени для выходных данных дампов.

%d

Помечает аргумент, содержащий или следующий за ‘%d’, как временное имя файла, так что этот файл будет удалён, если GCC завершится успешно. В отличие от ‘%g’, это не добавляет текст в аргумент.

%gsuffix

Замещает имя файла с расширением suffix, выбранное один раз за компиляцию, и отмечает аргумент так же, как и ‘%d’. Чтобы уменьшить уязвимость к атакам отказа в обслуживании, имя файла теперь выбирается таким образом, что его трудно предсказать, даже если известны ранее выбранные имена файлов. Например, ‘%g.s … %g.o … %g.s’ может превратиться в ‘ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s’. suffix соответствует регулярному выражению ‘[.A-Za-z]*’ или специальной строке ‘%O’, которая обрабатывается точно так же, как если бы ‘%O’ была предварительно обработана. Ранее ‘%g’ просто заменялось именем файла, выбранным один раз за компиляцию, без учёта добавленного расширения (которое, следовательно, обрабатывалось как обычный текст), что делало такие атаки более вероятными.

%usuffix

Подобно ‘%g’, но генерирует новое временное имя файла каждый раз, когда оно встречается, вместо одного раза за компиляцию.

%Usuffix

Заменяет последнее имя файла, сгенерированное с помощью ‘%usuffix’, генерируя новое, если такого последнего имени файла нет. В отсутствие ‘%usuffix’, это аналогично ‘%gsuffix’, за исключением того, что они не используют одно и то же пространство расширений. Поэтому ‘%g.s … %U.s … %g.s … %U.s’ подразумевает генерацию двух разных имён файлов, по одному для каждого ‘%g.s’ и другому для каждого ‘%U.s’. Ранее ‘%U’ просто заменялось именем файла, выбранным для предыдущего ‘%u’, без учёта присоединённого расширения.

%jsuffix

Замещает имя HOST_BIT_BUCKET, если оно есть, если оно доступно для записи и если не используется -save-temps; в противном случае замещает именем временного файла, как и ‘%u’. Этот временный файл не предназначен для связи между процессами, а скорее как механизм удаления мусора.

%|suffix
%msuffix

Подобно ‘%g’, но если включён параметр -pipe. В этом случае ‘%|’ подставляет одиночный дефис, а ‘%m’ – ничего. Это два наиболее распространённых способа указать программе читать со стандартного ввода или записывать в стандартный вывод. Если вам нужно что-то более сложное, вы можете использовать конструкцию ‘%{pipe:X}’; см., например, gcc/fortran/lang-specs.h.

%.SUFFIX

Заменяет .SUFFIX расширениями аргументов совпадающего ключа, когда он затем выводится с помощью ‘%*’. SUFFIX завершается следующей пробелом или символом %.

%w

Помечает аргумент, содержащий или следующий за ‘%w’, как назначенный выходной файл этой компиляции. Это помещает аргумент в последовательность аргументов, которые заменяет ‘%o’.

%V

Указывает, что эта компиляция не производит файл вывода.

%o

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

%O

Заменяет расширение для файлов-объектов. Обратите внимание, что это обрабатывается особым образом, когда оно следует непосредственно за ‘%g, %u, или %U’ из-за необходимости формирования полных имён файлов. Обработка такова, что ‘%O’ обрабатывается так, как будто оно уже было заменено, за исключением того, что ‘%g, %u, и %U’ в настоящее время не поддерживают дополнительные символы suffix после ‘%O’, как они поддерживают, например, после ‘.o’.

%I

Замещает любой из -iprefix (составленный из GCC_EXEC_PREFIX), -isysroot (составленный из TARGET_SYSTEM_ROOT), -isystem (составленный из COMPILER_PATH и опций -B) и -imultilib, при необходимости.

%s

Текущий аргумент – имя библиотеки или файла инициализации. Поиск этого файла в стандартном списке директорий и замена полным найденным именем. Текущая рабочая директория включена в список просматриваемых директорий.

%T

Текущий аргумент – имя скрипта компоновщика. Поиск этого файла в текущем списке директорий для поиска библиотек. Если файл найден, в командную строку вставляется опция --script с полным путём найденного файла. Если файл не найден, выводится сообщение об ошибке. Примечание: текущая рабочая директория не просматривается.

%estr

Выводит str как сообщение об ошибке. str завершается новой строкой. Используйте это при обнаружении несогласованных параметров.

%nstr

Выводит str как сообщение. str завершается новой строкой.

%(name)

Заменяет содержимое строки спецификации name на этом этапе.

%x{option}

Накапливает параметр для ‘%X’.

%X

Выводит накопленные параметры компоновщика, заданные строкой спецификации ‘%x’.

%Y

Выводит накопленные параметры ассемблера, заданные -Wa.

%Z

Выводит накопленные параметры препроцессора, заданные -Wp.

%M

Выводит multilib_os_dir.

%R

Выводит конкатенацию target_system_root и target_sysroot_suffix.

%a

Обрабатывает спецификацию asm. Это используется для вычисления параметров, передаваемых ассемблеру.

%A

Обрабатывает спецификацию asm_final. Это строка спецификаций для передачи параметров постпроцессору ассемблера, если такая программа требуется.

%l

Обрабатывает спецификацию link. Это спецификация для вычисления командной строки, передаваемой компоновщику. Обычно она использует последовательности ‘%L %G %S %D и %E’.

%D

Выводит опцию -L для каждой директории, которую GCC считает возможной для расположения файлов инициализации. Если целевая система поддерживает многоязыковые библиотеки, то текущая многоязыковая директория предваряет каждый из этих путей.

%L

Обрабатывает спецификацию lib. Это строка спецификаций для определения библиотек, которые включаются в командную строку компоновщика.

%G

Обрабатывает спецификацию libgcc. Это строка спецификаций для определения библиотеки поддержки GCC, которая включается в командную строку компоновщика.

%S

Обрабатывает спецификацию startfile. Это спецификация для определения первых файлов-объектов, которые передаются компоновщику. Обычно это файл с именем crt0.o.

%E

Обрабатывает спецификацию endfile. Это строка спецификаций, которая определяет последние файлы-объекты, передаваемые компоновщику.

%C

Обрабатывает спецификацию cpp. Это используется для построения аргументов, передаваемых препроцессору C.

%1

Обрабатывает спецификацию cc1. Это используется для построения параметров, передаваемых непосредственно компилятору C (cc1).

%2

Обрабатывает спецификацию cc1plus. Это используется для построения параметров, передаваемых непосредственно компилятору C++ (cc1plus).

%*

Заменяет переменную часть совпадающего параметра. Смотрите ниже. Обратите внимание, что каждая запятая в подставленной строке заменяется на один пробел.

%<S

Удаляет все вхождения -S из командной строки. Примечание – эта команда зависит от позиции. Команды ‘%’ в строке спецификации перед этой видят -S, команды ‘%’ в строке спецификации после этой не видят.

%<S*

Аналогично ‘%<S’, но сопоставляет все параметры, начинающиеся с -S.

%>S

Аналогично ‘%<S’, но сохраняет -S в командной строке GCC.

%:function(args)

Вызовите именованную функцию function, передав ей args. args сначала обрабатывается как вложенная строка спецификации, затем разбивается на вектор аргументов обычным способом. Функция возвращает строку, которая обрабатывается так, как будто она появилась буквально как часть текущей спецификации.

Ниже приведены встроенные функции спецификации:

getenv

Функция спецификации getenv принимает два аргумента: имя переменной среды и строку. Если переменная среды не определена, выдается ошибка. В противном случае возвращаемое значение — это значение переменной среды, конкатенированное со строкой. Например, если TOPDIR определена как /path/to/top, то:

%:getenv(TOPDIR /include)

расширяется до /path/to/top/include.

if-exists

Функция спецификации if-exists принимает один аргумент — абсолютный путь к файлу. Если файл существует, if-exists возвращает путь. Вот небольшой пример её использования:

*startfile:
crt0%O%s %:if-exists(crti%O%s) crtbegin%O%s
if-exists-else

Функция спецификации if-exists-else похожа на функцию спецификации if-exists, за исключением того, что она принимает два аргумента. Первый аргумент — абсолютный путь к файлу. Если файл существует, if-exists-else возвращает путь. Если он не существует, возвращается второй аргумент. Таким образом, if-exists-else можно использовать для выбора одного файла или другого в зависимости от существования первого. Вот небольшой пример её использования:

*startfile:
crt0%O%s %:if-exists(crti%O%s) \
%:if-exists-else(crtbeginT%O%s crtbegin%O%s)
if-exists-then-else

Функция спецификации if-exists-then-else принимает как минимум два аргумента и необязательный третий. Первый аргумент — абсолютный путь к файлу. Если файл существует, функция возвращает второй аргумент. Если файла нет, функция возвращает третий аргумент, если он есть, или NULL в противном случае. Это можно использовать для расширения одного текста или, по желанию, другого в зависимости от существования файла. Вот небольшой пример её использования:

-l%:if-exists-then-else(%:getenv(VSB_DIR rtnet.h) rtnet net)
sanitize

Функция спецификации sanitize не принимает аргументов. Она возвращает не NULL, если включены какие-либо санитайзеры адресов, потоков или неопределенного поведения.

%{%:sanitize(address):-funwind-tables}
replace-outfile

Функция спецификации replace-outfile принимает два аргумента. Она ищет первый аргумент в массиве outfiles и заменяет его вторым аргументом. Вот небольшой пример её использования:

%{fgnu-runtime:%:replace-outfile(-lobjc -lobjc-gnu)}
remove-outfile

Функция спецификации remove-outfile принимает один аргумент. Она ищет первый аргумент в массиве outfiles и удаляет его. Вот небольшой пример её использования:

%:remove-outfile(-lm)
version-compare

Функция спецификации version-compare принимает четыре или пять аргументов следующего формата:

<comparison-op> <arg1> [<arg2>] <switch> <result>

Она возвращает result если сравнение истинно и NULL, если нет. Поддерживаемые значения comparison-op:

>=

Истина, если switch — более поздняя (или такая же) версия, чем arg1

!>

Противоположность >=

<

Истина, если switch — более ранняя версия, чем arg1

!<

Противоположность <

><

Истина, если switch — arg1 или более поздняя версия и более ранняя, чем arg2

<>

Истина, если switch — более ранняя версия, чем arg1, или arg2 или более поздняя

Если switch отсутствует, условие ложно, если первый символ comparison-op равен !.

%:version-compare(>= 10.3 mmacosx-version-min= -lmx)

В приведенном выше примере будет добавлено -lmx, если было передано -mmacosx-version-min=10.3.9.

include

Функция спецификации include очень похожа на %include, но имеет преимущество в том, что может быть вложена в спецификацию и, таким образом, условна. Она принимает один аргумент — имя файла — и ищет его в пути startfile. Она всегда возвращает NULL.

%{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)}
pass-through-libs

Функция спецификации pass-through-libs принимает любое количество аргументов. Она находит все опции -l и все не опции, заканчивающиеся на .a (которые она предполагает, являются именами архивов библиотек входных файлов компоновщика), и возвращает результат, содержащий все найденные аргументы, каждый из которых предваряется -plugin-opt=-pass-through= и соединенные пробелами. Этот список предназначен для передачи плагину компоновщика LTO.

%:pass-through-libs(%G %L %G)
print-asm-header

Функция print-asm-header не принимает аргументов и просто выводит заголовок, например:

Assembler options
=================

Use "-Wa,OPTION" to pass "OPTION" to the assembler.

Она используется для разделения опций компилятора от опций ассемблера в выводе --target-help.

gt

Функция спецификации gt принимает два или более аргументов. Она возвращает "" (пустую строку), если предпоследний аргумент больше последнего аргумента, и NULL в противном случае. Следующий пример вставляет спецификацию link_gomp, если последняя опция -ftree-parallelize-loops=, заданная в командной строке, больше 1:

%{%:gt(%{ftree-parallelize-loops=*:%*} 1):%:include(libgomp.spec)%(link_gomp)}
debug-level-gt

Функция спецификации debug-level-gt принимает один аргумент и возвращает "" (пустую строку), если debug_info_level больше указанного числа, и NULL в противном случае.

%{%:debug-level-gt(0):%{gdwarf*:--gdwarf2}}
%{S}

Заменяет переключатель -S, если этот переключатель задан для GCC. Если этот переключатель не указан, он ничего не заменяет. Обратите внимание, что ведущий дефис опускается при указании этой опции, и он автоматически вставляется, если выполняется замена. Таким образом, строка спецификации ‘%{foo}’ соответствует опции командной строки -foo и выводит опцию командной строки -foo.

%W{S}

Как %{S}, но помечает последний предоставленный аргумент как файл, который будет удалён при ошибке.

%@{S}

Как %{S}, но помещает результат в FILE и заменяет @FILE, если был предоставлен аргумент @file.

%{S*}

Заменяет все переключатели, указанные для GCC, имена которых начинаются с -S, но которые также принимают аргумент. Это используется для переключателей, таких как -o, -D, -I и т. д. GCC рассматривает -o foo как один переключатель, имя которого начинается с ‘o’. %{o*} заменяет этот текст, включая пробел. Таким образом, генерируются два аргумента.

%{S*&T*}

Как %{S*}, но сохраняет порядок опций S и T (порядок S и T в спецификации не имеет значения). Может быть любое количество переменных, разделенных амперсандом; для каждой переменной звездочка необязательна. Полезно для CPP, как ‘%{D*&U*&A*}’.

%{S:X}

Заменяет X, если переключатель -S задан для GCC.

%{!S:X}

Заменяет X, если переключатель -S не задан для GCC.

%{S*:X}

Заменяет X, если для GCC указан один или несколько переключателей, имена которых начинаются с -S. Обычно X заменяется только один раз, независимо от того, сколько таких переключателей появилось. Однако, если %* появляется где-то в X, то X заменяется один раз для каждого соответствующего переключателя, с заменой %* на часть переключателя, соответствующую *.

Если %* появляется в качестве последней части последовательности спецификаций, то после окончания последней замены добавляется пробел. Однако, если в последовательности есть ещё текст, то пробел не генерируется. Это позволяет использовать замену %* в качестве части большей строки. Например, строка спецификации такого вида:

%{mcu=*:--script=%*/memory.ld}

при сопоставлении с опцией, такой как -mcu=newchip, даёт:

--script=newchip/memory.ld
%{.S:X}

Заменяет X, если обрабатывается файл с суффиксом S.

%{!.S:X}

Заменяет X, если не обрабатывается файл с суффиксом S.

%{,S:X}

Заменяет X, если обрабатывается файл для языка S.

%{!,S:X}

Заменяет X, если не обрабатывается файл для языка S.

%{S|P:X}

Заменяет X, если для GCC указан либо -S, либо -P. Это можно комбинировать с ‘!’, ‘.’, ‘,’, и последовательностями *, хотя они имеют более сильную связность, чем ‘|’. Если %* появляется в X, все альтернативы должны быть помечены звёздочкой, и только первая соответствующая альтернатива будет заменена.

Например, строка спецификации такого вида:

%{.c:-foo} %{!.c:-bar} %{.c|d:-baz} %{!.c|d:-boggle}

выводит следующие опции командной строки из следующих опций командной строки:

fred.c        -foo -baz
jim.d         -bar -boggle
-d fred.c     -foo -baz -boggle
-d jim.d      -bar -baz -boggle
%{%:function(args):X}

Вызовите функцию с именем function с аргументами args. Если функция возвращает значение отличное от NULL, то X заменяется, если возвращает NULL, то не заменяется.

%{S:X; T:Y; :D}

Если S задано для GCC, подставляется X; в противном случае, если T задано для GCC, подставляется Y; в противном случае подставляется D. Может быть столько условий, сколько нужно. Это может быть сочетано с ., ,, !, |, и * по мере необходимости.

Сопоставление текста переключателя S в конструкции ‘%{S}’, ‘%{S:X}’ или аналогичной может использовать обратную косую черту для игнорирования специального значения следующего за ней символа, тем самым позволяя выполнить буквальное сопоставление символа, который в противном случае обрабатывается особым образом. Например, ‘%{std=iso9899\:1999:X}’ подставляет X если опция -std=iso9899:1999 задана.

Условный текст X в конструкции ‘%{S:X}’ или аналогичной может содержать другие вложенные конструкции ‘%’ или пробелы, или даже новые строки. Они обрабатываются как обычно, как описано выше. Конечные пробелы в X игнорируются. Пробелы также могут появляться где угодно слева от двоеточия в этих конструкциях, за исключением пробелов между . или * и соответствующим словом.

Переключатели -O, -f, -m и -W обрабатываются специально в этих конструкциях. Если другое значение -O или отрицающая форма -f, -m или -W переключателя встречается позже в командной строке, более раннее значение переключателя игнорируется, за исключением случаев с {S*} где S — всего одна буква, которая пропускает все соответствующие опции.

Символ ‘|’ в начале текста предиката используется для указания на то, что команда должна быть передана в следующую команду, но только если указана опция -pipe.

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

GCC также неявно понимает, что аргументы, начинающиеся с -l, должны обрабатываться как файлы вывода компилятора и передаваться компоновщику в их правильном положении среди других файлов вывода.

Далее: Переменные среды, Предыдущее: Опции подмодели, Вверх: Вызов GCC [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Spec-Files.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API