3.20 Указание дочерних процессов и переключателей для передачи им ¶
gcc является драйверной программой. Она выполняет свою работу, вызывая последовательность других программ для выполнения задач компиляции, сборки и компоновки. GCC интерпретирует параметры командной строки и использует их для определения, какие программы следует вызвать и какие параметры командной строки следует передать в их командные строки. Это поведение контролируется строками спецификаций. В большинстве случаев для каждой программы, которую может вызвать GCC, существует одна строка спецификаций, но некоторые программы имеют несколько строк спецификаций для управления их поведением. Встроенные в GCC строки спецификаций могут быть переопределены с помощью переключателя командной строки -specs= для указания файла спецификаций.
Файлы спецификаций — это текстовые файлы, которые используются для построения строк спецификаций. Они состоят из последовательности директив, разделенных пустыми строками. Тип директивы определяется первым не-пробельным символом в строке, который может быть одним из следующих:
%command-
Выполняет команду для процессора файла спецификаций. Команды, которые могут появиться здесь:
%include <file>-
Ищет файл и вставляет его текст в текущую точку файла спецификаций.
%include_noerr <file>-
Точно так же, как ‘%include’, но не генерирует сообщение об ошибке, если файл включения не найден.
%rename 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-
Замените имя базовой части входного файла, обрабатываемого программой. Это подстрока до (и не включая) последней точки и не включая каталог.
%B-
Это то же самое, что и ‘%b’, но включает расширение файла (текст после последней точки).
%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’.
%o-
Заменяет имена всех выходных файлов со автоматически добавленными пробелами вокруг них. Вы также должны добавить пробелы вокруг ‘%o’, иначе результаты будут неопределенными. ‘%o’ предназначен для использования в спецификациях для запуска компоновщика. Входные файлы, имена которых не имеют распознанного расширения, не компилируются, но они включаются в список выходных файлов, поэтому они компонуются.
%O-
Заменяет расширение для файлов объектов. Обратите внимание, что это обрабатывается особым образом, когда оно непосредственно следует за ‘%g, %u или %U’ из-за необходимости формирования полных имён файлов. Обработка такова, что ‘%O’ обрабатывается так же, как если бы оно уже было заменено, за исключением того, что ‘%g, %u и %U’ в настоящее время не поддерживают дополнительные символы suffix после ‘%O’, как они поддерживают после, например, ‘.o’.
%p-
Заменяет стандартные макроопределения для текущей целевой машины. Используйте это при запуске
cpp. %P-
Как ‘%p’, но добавляет ‘__’ перед и после имени каждого предопределённого макроса, за исключением макросов, начинающихся с ‘__’ или с ‘_L’, где L — большая буква. Это для ISO C.
%I-
Замените любое из -iprefix (составлено из
GCC_EXEC_PREFIX), -isysroot (составлено изTARGET_SYSTEM_ROOT), -isystem (составлено изCOMPILER_PATH) и -B опций, и -imultilib, при необходимости. %s-
Текущий аргумент — имя библиотеки или файла инициализации. Поиск этого файла в стандартном списке каталогов и замена полным именем, найденным. Текущий рабочий каталог включается в список сканируемых каталогов.
%T-
Текущий аргумент — имя файла скрипта компоновщика. Поиск этого файла в текущем списке каталогов для поиска библиотек. Если файл найден, введите опцию --script в командную строку, после чего полное имя найденного файла. Если файл не найден, выведите сообщение об ошибке. Примечание: текущий рабочий каталог не ищется.
%estr-
Вывести str как сообщение об ошибке. str завершается новой строкой. Используйте это, когда обнаружены несовместимые опции.
%(name)-
Замените содержимое строки спецификаций name на данном этапе.
%x{option}-
Накопить опцию для ‘%X’.
%X-
Вывести накопленные опции компоновщика, заданные строкой спецификации ‘%x’.
%Y-
Вывести накопленные опции ассемблера, заданные -Wa.
%Z-
Вывести накопленные опции препроцессора, заданные -Wp.
%a-
Обработать
asmспецификацию. Это используется для вычисления параметров, которые будут переданы ассемблеру. %A-
Обработать
asm_finalспецификацию. Это строка спецификаций для передачи параметров постпроцессору ассемблера, если такая программа нужна. %l-
Обработать
linkспецификацию. Это спецификация для вычисления командной строки, передаваемой компоновщику. Обычно она использует последовательности ‘%L %G %S %D и %E’. %D-
Вывести опцию -L для каждого каталога, который GCC считает потенциальным местоположением файлов инициализации. Если целевая система поддерживает многоязыковые библиотеки, то текущий каталог multilib добавляется в начало каждого из этих путей.
%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, команды ‘%’ в строке спецификации после этой — нет. %: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)
replace-outfile-
Функция спецификации
replace-outfileпринимает два аргумента. Она ищет первый аргумент в массиве outfiles и заменяет его на второй аргумент. Вот небольшой пример её использования:%{fgnu-runtime:%:replace-outfile(-lobjc -lobjc-gnu)} remove-outfile-
Функция спецификации
remove-outfileпринимает один аргумент. Она ищет первый аргумент в массиве outfiles и удаляет его. Вот небольшой пример её использования:%:remove-outfile(-lm)
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.
%{S}-
Заменяет переключатель
-S, если этот переключатель задан для GCC. Если этот переключатель не указан, ничего не заменяется. Обратите внимание, что ведущий дефис опускается при указании этой опции, и он автоматически вставляется, если выполняется замена. Таким образом, строка спецификации ‘%{foo}’ соответствует опции командной строки -foo и выводит опцию командной строки -foo. %W{S}-
Как %{
S}, но помечает последний предоставленный аргумент как файл, который необходимо удалить при ошибке. %{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
%{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, должны обрабатываться как выходные файлы компилятора и передаваться линковщику в их правильной позиции среди других выходных файлов.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/Spec-Files.html