Spec-Zone.ru › GCC 13

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

Замените имя без пути к выходным данным, связанным с обрабатываемым входным файлом. Часто это подстрока до (но не включая) последней точки и не включая каталог, но, если %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, or %U’, из-за необходимости формирования полных имён файлов. Обработка такова, что ‘%O’ обрабатывается так, как будто оно уже было заменено, за исключением того, что ‘%g, %u, and %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 принимает два аргумента: имя переменной окружения и строку. Если переменная окружения не определена, выдается ошибка fatal. В противном случае возвращаемое значение — это значение переменной окружения, соединённое со строкой. Например, если 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, если указан один или несколько переключателей, имена которых начинаются с -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
%{%: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, должны обрабатываться как файлы выходных данных компилятора и передаваться компоновщику в соответствующем положении среди других выходных файлов.

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

Spec-Zone.ru

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