Spec-Zone.ru › GCC 14

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

Замещает базовое имя (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, если заданы один или несколько переключателей, имена которых начинаются с -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-14.2.0/gcc/Spec-Files.html

Spec-Zone.ru

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