5.11.1. Замена программы для одной или нескольких фаз
Можно указать, что для одной из фаз системы компиляции будет использоваться другая программа вместо той, которую ghc встроил в неё. Например, может понадобиться попробовать другой ассемблер. Следующие параметры позволяют изменить внешнюю программу, используемую на определённой фазе компиляции:
-
-pgmL ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве препроцессора literate.
-
-pgmP ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве препроцессора C для Haskell (только вместе с
-cpp). Обратите внимание, что препроцессор C для Haskell обрабатывает только файлы Haskell.
-
-pgmJSP ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве препроцессора C для JavaScript (только для бэкенда JavaScript).
-
-pgmCmmP ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве препроцессора C для C–.
-
-pgmc ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве компилятора C.
-
-pgmcxx ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве компилятора C++.
-
-pgmlo ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве оптимизатора LLVM.
-
-pgmlc ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве компилятора LLVM.
-
-pgmlas ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве ассемблера LLVM
-
-pgms ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве разделителя.
-
-pgma ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве ассемблера.
-
-pgml ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве компоновщика.
-
-pgmlm ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве компоновщика при объединении объектных файлов (например, при создании объединённых объектных файлов для загрузки в GHCi).
-
-pgmF ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве препроцессора (только вместе с
-F).
-
-pgmotool ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве программы для анализа динамических библиотек и исполняемых файлов Mach-O с целью чтения зависимостей динамических библиотек. Мы вычислим необходимый вызов
runpath``s to embed for the dependencies based on the result of the ``otool.
-
-pgminstall_name_tool ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве программы для добавления вызова
runpath``s into mach-o dynamic libraries and executables. As detected by the ``otool.
-
-pgmwindres ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве программы для встраивания манифестов в Windows. Обычно это программа
windres, поставляемая вместе с установкой GHC. См.-fno-embed-manifestв разделе Параметры, влияющие на компоновку.
-
-pgmi ⟨cmd⟩ -
Использовать ⟨cmd⟩ в качестве команды внешнего интерпретатора (см. Запуск интерпретатора в отдельном процессе). По умолчанию:
ghc-iserv-prof, если включён параметр-prof;ghc-iserv-dyn, если включён параметр-dynamic; илиghc-iservв остальных случаях.
5.11.2. Передача параметров определённой фазе
Параметры можно передать определённой фазе компиляции с помощью следующих флагов:
-
-optL ⟨option⟩ -
Передать ⟨option⟩ препроцессору literate
-
-optP ⟨option⟩ -
Передать ⟨option⟩ препроцессору CPP для Haskell (имеет смысл только при включённом параметре
-cpp). Обратите внимание, что параметры препроцессора Haskell применяются только при предварительной обработке файлов Haskell; например, чтобы использовать другие параметры для предварительной обработки JavaScript или Cmm, следует использовать соответственно-optJSPили-optCmmP.
-
-optJSP ⟨option⟩ -
Передать ⟨option⟩ препроцессору C для JavaScript (только для бэкенда JavaScript).
-
-optCmmP ⟨option⟩ -
Передать ⟨option⟩ препроцессору C для C–.
Препроцессор C для C– также получает флаги компилятора C. Эти флаги указываются _перед_ флагами, добавленными этим параметром. В результате совокупный эффект следующей пары флагов равен нулю:
-optCmmP-UFOO -optc-DFOO.
-
-optF ⟨option⟩ -
Передать ⟨option⟩ пользовательскому препроцессору (см. Параметры, влияющие на препроцессор Haskell).
-
-optc ⟨option⟩ -
Передать ⟨option⟩ компилятору C и, для совместимости, препроцессору C–.
-
-pgmc-supports-no-pie -
Выполняет то же действие, что и
-pgml-supports-no-pie, заменивший этот параметр.
-
-pgml-supports-no-pie -
При использовании
-pgmlGHC по умолчанию никогда не передаёт флаг командной строки-no-pie. Причина в том, что неизвестно, поддерживает ли его указанный компилятор, используемый для компоновки (напомним, что мы вызываем компоновщик от своего имени с помощью компилятора C). Этот флаг позволяет указать, что-no-pieподдерживается. Его необходимо передать после-pgml.Этот флаг не требуется, если
-pgmcне используется, поскольку GHC хранит сведения о поддержке-no-pieкомпилятором C по умолчанию во внутреннем файле настроек.
-
-optcxx ⟨option⟩ -
Передать ⟨option⟩ компилятору C++.
-
-optlo ⟨option⟩ -
Передать ⟨option⟩ оптимизатору LLVM.
-
-optlc ⟨option⟩ -
Передать ⟨option⟩ компилятору LLVM.
-
-optlas ⟨option⟩ -
Передать ⟨option⟩ ассемблеру LLVM (обычно clang).
-
-opta ⟨option⟩ -
Передать ⟨option⟩ ассемблеру.
-
-optl ⟨option⟩ -
Передать ⟨option⟩ компоновщику.
-
-optlm ⟨option⟩ -
Передать ⟨option⟩ компоновщику при объединении объектных файлов. В случае стандартного компоновщика в стиле
ldсюда обычно следует включить флаг-r.
-
-optwindres ⟨option⟩ -
Передать ⟨option⟩ программе
windresпри встраивании манифестов в Windows. См.-fno-embed-manifestв разделе Параметры, влияющие на компоновку.
-
-opti ⟨option⟩ -
Передать ⟨option⟩ подпроцессу интерпретатора (см. Запуск интерпретатора в отдельном процессе). Часто это используется для передачи параметров RTS, например
-opti+RTS -opti-A64m, или для включения подробного вывода с помощью-opti-v, чтобы видеть, какие сообщения передаются между GHC и интерпретатором.
Например, чтобы передать ассемблеру параметр -Ewurble, нужно указать драйверу -opta-Ewurble (дефис перед E обязателен).
GHC — это программа на Haskell, поэтому, если нужно напрямую передать параметры среде выполнения GHC, их можно заключить в +RTS ... -RTS (см. Параметры среды выполнения (RTS)).
5.11.3. Параметры, влияющие на препроцессор C
-
CPP -
- Начиная с:
-
6.8.1
Языковое расширение
CPPвключает препроцессор C. Его можно включить с помощью флага командной строки, добавив перед ним-X. Например:$ ghc -XCPP foo.hs
Языковое расширение
CPPтакже можно включить с помощью прагмы LANGUAGE. Например:{-# LANGUAGE CPP #-}
-
-cpp -
Препроцессор C cpp обрабатывает код Haskell, если указан параметр
-cppили расширениеCPP. Если только вы не собираете большую систему с широким использованием условной компиляции, скорее всего, он вам не понадобится.
-
-D⟨symbol⟩[=⟨value⟩] -
Определить макрос ⟨symbol⟩ обычным способом. Если значение не указано, ему присваивается значение
1. Например,-DUSE_MYLIBэквивалентно-DUSE_MYLIB=1.Примечание
-D⟨symbol⟩[=⟨value⟩]не влияет на макросы-D, передаваемые компилятору C при сборке без регистрации! В этом случае используйте обходной приём с-optc-Dfoo… (см. Передача параметров определённой фазе).
-
-U⟨symbol⟩ -
Отменить определение макроса ⟨symbol⟩ обычным способом.
-
-I⟨dir⟩ -
Указать каталог для поиска файлов
#includeобычным для C способом.
При обработке исходного кода Haskell драйвер GHC предварительно определяет несколько макросов (для файлов .hs или .lhs).
5.11.3.1. Стандартные макросы CPP
Ниже перечислены символы, определяемые GHC. Чтобы проверить, какие символы определены в установленной у вас версии GHC, можно воспользоваться следующим приёмом:
$ ghc -E -optP-dM -cpp foo.hs $ cat foo.hspp
(понадобится файл foo.hs, но фактически он не используется).
-
__GLASGOW_HASKELL__ -
Для версии GHC
x.y.zзначением__GLASGOW_HASKELL__является целое число ⟨xyy⟩ (если ⟨y⟩ состоит из одной цифры, перед ней добавляется ноль; например, для GHC версии 6.2 значение равно__GLASGOW_HASKELL__==602). Дополнительные сведения приведены в разделе Политика нумерации версий GHC.Можно надеяться, что во всех других реализациях с поддержкой препроцессора в стиле C макрос
__GLASGOW_HASKELL__не определён.Примечание
Соответствующие символы для других систем:
__HUGS__для Hugs,__NHC__для nhc98 и__HBC__для hbc).Примечание. Этот макрос задаётся при предварительной обработке исходного кода как Haskell, так и C, включая исходный код C, сгенерированный из модуля Haskell (то есть файлы
.hs,.lhs,.cи.hc). -
__GLASGOW_HASKELL_FULL_VERSION__ -
Этот макрос содержит полную строку версии. Например:
__GLASGOW_HASKELL_FULL_VERSION__==8.11.0.20200319. Его значение берётся из переменной AutotoolsProjectVersion.Добавлен в GHC 9.0.1
-
__GLASGOW_HASKELL_PATCHLEVEL1__; __GLASGOW_HASKELL_PATCHLEVEL2__ -
Эти макросы доступны начиная с GHC 7.10.1.
Для трёхкомпонентных номеров версий GHC
x.y.zзначением__GLASGOW_HASKELL_PATCHLEVEL1__является целое число ⟨z⟩.Для четырёхкомпонентных номеров версий GHC
x.y.z.z'значением__GLASGOW_HASKELL_PATCHLEVEL1__является целое число ⟨z⟩, а значением__GLASGOW_HASKELL_PATCHLEVEL2__— целое число ⟨z’⟩.Эти макросы позволяют задавать более точную гранулярность, чем
__GLASGOW_HASKELL__. Обычно в этом нет необходимости, поскольку предполагается, что большинство API остаются стабильными между выпусками с разными уровнями исправлений, но иногда для исправления ошибок требуются изменения внутренних API. Кроме того, условная компиляция по уровню исправлений может быть полезна для обхода ошибок в старых выпусках.Совет
Эти макросы задаются при предварительной обработке исходного кода как Haskell, так и C, включая исходный код C, сгенерированный из модуля Haskell (то есть файлы
.hs,.lhs,.cи.hc). -
MIN_VERSION_GLASGOW_HASKELL(x,y,z,z') -
Этот макрос доступен начиная с GHC 7.10.1.
Этот макрос предназначен для удобства при написании условий CPP, проверяющих, что используется версия GHC
x.y.z.z'или более поздняя.Если требуется совместимость с компиляторами Haskell (включая версии GHC до 7.10.1), которые не определяют
MIN_VERSION_GLASGOW_HASKELL, перед его вызовом необходимо убедиться в наличии макросаMIN_VERSION_GLASGOW_HASKELL, например:#if defined(MIN_VERSION_GLASGOW_HASKELL) #if MIN_VERSION_GLASGOW_HASKELL(7,10,2,0) /* code that applies only to GHC 7.10.2 or later */ #endif #endif
Совет
Этот макрос задаётся при предварительной обработке исходного кода как Haskell, так и C, включая исходный код C, сгенерированный из модуля Haskell (то есть файлы
.hs,.lhs,.cи.hc). -
__GLASGOW_HASKELL_TH__ -
Значение этого макроса равно
1, если компилятор поддерживает Template Haskell, и0, если не поддерживает. Последнее относится к компилятору первой стадии во время начальной загрузки или к архитектурам, для которых интерпретатор недоступен. -
__GLASGOW_HASKELL_LLVM__ -
Определён только при указании
-fllvm. Если GHC использует версию LLVMx.y.z, значением__GLASGOW_HASKELL_LLVM__является целое число ⟨xyy⟩ (если ⟨y⟩ состоит из одной цифры, перед ней добавляется ноль; например, при использовании LLVM версии 3.7 значение равно__GLASGOW_HASKELL_LLVM__==307). -
__GLASGOW_HASKELL_ASSERTS_IGNORED__ -
Определён только при указании
-fignore-asserts. Его можно использовать для создания собственных проверок; см. раздел Проверки. -
os_HOST_OS=1 -
Это определение позволяет выполнять условную компиляцию в зависимости от операционной системы, где ⟨os⟩ — название текущей операционной системы (например,
linux,mingw32для Windows,solarisи т. д.). -
arch_HOST_ARCH=1 -
Это определение позволяет выполнять условную компиляцию в зависимости от архитектуры хоста, где ⟨arch⟩ — название текущей архитектуры (например,
i386,x86_64,aarch64,powerpc,sparcи т. д.). -
VERSION_pkgname -
Этот макрос доступен начиная с GHC 8.0. Он определён для каждого экспортируемого пакета. Макрос раскрывается в строку, содержащую версию
pkgname, доступную для импорта модулей. По поведению он идентичен макросамVERSION_pkgname, определяемым Cabal. -
MIN_VERSION_pkgname(x,y,z) -
Этот макрос доступен начиная с GHC 8.0. Он определён для каждого экспортируемого пакета. Макрос предназначен для удобства при написании условий CPP, проверяющих, что версия пакета не ниже
x.y.z. По поведению он идентичен макросамMIN_VERSION_pkgname, определяемым Cabal. - Макросы SIMD
-
Они определяются условно в зависимости от флагов SIMD, используемых при компиляции:
__SSE__,__SSE2__,__SSE4_2__,__FMA__,__AVX__,__AVX2__,__AVX512CD__,__AVX512ER__,__AVX512F__,__AVX512PF__,
5.11.3.2. CPP и промежутки в строках
Небольшое предупреждение: -cpp плохо работает с «промежутками в строках». Иными словами, следующие строки:
strmod = "\ \ p \ \ "
не работают с -cpp; /usr/bin/cpp удаляет пары «обратная косая черта — перевод строки».
Однако, похоже, если добавить пробел в конец строки, то cpp (по крайней мере GNU cpp и, возможно, другие cpp) оставляет пары «обратная косая черта — пробел» без изменений, и промежуток в строке работает как ожидается.
5.11.4. Параметры, влияющие на препроцессор Haskell
-
-F -
Пользовательский препроцессор обрабатывает исходный файл Haskell только при указании параметра
-F.В некоторых случаях запуск пользовательского препроцессора во время компиляции уместен и полезен. Параметр
-Fпозволяет запускать препроцессор в составе общего конвейера компиляции GHC. Это даёт преимущество перед отдельным запуском препроцессора Haskell: такой подход работает в режиме интерпретации, и при этом можно продолжать пользоваться преимуществами проверки перекомпиляции GHC.Препроцессор запускается непосредственно перед тем, как собственно компилятор Haskell обрабатывает входные данные Haskell, но после удаления разметки literate и (возможно) обработки входных данных Haskell препроцессором C.
Используйте
-pgmF ⟨cmd⟩, чтобы выбрать программу для препроцессора. При запуске препроцессор ⟨cmd⟩ получает в командной строке как минимум три аргумента: первый — имя исходного файла, второй — имя файла с входными данными, третий — имя файла, в который ⟨cmd⟩ должен записать результат.Дополнительные аргументы препроцессору можно передать с помощью параметра
-optF ⟨option⟩. Они передаются ⟨cmd⟩ в командной строке после трёх стандартных аргументов ввода и вывода.Пример использования препроцессора — преобразование исходных файлов в кодировку, ожидаемую GHC: для этого создайте скрипт
convert.shсо следующим содержимым:#!/bin/sh ( echo "{-# LINE 1 \"$1\" #-}" ; iconv -f l1 -t utf-8 $2 ) > $3и передайте GHC параметр
-F -pgmF convert.sh. Параметр-f l1указывает iconv преобразовать файл в кодировке Latin-1, переданный в аргументе$2, а параметры «-t utf-8» указывают iconv вернуть файл в кодировке UTF-8. Результат перенаправляется в аргумент$3. Параметрecho "{-# LINE 1 \"$1\" #-}"лишь обеспечивает вывод позиций ошибок относительно исходного файла.