3.19 Указание подпроцессов и переключателей, передаваемых им
gcc — это программа-драйвер. Она выполняет свою работу, вызывая последовательность других программ для выполнения задач компиляции, сборки и компоновки. GCC интерпретирует параметры командной строки и использует их для определения, какие программы необходимо вызвать, а также какие параметры командной строки необходимо передать каждой из них. Это поведение контролируется *строками спецификаций*. В большинстве случаев для каждой программы, которую может вызвать GCC, существует одна строка спецификации, но некоторые программы имеют несколько строк спецификаций для управления их поведением. Встроенные в GCC строки спецификаций можно переопределить, используя переключатель командной строки -specs= для указания файла спецификаций.
Файлы спецификаций — это текстовые файлы, используемые для построения строк спецификаций. Они состоят из последовательности директив, разделенных пустыми строками. Тип директивы определяется первым не-пробельным символом в строке, который может быть одним из следующих:
%commandВыполняет команду для процессора файла спецификаций. Команды, которые могут здесь появиться, включают:
%include <file>Ищет файл и вставляет его текст в текущую позицию в файле спецификаций.
%include_noerr <file>Точно так же, как ‘%include’, но не генерирует сообщение об ошибке, если файл включения не найден.
%rename old_name new_nameПереименовывает строку спецификации old_name в new_name.
*[spec_name]:Это указывает компилятору создать, переопределить или удалить именованную строку спецификации. Все строки после этой директивы до следующей директивы или пустой строки считаются текстом для строки спецификации. Если это приводит к пустой строке, то спецификация удаляется. (Или, если спецификация не существовала, ничего не происходит.) В противном случае, если спецификация в настоящее время не существует, создается новая спецификация. Если спецификация существует, её содержимое переопределяется текстом этой директивы, если первый символ этого текста не является символом ‘+’, в этом случае текст добавляется к спецификации.
[suffix]:Создает новую пару «[суффикс] spec». Все строки после этой директивы и до следующей директивы или пустой строки считаются строкой спецификации для указанного суффикса. Когда компилятор сталкивается с входным файлом с указанным суффиксом, он обрабатывает строку спецификации, чтобы выяснить, как скомпилировать этот файл. Например:
.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’ переопределяется новым. Новое определение добавляет дополнительные параметры командной строки перед включением текста старого определения.
Строки спецификаций — это список параметров командной строки, которые должны быть переданы соответствующей программе. Кроме того, строки спецификаций могут содержать последовательности, начинающиеся с ‘%’, для подстановки переменного текста или условной вставки текста в командную строку. Используя эти конструкции, можно генерировать довольно сложные командные строки.
Вот таблица всех определённых последовательностей ‘%’ для строк спецификаций. Обратите внимание, что пробелы не генерируются автоматически вокруг результатов расширения этих последовательностей. Поэтому вы можете конкатенировать их или комбинировать с постоянным текстом в одном аргументе.
END_OF_DOCUMENT_MARKER%%-
Замените одну ‘%’ в имени программы или аргументе.
%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}’: см., например, f/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-
Выводит накопленные опции компоновщика, заданные -Wl или строкой спецификации ‘%x’.
%Y-
Выводит накопленные опции ассемблера, заданные -Wa.
%Z-
Выводит накопленные опции препроцессора, заданные -Wp.
%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, команды ‘%’ в строке спецификации после этой команды не видят. %: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, если один или несколько переключателей, имена которых начинаются с-S, заданы для GCC. Обычно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, если переключатель-Sили-Pзадан для GCC. Это можно комбинировать с последовательностями ‘!’, ‘.’, ‘,’ и*, хотя у них более сильная связь, чем у ‘|’. Если%*появляется в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. Вы можете добавить столько условий, сколько вам нужно. Это можно комбинировать с.,,,!,|, и*по мере необходимости.
Условный текст 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-7.5.0/gcc/Spec-Files.html