Глава 16. Компиляция в машинный код (ocamlopt)
В этой главе описан высокопроизводительный компилятор OCaml в машинный код ocamlopt, который компилирует исходные файлы OCaml в объектные файлы с машинным кодом и связывает эти объектные файлы, создавая автономные исполняемые файлы.
Компилятор в машинный код доступен только на некоторых платформах. Он создает код, который выполняется быстрее байт-кода, создаваемого ocamlc, но требует больше времени на компиляцию и создает исполняемые файлы большего размера. Совместимость с компилятором в байт-код чрезвычайно высока: один и тот же исходный код должен выполняться одинаково при компиляции с помощью ocamlc и ocamlopt.
Объектные файлы с машинным кодом, созданные ocamlopt, нельзя смешивать с объектными файлами с байт-кодом, созданными ocamlc: программа должна быть полностью скомпилирована с помощью ocamlopt или полностью с помощью ocamlc. Объектные файлы с машинным кодом, созданные ocamlopt, нельзя загрузить в интерактивную систему ocaml.
1 Обзор компилятора
Команда ocamlopt имеет интерфейс командной строки, очень похожий на интерфейс ocamlc. Она принимает аргументы тех же типов и обрабатывает их последовательно после обработки всех параметров:
- Аргументы, оканчивающиеся на .mli, рассматриваются как исходные файлы интерфейсов единиц компиляции. Интерфейсы задают имена, экспортируемые единицами компиляции: объявляют имена значений и их типы, определяют публичные типы данных, объявляют абстрактные типы данных и так далее. Из файла x.mli компилятор ocamlopt создает скомпилированный интерфейс в файле x.cmi. Созданный интерфейс идентичен интерфейсу, полученному с помощью компилятора в байт-код ocamlc.
- Аргументы, оканчивающиеся на .ml, рассматриваются как исходные файлы реализаций единиц компиляции. Реализации задают определения для имен, экспортируемых единицей, а также содержат выражения, которые вычисляются ради побочных эффектов. Из файла x.ml компилятор ocamlopt создает два файла: x.o, содержащий объектный код на машинном языке, и x.cmx, содержащий дополнительную информацию для связывания и оптимизации клиентских модулей этой единицы. На скомпилированную реализацию всегда следует ссылаться по имени x.cmx (если указан файл .o или .obj, ocamlopt предполагает, что он содержит код, скомпилированный из C, а не из OCaml).
Реализация проверяется на соответствие файлу интерфейса x.mli (если он существует), как описано в руководстве по ocamlc (глава 13).
- Аргументы, оканчивающиеся на .cmx, рассматриваются как скомпилированный объектный код. Эти файлы связываются вместе с объектными файлами, полученными при компиляции аргументов .ml (если они есть), и стандартной библиотекой OCaml для создания исполняемой программы с машинным кодом. Порядок, в котором аргументы .cmx и .ml указаны в командной строке, имеет значение: единицы компиляции инициализируются во время выполнения в этом порядке, и при связывании возникает ошибка, если компонент единицы используется до ее инициализации. Поэтому файл x.cmx должен располагаться перед всеми файлами .cmx, которые ссылаются на единицу x.
- Аргументы, оканчивающиеся на .cmxa, рассматриваются как библиотеки объектного кода. Такая библиотека объединяет в двух файлах (lib.cmxa и lib.a/.lib) набор объектных файлов (файлы .cmx и .o/.obj). Библиотеки создаются с помощью ocamlopt -a (см. описание параметра -a ниже). Объектные файлы из библиотеки связываются так же, как обычные файлы .cmx (см. выше), в порядке, заданном при создании библиотеки. Единственное отличие заключается в том, что если объектный файл из библиотеки нигде в программе не используется, он не включается в нее.
- Аргументы, оканчивающиеся на .c, передаются компилятору C, который создает объектный файл .o/.obj. Этот объектный файл связывается с программой.
- Аргументы, оканчивающиеся на .o, .a или .so (.obj, .lib и .dll в Windows), считаются объектными файлами и библиотеками C. Они связываются с программой.
Результатом этапа связывания является обычный исполняемый файл Unix или Windows. Для его выполнения не требуется ocamlrun.
Компилятор может выводить некоторую информацию о своих внутренних этапах:
-
Файлы .cmt для реализации единицы компиляции и .cmti для сигнатур создаются, если передан параметр -bin-annot (см. описание параметра -bin-annot ниже). Каждый такой файл содержит типизированное абстрактное синтаксическое дерево (AST), создаваемое в процессе проверки типов. Это дерево содержит всю доступную информацию о расположении и конкретном типе каждого элемента в исходном файле. Если проверка типов завершилась неудачно, AST будет неполным.
Эти файлы .cmt и .cmti обычно полезны инструментам для анализа кода.
-
Файлы .cmir-linear для реализации единицы компиляции создаются, если передан параметр -save-ir-after scheduling. Каждый такой файл содержит низкоуровневое промежуточное представление, создаваемое этапом планирования инструкций.
Внешний инструмент может выполнять низкоуровневые оптимизации, например изменять расположение кода, преобразуя файл .cmir-linear. Чтобы продолжить компиляцию, компилятору можно передать в качестве аргумента файл .cmir-linear (возможно, измененный) вместо соответствующего исходного файла.
2 Параметры
Команда ocamlopt распознает следующие параметры командной строки. Параметры -pack, -a, -shared, -c, -output-obj и -output-complete-obj взаимоисключающие.
- -a
- Создать библиотеку (файлы .cmxa и .a/.lib) из объектных файлов (файлы .cmx и .o/.obj), указанных в командной строке, вместо их компоновки в исполняемый файл. Имя библиотеки должно задаваться параметром -o.
Если в командной строке указаны параметры -cclib или -ccopt, они сохраняются в результирующей библиотеке .cmxa. Затем при компоновке с этой библиотекой параметры -cclib и -ccopt автоматически добавляются повторно, как если бы они были указаны в командной строке, если только не задан параметр -noautolink.
- -absname
- Выводить в сообщениях об ошибках абсолютные пути к файлам.
- -no-absname
- Не выводить абсолютные пути к файлам в сообщениях об ошибках.
- -annot
- Устарел начиная с OCaml 4.11. Используйте вместо него -bin-annot.
- -args filename
- Считать из filename дополнительные аргументы командной строки, разделённые символами новой строки.
- -args0 filename
- Считать из filename дополнительные аргументы командной строки, разделённые нулевыми символами.
- -bin-annot
- Сохранять подробную информацию о компиляции (типах, связываниях, хвостовых вызовах и т. д.) в двоичном формате. Информация для файла src.ml (соответственно, src.mli) помещается в файл src.cmt (соответственно, src.cmti). При ошибке типов сохранять всю информацию, выведенную проверкой типов до возникновения ошибки. Файлы *.cmt и *.cmti, созданные с помощью -bin-annot, содержат больше информации и значительно компактнее файлов, созданных с помощью -annot.
- -c
- Только компиляция. Пропустить этап компоновки. Файлы исходного кода преобразуются в скомпилированные файлы, но исполняемый файл не создаётся. Этот параметр полезен для раздельной компиляции модулей.
- -cc ccomp
- Использовать ccomp в качестве компоновщика C для сборки итогового исполняемого файла и в качестве компилятора C для компиляции исходных файлов .c. При компоновке объектных файлов, созданных компилятором C++ (например, g++ или clang++), рекомендуется использовать -cc c++.
- -cclib -llibname
- Передать компоновщику параметр -llibname. Это приводит к компоновке указанной библиотеки C с программой.
- -ccopt option
- Передать указанный параметр компилятору и компоновщику C. Например, -ccopt -Ldir указывает компоновщику C искать библиотеки C в каталоге dir.
- -cmi-file filename
- Использовать указанный файл интерфейса для проверки типов исходного файла ML, который нужно скомпилировать. Если этот параметр не указан, компилятор ищет файл .mli с тем же базовым именем, что и компилируемая реализация, в том же каталоге. Если такой файл найден, компилятор ищет соответствующий файл .cmi в подключённых каталогах и сообщает об ошибке, если не может его найти.
- -color mode
- Включить или отключить цвета в сообщениях компилятора (в частности, в предупреждениях и сообщениях об ошибках). Поддерживаются следующие режимы:
- auto
- использовать эвристики, чтобы включать цвета, только если вывод их поддерживает (терминал tty, совместимый с ANSI);
- always
- всегда включать цвета;
- never
- отключить цветной вывод.
Если параметр -color не указан, учитывается переменная окружения OCAML_COLOR. Её значения — auto/always/never, как указано выше.
Если параметр -color не указан, переменная окружения OCAML_COLOR не задана, а переменная окружения NO_COLOR задана, цветной вывод отключается. В противном случае используется значение по умолчанию ’auto’; текущая эвристика проверяет, что переменная окружения TERM существует и не является пустой или равной dumb, а также что выполняется условие ’isatty(stderr)’.
- -error-style mode
- Задать способ вывода сообщений об ошибках и предупреждений. Поддерживаются следующие режимы:
- short
- выводить только ошибку и её местоположение;
- contextual
- как short, но также отображать фрагмент исходного кода, соответствующий местоположению ошибки.
Если параметр -error-style не указан, учитывается переменная окружения OCAML_ERROR_STYLE. Её значения — short/contextual, как указано выше.
- -compact
- Оптимизировать созданный код для уменьшения размера, а не для повышения скорости. В результате программы получаются немного меньше, но немного медленнее. По умолчанию выполняется оптимизация скорости.
- -config
- Вывести номер версии ocamlopt и подробную сводку его конфигурации, затем завершить работу.
- -config-var var
- Вывести значение указанной переменной конфигурации из вывода -config, затем завершить работу. Если переменная не существует, возвращается ненулевой код завершения. Этот параметр доступен только начиная с OCaml 4.08, поэтому авторам скриптов следует предусмотреть альтернативный вариант для более ранних версий.
- -depend ocamldep-args
- Вычислить зависимости, как это делает команда ocamldep. Остальные аргументы интерпретируются так, как если бы они были переданы команде ocamldep.
- -for-pack module-path
- Создать объектный файл (файлы .cmx и .o/.obj), который впоследствии можно включить как подмодуль (с указанным путём доступа) в единицу компиляции, созданную с помощью -pack. Например, команда ocamlopt -for-pack P -c A.ml создаст файлы a.cmx и a.o, которые впоследствии можно использовать с командой ocamlopt -pack -o P.cmx a.cmx. Примечание: модуль можно упаковать и без компиляции с параметром -for-pack, но в этом случае исключения будут выводиться с неправильными именами.
- -g
- Добавлять отладочную информацию при компиляции и компоновке. Этот параметр необходим для создания трассировок стека при завершении программы из-за необработанного исключения (см. раздел 15.2).
- -no-g
- Не записывать отладочную информацию (значение по умолчанию).
- -i
- При компиляции реализации (файла .ml) вывести все определённые имена (с выведенными типами или определениями). Скомпилированные файлы (файлы .cmo и .cmi) не создаются. Это может быть полезно для проверки типов, выведенных компилятором. Кроме того, поскольку вывод соответствует синтаксису интерфейсов, он может помочь при написании явного интерфейса (файла .mli) для файла: просто перенаправьте стандартный вывод компилятора в файл .mli и отредактируйте его, удалив все объявления неэкспортируемых имён.
- -i-variance
- Выводить вычисленную вариативность параметров типов для каждого объявления типа. Без этого параметра вариативность выводится только для приватных типов или типов без манифеста (например, абстрактных типов).
- -I directory
- Добавить указанный каталог в список каталогов, в которых выполняется поиск скомпилированных файлов интерфейсов (.cmi), скомпилированных объектных файлов (.cmx) и библиотек (.cmxa). По умолчанию сначала выполняется поиск в текущем каталоге, затем — в каталоге стандартной библиотеки. Каталоги, добавленные с помощью -I, просматриваются после текущего каталога в порядке их указания в командной строке, но до каталога стандартной библиотеки. См. также параметр -nostdlib.
Если указанный каталог начинается с +, он считается относительно каталога стандартной библиотеки. Например, -I +unix добавляет подкаталог unix стандартной библиотеки в путь поиска.
- -H directory
- Работает так же, как -I, за исключением того, что (a) программы не могут напрямую ссылаться на модули, добавленные таким образом в путь поиска, и (b) эти каталоги просматриваются после всех каталогов -I. Это позволяет предоставить компилятору скомпилированные файлы интерфейсов и объектного кода для транзитивных зависимостей текущей программы (зависимостей её зависимостей), не позволяя им незаметно становиться прямыми зависимостями.
- -impl filename
- Скомпилировать файл filename как файл реализации, даже если его расширение не .ml.
- -inline n
- Задать агрессивность встраивания равной n, где n — положительное целое число. Указание -inline 0 запрещает встраивание всех функций, кроме тех, чьё тело меньше места вызова. Таким образом, встраивание не увеличивает размер кода. Значение агрессивности по умолчанию, -inline 1, позволяет встраивать немного более крупные функции, что приводит к небольшому увеличению размера кода. Более высокие значения параметра -inline позволяют рассматривать для встраивания всё более крупные функции, но могут привести к значительному увеличению размера кода.
- -intf filename
- Скомпилировать файл filename как файл интерфейса, даже если его расширение не .mli.
- -intf-suffix string
- Распознавать имена файлов, оканчивающиеся на string, как имена файлов интерфейсов (вместо расширения по умолчанию .mli).
- -keywords version+list
- Задать ключевые слова согласно спецификации version+list.
Эта спецификация начинается с необязательного номера версии, который определяет базовый набор ключевых слов, после чего следует разделённый символом + список дополнительных ключевых слов, добавляемых в этот набор.
Если номер версии не указан явно, базовым набором ключевых слов считается набор из текущей версии OCaml. Если в исходном коде встречаются дополнительные ключевые слова, которые не соответствуют ни одному известному ключевому слову текущей версии языка, возникает ошибка.
- -labels
- Метки учитываются в типах, их можно использовать при вызовах, а именованные параметры можно указывать в любом порядке. Это поведение используется по умолчанию.
- -linkall
- Принудительно включать в компоновку все модули, содержащиеся в библиотеках. Если этот флаг не указан, неиспользуемые модули не включаются в компоновку. При сборке библиотеки (параметр -a) параметр -linkall заставляет все последующие компоновки программ с этой библиотекой включать в них все содержащиеся в ней модули. При компиляции модуля (параметр -c) параметр -linkall гарантирует, что этот модуль всегда будет включён в компоновку, если он помещён в библиотеку и эта библиотека компонуется.
- -linscan
- Использовать линейное сканирование для распределения регистров. Компиляция с этим распределителем выполняется быстрее, чем с обычным распределителем на основе раскраски графа; для длинных функций и модулей ускорение иногда бывает весьма значительным. С другой стороны, сгенерированный код может работать немного медленнее.
- -match-context-rows number
- Задать число строк контекста, используемых для оптимизации при компиляции сопоставления с образцом. Значение по умолчанию — 32. Меньшие значения ускоряют компиляцию, но приводят к менее оптимизированному коду. Этот дополнительный параметр предназначен для случаев, когда программа с большим количеством сопоставлений с образцом значительно увеличивает время компиляции.
- -no-alias-deps
- Не записывать зависимости для псевдонимов модулей. Дополнительные сведения см. в разделе 12.8.
- -no-app-funct
- Отключить аппликативное поведение функторов. При использовании этого параметра каждое применение функтора создаёт новые типы в результате, а применение одного и того же функтора дважды к одному и тому же аргументу даёт две несовместимые структуры.
- -no-float-const-prop
- Отключить распространение констант для операций с плавающей точкой. Этот параметр следует указывать, если программа изменяет режим округления чисел с плавающей точкой во время выполнения.
- -noassert
- Не компилировать проверки утверждений. Обратите внимание, что специальная форма assert false всегда компилируется, поскольку для неё предусмотрена специальная обработка типов. Этот флаг не влияет на компоновку уже скомпилированных файлов.
- -noautolink
- При компоновке библиотек .cmxa игнорировать параметры -cclib и -ccopt, которые могут содержаться в библиотеках (если эти параметры были указаны при сборке библиотек). Это может быть полезно, если библиотека содержит некорректные указания библиотек C или параметров C; в этом случае при компоновке укажите -noautolink и передайте правильные библиотеки C и параметры в командной строке.
- -nodynlink
- Разрешить компилятору использовать некоторые оптимизации, корректные только для кода со статической компоновкой, чтобы создать нерелокируемый исполняемый файл. Сгенерированный код нельзя скомпоновать в разделяемую библиотеку или позиционно-независимый исполняемый файл (PIE). Многие операционные системы по умолчанию создают файлы PIE, что приводит к ошибкам при компоновке кода, скомпилированного с параметром -nodynlink. Либо не используйте -nodynlink, либо передайте параметр -ccopt -no-pie на этапе компоновки.
- -nolabels
- Игнорировать необязательные метки в типах. Метки нельзя использовать при вызовах, а порядок параметров становится строгим.
- -nostdlib
- Не добавлять автоматически каталог стандартной библиотеки в список каталогов, в которых выполняется поиск скомпилированных файлов интерфейсов (.cmi), скомпилированных объектных файлов (.cmx) и библиотек (.cmxa). См. также параметр -I.
- -o filename
- Задать имя итогового выходного файла: исполняемого файла, скомпилированного объекта (параметр -c), библиотеки (параметр -a), упакованного объекта (параметр -pack), подключаемого модуля для динамической компоновки (параметр -shared) или файла исходного кода либо объектного файла C (параметры -output-obj и -output-complete-obj).
Имя исполняемого файла по умолчанию зависит от платформы: в Unix это a.out, в Windows — camlprog.exe.
Этот параметр также можно использовать при компиляции файла интерфейса или реализации без компоновки (параметр -c); в этом случае он задаёт имя файла cmi или .cmx, а также имя единицы компиляции, взятое из filename до первой точки.
- -opaque
- При компиляции реализации нативный компилятор по умолчанию создаёт файл .cmx, содержащий сведения для межмодульной оптимизации. Он также ожидает наличия файлов .cmx для зависимостей компилируемого исходного кода и использует их для оптимизации. Начиная с OCaml 4.03 компилятор выдаёт предупреждение, если не может найти файл .cmx для одной из таких зависимостей.
Параметр -opaque, доступный начиная с версии 4.04, отключает сведения для межмодульной оптимизации текущей компилируемой единицы. При компиляции интерфейса .mli использование -opaque помечает скомпилированный интерфейс .cmi, чтобы последующие компиляции зависящих от него модулей не использовали соответствующий файл .cmx и не выдавали предупреждение при его отсутствии. При компиляции нативным компилятором реализации .ml использование -opaque создаёт файл .cmx, не содержащий сведений для межмодульной оптимизации.
Использование этого параметра может ухудшить качество сгенерированного кода, но сокращает время компиляции как при чистой, так и при инкрементальной сборке. Действительно, при использовании нативного компилятора изменение реализации единицы компиляции может потребовать повторной компиляции всех зависящих от неё единиц, поскольку сведения для межмодульной оптимизации могли измениться. Если реализация изменённой единицы компиляции была скомпилирована с параметром -opaque, повторная компиляция не требуется. Поэтому этот параметр можно использовать, например, чтобы ускорить циклы редактирования, компиляции и тестирования.
- -open Module
- Открыть указанный модуль перед обработкой файлов интерфейса или реализации. Если указано несколько параметров -open, они обрабатываются по порядку, как если бы в начало каждого файла были добавлены инструкции open! Module1;; ... open! ModuleN;;.
- -output-obj
- Указать компоновщику создать объектный файл C вместо исполняемого файла. Это полезно для упаковки кода OCaml в библиотеку C, которую можно вызывать из любой программы на C. См. главу 23, раздел 23.7.6. Имя выходного объектного файла должно задаваться параметром -o. Этот параметр также можно использовать для создания скомпилированной разделяемой/динамической библиотеки (с расширением .so, а в Windows — .dll).
- -output-complete-obj
- То же, что и параметр -output-obj, за исключением того, что созданный объектный файл включает среду выполнения и библиотеки автокомпоновки.
- -pack
- Создаёт объектный файл (.cmx и .o/.obj) и связанный с ним скомпилированный интерфейс (.cmi), объединяющий объектные файлы .cmx, указанные в командной строке, и представляющий их в виде подмодулей выходного файла .cmx. Имя выходного файла .cmx необходимо указать с помощью параметра -o. Например,
ocamlopt -pack -o P.cmx A.cmx B.cmx C.cmx
создаёт скомпилированные файлы P.cmx, P.o и P.cmi, описывающие единицу компиляции с тремя подмодулями A, B и C, соответствующими содержимому объектных файлов A.cmx, B.cmx и C.cmx. В остальной части программы к этому содержимому можно обращаться как к P.A, P.B и P.C.Объектные файлы .cmx, объединяемые таким образом, должны быть скомпилированы с соответствующим параметром -for-pack. В приведённом выше примере файлы A.cmx, B.cmx и C.cmx должны быть скомпилированы командой ocamlopt -for-pack P.
Несколько уровней упаковки можно получить, комбинируя параметры -pack и -for-pack. Рассмотрим следующий пример:
ocamlopt -for-pack P.Q -c A.ml ocamlopt -pack -o Q.cmx -for-pack P A.cmx ocamlopt -for-pack P -c B.ml ocamlopt -pack -o P.cmx Q.cmx B.cmxПолученный объектный файл P.cmx содержит подмодули P.Q, P.Q.A и P.B.
- -pp command
- Указывает компилятору вызывать заданную команду в качестве препроцессора для каждого исходного файла. Вывод команды перенаправляется во временный файл, который затем компилируется. Если ошибок компиляции нет, временный файл удаляется.
- -ppx command
- После разбора передаёт абстрактное синтаксическое дерево препроцессору command. Модуль Ast_mapper, описанный в главе 31: Ast_mapper , реализует внешний интерфейс препроцессора.
- -principal
- Проверяет путь информации во время проверки типов, чтобы убедиться, что все типы выводятся принципиальным образом. При использовании именованных аргументов и/или полиморфных методов этот параметр необходим, чтобы гарантировать, что будущие версии компилятора смогут корректно выводить типы, даже если внутренние алгоритмы изменятся. Все программы, принимаемые в режиме -principal, также принимаются в режиме по умолчанию с эквивалентными типами, но с другими двоичными сигнатурами; при этом проверка типов может выполняться медленнее. Тем не менее перед публикацией исходного кода рекомендуется использовать этот параметр.
- -rectypes
- Разрешает произвольные рекурсивные типы во время проверки типов. По умолчанию поддерживаются только рекурсивные типы, в которых рекурсия проходит через тип объекта. Обратите внимание: создав интерфейс с этим параметром, вы должны использовать его и для всех зависимостей.
- -runtime-variant suffix
- Добавляет строку suffix к имени библиотеки среды выполнения, используемой программой. В настоящее время поддерживается только один такой суффикс: d, и только если компилятор OCaml был настроен с параметром -with-debug-runtime. Этот суффикс указывает на отладочную версию среды выполнения, полезную для отладки проблем с указателями в низкоуровневом коде, например в заглушках C.
- -S
- Сохраняет ассемблерный код, созданный во время компиляции. Ассемблерный код для исходного файла x.ml сохраняется в файле x.s.
- -safe-string
- Обеспечивает разделение типов string и bytes, делая строки доступными только для чтения. Это поведение используется по умолчанию и принудительно применяется начиная с OCaml 5.0.
- -safer-matching
- Не использует информацию о типах для оптимизации сопоставления с образцом. Это позволяет обнаруживать ошибки сопоставления, даже если ошибочно предполагалось, что сопоставление с образцом является исчерпывающим. Это влияет только на компиляцию GADT и полиморфных вариантов.
- -save-ir-after pass
- Сохраняет промежуточное представление после указанного этапа компиляции в файл. В настоящее время поддерживаются следующие этапы и соответствующие им расширения файлов: scheduling (.cmir-linear).
Эта экспериментальная возможность позволяет внешним инструментам изучать и изменять промежуточное представление программы компилятора с помощью библиотеки compiler-libs (см. главу 31 и Compiler_libs ).
- -set-runtime-default name=value
- При компоновке исполняемого файла переопределяет значение параметра среды выполнения по умолчанию. В настоящее время поддерживаются следующие параметры:
- standard_library_default
- Указывает расположение по умолчанию, которое исполняемый файл использует для поиска стандартной библиотеки. По умолчанию это абсолютный путь к стандартной библиотеке, с которой был настроен сам компилятор.
- -shared
- Создаёт плагин (обычно файл .cmxs), который можно динамически загружать с помощью модуля Dynlink. Имя плагина задаётся параметром -o. Плагин может включать несколько модулей и библиотек OCaml, а также дополнительные объектные файлы машинного кода (.o, .obj, .a, .lib). Создание плагинов машинного кода поддерживается только в некоторых операционных системах. В некоторых системах (в настоящее время только в Linux AMD 64) весь код OCaml, включаемый в плагин, должен быть скомпилирован без параметра -nodynlink. Также могут действовать некоторые ограничения на способ компиляции дополнительных объектных файлов машинного кода (в Linux AMD 64 они должны содержать только позиционно-независимый код).
- -short-paths
- Если тип доступен по нескольким путям модулей, использует кратчайший путь при выводе имени типа в выведенных интерфейсах и сообщениях об ошибках и предупреждениях. Имена идентификаторов, начинающиеся с подчёркивания _ или содержащие двойное подчёркивание __, получают штраф +10 при вычислении длины.
- -stop-after pass
- Останавливает компиляцию после указанного этапа компиляции. В настоящее время поддерживаются следующие этапы: parsing, typing, scheduling, emit.
- -strict-sequence
- Требует, чтобы левая часть каждой последовательности имела тип unit.
- -strict-formats
- Отклоняет некорректные форматы, которые принимались в устаревших реализациях форматов. Используйте этот параметр, чтобы обнаружить и исправить такие некорректные форматы, поскольку будущие версии OCaml будут их отклонять.
- -unboxed-types
- Если тип допускает представление без упаковки (то есть это запись с одним полем или конкретный тип данных с одним конструктором и одним аргументом), он будет представлен без упаковки, если не снабжён аннотацией [@@ocaml.boxed].
- -no-unboxed-types
- Если тип допускает представление без упаковки, он будет представлен с упаковкой, если не снабжён аннотацией [@@ocaml.unboxed]. Это поведение используется по умолчанию.
- -unsafe
- Отключает проверку границ при обращении к массивам и строкам (конструкции v.(i) и s.[i]). Поэтому программы, скомпилированные с параметром -unsafe, работают быстрее, но небезопасны: если программа обращается к элементу массива или строки за пределами их границ, возможно любое поведение. Кроме того, отключается проверка деления на ноль в операциях целочисленного деления и вычисления остатка. При использовании -unsafe деление (или вычисление остатка) целого числа на ноль может остановить программу либо продолжиться с неопределённым результатом вместо вызова исключения Division_by_zero.
- -unsafe-string
- Объединяет типы string и bytes, делая строки доступными для записи. Этот параметр предназначен для совместимости со старым исходным кодом и не должен использоваться в новом программном обеспечении. Начиная с OCaml 5.0 этот параметр всегда вызывает ошибку.
- -v
- Выводит номер версии компилятора и расположение каталога стандартной библиотеки, затем завершает работу.
- -verbose
- Перед выполнением выводит все внешние команды, в частности вызовы ассемблера, компилятора C и компоновщика. Полезно для отладки проблем с библиотеками C.
- -version or -vnum
- Выводит номер версии компилятора в краткой форме (например, 3.11.0), затем завершает работу.
- -w warning-list
- Включает, отключает или помечает как фатальные предупреждения, указанные аргументом warning-list. Каждое предупреждение может быть включено или отключено, а также может быть фатальным или нефатальным. Если предупреждение отключено, оно не отображается и никак не влияет на компиляцию (даже если оно фатальное). Если предупреждение включено, компилятор отображает его обычным образом всякий раз, когда его вызывает исходный код. Если предупреждение включено и является фатальным, после его отображения компилятор также завершит работу с ошибкой.
Аргумент warning-list представляет собой последовательность спецификаторов предупреждений без разделителей между ними. Спецификатор предупреждения — один из следующих:
- +num
- Включить предупреждение с номером num.
- -num
- Отключить предупреждение с номером num.
- @num
- Включить и пометить как фатальное предупреждение с номером num.
- +num1..num2
- Включить предупреждения в указанном диапазоне.
- -num1..num2
- Отключить предупреждения в указанном диапазоне.
- @num1..num2
- Включить и пометить как фатальные предупреждения в указанном диапазоне.
- +letter
- Включить набор предупреждений, соответствующий letter. Буква может быть прописной или строчной.
- -letter
- Отключить набор предупреждений, соответствующий letter. Буква может быть прописной или строчной.
- @letter
- Включить и пометить как фатальные набор предупреждений, соответствующий letter. Буква может быть прописной или строчной.
- uppercase-letter
- Включить набор предупреждений, соответствующий uppercase-letter.
- lowercase-letter
- Отключить набор предупреждений, соответствующий lowercase-letter.
Кроме того, warning-list может задавать одно предупреждение с помощью его мнемонического имени (см. ниже) следующим образом:
- +name
- Включить предупреждение name.
- -name
- Отключить предупреждение name.
- @name
- Включить и пометить как фатальное предупреждение name.
Номера, буквы и имена предупреждений, которые в настоящее время не определены, игнорируются. Список предупреждений приведён ниже (имя после каждого номера — мнемоническое имя этого предупреждения).
- 1 comment-start
- Подозрительно выглядящий маркер начала комментария.
- 2 comment-not-end
- Подозрительно выглядящий маркер конца комментария.
- 3
- Устаревший синоним предупреждения «deprecated».
- 4 fragile-match
- Ненадёжное сопоставление с образцом: сопоставление, которое останется полным, даже если к одному из сопоставляемых вариантовных типов будут добавлены дополнительные конструкторы.
- 5 ignored-partial-application
- Частично применённая функция: выражение, результат которого имеет функциональный тип и игнорируется.
- 6 labels-omitted
- Метка пропущена при применении функции.
- 7 method-override
- Метод переопределён.
- 8 partial-match
- Неполное сопоставление: отсутствуют варианты в сопоставлении с образцом.
- 9 missing-record-field-pattern
- В образце записи отсутствуют поля.
- 10 non-unit-statement
- Выражение в левой части последовательности не имеет типа unit (и не является функцией, см. предупреждение номер 5).
- 11 redundant-case
- Избыточный вариант в сопоставлении с образцом (неиспользуемый вариант сопоставления).
- 12 redundant-subpat
- Избыточный подобразец в сопоставлении с образцом.
- 13 instance-variable-override
- Переменная экземпляра переопределена.
- 14 illegal-backslash
- Недопустимая escape-последовательность с обратной косой чертой в строковой константе.
- 15 implicit-public-methods
- Приватный метод неявно стал публичным.
- 16 unerasable-optional-argument
- Неустранимый необязательный аргумент.
- 17 undeclared-virtual-method
- Необъявленный виртуальный метод.
- 18 not-principal
- Непринципиальный тип.
- 19 non-principal-labels
- Тип без свойства принципиальности.
- 20 ignored-extra-argument
- Неиспользуемый аргумент функции.
- 21 nonreturning-statement
- Инструкция, не возвращающая управление.
- 22 preprocessor
- Предупреждение препроцессора.
- 23 useless-record-with
- Бесполезная часть записи with.
- 24 bad-module-name
- Некорректное имя модуля: имя исходного файла не является допустимым именем модуля OCaml.
- 25
- Игнорируется: теперь входит в предупреждение 8.
- 26 unused-var
- Подозрительная неиспользуемая переменная: неиспользуемая переменная, связанная с помощью let или as и имя которой не начинается с символа подчёркивания (_).
- 27 unused-var-strict
- Безобидная неиспользуемая переменная: неиспользуемая переменная, не связанная ни с помощью let, ни с помощью as, и имя которой не начинается с символа подчёркивания (_).
- 28 wildcard-arg-to-constant-constr
- Образец-шаблон передан в качестве аргумента конструктору без аргументов.
- 29 eol-in-string
- Незаэкранированный конец строки в строковой константе (непереносимый код).
- 30 duplicate-definitions
- Две метки или конструктора с одинаковым именем определены в двух взаимно рекурсивных типах.
- 31 module-linked-twice
- Модуль дважды скомпонован в одном исполняемом файле. Игнорируется: теперь это критическая ошибка (начиная с версии 5.1).
- 32 unused-value-declaration
- Неиспользуемое объявление значения. (начиная с версии 4.00)
- 33 unused-open
- Неиспользуемая инструкция open. (начиная с версии 4.00)
- 34 unused-type-declaration
- Неиспользуемое объявление типа. (начиная с версии 4.00)
- 35 unused-for-index
- Неиспользуемый индекс цикла for. (начиная с версии 4.00)
- 36 unused-ancestor
- Неиспользуемая переменная предка. (начиная с версии 4.00)
- 37 unused-constructor
- Неиспользуемый конструктор. (начиная с версии 4.00)
- 38 unused-extension
- Неиспользуемый конструктор расширения. (начиная с версии 4.00)
- 39 unused-rec-flag
- Неиспользуемый флаг rec. (начиная с версии 4.00)
- 40 name-out-of-scope
- Имя конструктора или метки используется вне области видимости. (начиная с версии 4.01)
- 41 ambiguous-name
- Неоднозначное имя конструктора или метки. (начиная с версии 4.01)
- 42 disambiguated-name
- Имя конструктора или метки разрешено как неоднозначное (предупреждение о совместимости). (начиная с версии 4.01)
- 43 nonoptional-label
- Необязательный аргумент применён к обязательной метке. (начиная с версии 4.01)
- 44 open-shadow-identifier
- Инструкция open затеняет уже определённый идентификатор. (начиная с версии 4.01)
- 45 open-shadow-label-constructor
- Инструкция open затеняет уже определённую метку или конструктор. (начиная с версии 4.01)
- 46 bad-env-variable
- Ошибка в переменной окружения. (начиная с версии 4.01)
- 47 attribute-payload
- Недопустимая полезная нагрузка атрибута. (начиная с версии 4.02)
- 48 eliminated-optional-arguments
- Неявное устранение необязательных аргументов. (начиная с версии 4.02)
- 49 no-cmi-file
- Отсутствует файл cmi при поиске псевдонима модуля. (начиная с версии 4.02)
- 50 unexpected-docstring
- Неожиданный комментарий документации. (начиная с версии 4.03)
- 51 wrong-tailcall-expectation
- Вызов функции помечен некорректным атрибутом @tailcall. (начиная с версии 4.03)
- 52 fragile-literal-pattern (см. 13.5.3)
- Ненадёжный образец-константа. (начиная с версии 4.03)
- 53 misplaced-attribute
- Атрибут не может использоваться в этом контексте. (начиная с версии 4.03)
- 54 duplicated-attribute
- Атрибут использован в выражении более одного раза. (начиная с версии 4.03)
- 55 inlining-impossible
- Встраивание невозможно. (начиная с версии 4.03)
- 56 unreachable-case
- Недостижимый вариант в сопоставлении с образцом (на основании информации о типах). (начиная с версии 4.03)
- 57 ambiguous-var-in-pattern-guard (см. 13.5.4)
- Неоднозначные переменные в альтернативном образце под условием. (начиная с версии 4.03)
- 58 no-cmx-file
- Отсутствует файл cmx. (начиная с версии 4.03)
- 59 flambda-assignment-to-non-mutable-value
- Присваивание неизменяемому значению. (начиная с версии 4.03)
- 60 unused-module
- Неиспользуемое объявление модуля. (начиная с версии 4.04)
- 61 unboxable-type-in-prim-decl
- Нераспаковываемый тип в объявлении примитива. (начиная с версии 4.04)
- 62 constraint-on-gadt
- Ограничение типа в объявлении типа GADT. (начиная с версии 4.06)
- 63 erroneous-printed-signature
- Некорректно выведенная сигнатура. (начиная с версии 4.08)
- 64 unsafe-array-syntax-without-parsing
- Параметр -unsafe использован с препроцессором, возвращающим синтаксическое дерево. (начиная с версии 4.08)
- 65 redefining-unit
- Объявление типа определяет новый конструктор ’()’. (начиная с версии 4.08)
- 66 unused-open-bang
- Неиспользуемая инструкция open!. (начиная с версии 4.08)
- 67 unused-functor-parameter
- Неиспользуемый параметр функтора. (начиная с версии 4.10)
- 68 match-on-mutable-state-prevent-uncurry
- Сопоставление с образцом, зависящее от изменяемого состояния, препятствует раскручиванию оставшихся аргументов. (начиная с версии 4.12)
- 69 unused-field
- Неиспользуемое поле записи. (начиная с версии 4.13)
- 70 missing-mli
- Отсутствует файл интерфейса. (начиная с версии 4.13)
- 71 unused-tmc-attribute
- Неиспользуемый атрибут @tail_mod_cons. (начиная с версии 4.14)
- 72 tmc-breaks-tailcall
- Хвостовой вызов превращается в обычный вызов в результате преобразования @tail_mod_cons. (начиная с версии 4.14)
- 73 generative-application-expects-unit
- Генеративный функтор применён к пустой структуре (struct end), а не к (). (начиная с версии 5.1)
- 74 degraded-to-partial-match
- Сопоставление с образцом компилируется как неполное, хотя выглядит полным. (начиная с версии 5.3)
- 75 unnecessarily-partial-tuple-pattern
- Образец кортежа заканчивается на .., хотя полностью соответствует ожидаемому типу. (начиная с версии 5.4)
- A
- все предупреждения
- C
- предупреждения 1, 2.
- D
- Псевдоним предупреждения 3.
- E
- Псевдоним предупреждения 4.
- F
- Псевдоним предупреждения 5.
- K
- предупреждения 32, 33, 34, 35, 36, 37, 38, 39.
- L
- Псевдоним предупреждения 6.
- M
- Псевдоним предупреждения 7.
- P
- Псевдоним предупреждения 8.
- R
- Псевдоним предупреждения 9.
- S
- Псевдоним предупреждения 10.
- U
- предупреждения 11, 12.
- V
- Псевдоним предупреждения 13.
- X
- предупреждения 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 30.
- Y
- Псевдоним предупреждения 26.
- Z
- Псевдоним предупреждения 27.
По умолчанию используется настройка -w +a-4-7-9-27-29-30-32..42-44-45-48-50-60-66..70-74. Она отображается командой ocamlopt -help. Обратите внимание, что предупреждения 5 и 10 возникают не всегда — это зависит от внутреннего устройства средства проверки типов.
- -warn-error warning-list
- Помечает как фатальные предупреждения, указанные аргументом warning-list. При появлении одного из этих предупреждений компилятор завершит работу с ошибкой. Аргумент warning-list имеет то же значение, что и для параметра -w: знак + (или прописная буква) помечает соответствующие предупреждения как фатальные, знак - (или строчная буква) снова делает их нефатальными, а знак @ одновременно включает соответствующие предупреждения и помечает их как фатальные.
Примечание: не рекомендуется использовать наборы предупреждений (то есть буквы) в качестве аргументов -warn-error в рабочем коде, поскольку новые предупреждения в будущих версиях OCaml могут привести к сбою сборки.
По умолчанию используется настройка -warn-error -a (ни одно предупреждение не является фатальным).
- -warn-help
- Показать описание всех доступных номеров предупреждений.
- -where
- Вывести расположение стандартной библиотеки и завершить работу.
- -with-runtime
- Пара параметров -with-runtime и -without-runtime позволяет точно управлять способом компоновки среды выполнения. По умолчанию используется -with-runtime. Вкратце, этот параметр указывает включить систему времени выполнения или ссылку на её путь по умолчанию в создаваемую программу, исполняемый файл или объектный файл. Точное поведение зависит от используемого компилятора и параметров:
Для ocamlc в режиме компоновки по умолчанию (без использования -custom или -output-*) параметр -with-runtime создаёт файл, который можно выполнить, тогда как -without-runtime создаёт чистый байт-код, который необходимо явно передать среде выполнения (то есть ./foo или ocamlrun ./foo).
Во всех остальных случаях использования ocamlc и ocamlopt параметры -with-runtime и -without-runtime определяют, передаёт ли компилятор флаги для компоновки с установленной средой выполнения (-with-runtime) или пользователь должен передать их самостоятельно (-without-runtime).
Дополнительные сведения о параметрах -custom и -output-* см. в их документации и в разделе 23.7.6 руководства.
- -without-runtime
- Компилятор не включает систему времени выполнения (и ссылку на неё) в создаваемую программу, исполняемый или объектный файл; её необходимо предоставить отдельно. Подробности см. в описании параметра -with-runtime.
- - file
- Обработать file как имя файла, даже если оно начинается со знака дефиса (-).
- -help или --help
- Показать краткую сводку по использованию и завершить работу.
Параметры для 64-разрядной архитектуры x86
Генератор 64-разрядного кода для процессоров Intel/AMD x86 (архитектура amd64) поддерживает следующие дополнительные параметры:
- -fPIC
- Генерировать машинный код, независимый от расположения. Это поведение используется по умолчанию.
- -fno-PIC
- Генерировать машинный код, зависимый от расположения.
Контекстное управление параметрами командной строки
Командную строку компилятора можно изменять «извне» с помощью следующих механизмов. Они являются экспериментальными и могут измениться. Их следует использовать только для экспериментов и разработки, но не в выпущенных пакетах.
- OCAMLPARAM (переменная окружения)
- Набор аргументов, которые будут вставлены перед аргументами командной строки или после них. Аргументы задаются в виде списка пар name=value, разделённых запятыми. Для указания позиции аргументов командной строки используется _, то есть a=x,_,b=y означает, что a=x следует обработать до разбора аргументов, а b=y — после. Наконец, в качестве первого символа строки можно указать альтернативный разделитель из набора :|; ,.
- ocaml_compiler_internal_params (файл в каталоге stdlib)
- Сопоставление имён файлов со списками аргументов, которые будут добавлены в командную строку (и к аргументам OCAMLPARAM).
3 Распространённые ошибки
Сообщения об ошибках почти идентичны сообщениям ocamlc. См. раздел 13.4.
4 Запуск исполняемых файлов, созданных ocamlopt
Исполняемые файлы, созданные ocamlopt, являются автономными исполняемыми файлами с машинным кодом, которые можно запускать напрямую. Они не зависят от байт-кодовой системы выполнения ocamlrun и динамически загружаемых заглушечных библиотек C/OCaml.
При выполнении исполняемого файла, созданного ocamlopt, также учитываются следующие переменные окружения:
- OCAMLRUNPARAM
- Используется так же, как и в ocamlrun (см. раздел 15.2), за исключением того, что параметр l игнорируется (вместо него используется ограничение размера стека, установленное операционной системой).
- CAMLRUNPARAM
- Если переменная OCAMLRUNPARAM не найдена в окружении, вместо неё используется CAMLRUNPARAM. Если CAMLRUNPARAM не найдена, используются значения по умолчанию.
Windows: В Windows исполняемый файл, созданный ocamlopt, раскрывает подстановочные символы * и ? в аргументах прежде, чем выполнить что-либо ещё. Массив строк Sys.argv формируется с использованием раскрытых аргументов. Чтобы избежать такого поведения, можно написать собственную точку входа на C, как описано в разделе 23.7.5.
5 Совместимость с компилятором байт-кода
В этом разделе перечислены известные несовместимости между компилятором байт-кода и компилятором машинного кода. За исключением этих случаев, оба компилятора должны генерировать код, который ведёт себя одинаково.
- Сигналы обнаруживаются только тогда, когда программа выполняет выделение памяти в куче. То есть, если сигнал поступает во время выполнения участка кода, который не выделяет память, его обработчик не будет вызван до следующего выделения памяти в куче.
- На процессорах ARM и PowerPC (32- и 64-разрядных) для умножения чисел с плавающей точкой с последующим сложением или вычитанием, например x *. y +. z, могут генерироваться инструкции слитного умножения-сложения (FMA). Инструкция FMA позволяет избежать округления промежуточного результата x *. y, что обычно полезно, но приводит к результатам вычислений с плавающей точкой, немного отличающимся от результатов интерпретатора байт-кода.
- Компилятор машинного кода выполняет ряд оптимизаций, которые не выполняет компилятор байт-кода, особенно при активном оптимизаторе Flambda. В частности, компилятор машинного кода обнаруживает и удаляет «мёртвый код», то есть вычисления, не влияющие на результаты программы. Например,
let _ = ignore M.f
содержит ссылку на единицу компиляции M при компиляции в байт-код. Эта ссылка заставляет компоновщик подключить M и выполнить её код инициализации. Компилятор машинного кода удаляет ссылку на M, поэтому единица компиляции M может не быть подключена и выполнена. В качестве обходного решения скомпилируйте M с флагом -linkall, чтобы она всегда подключалась и выполнялась, даже если на неё нет ссылок. См. также функцию Sys.opaque_identity из стандартного модуля библиотеки Sys. - До версии 4.10 переполнение стека, обычно вызванное чрезмерно глубокой рекурсией, не всегда преобразуется в исключение Stack_overflow, как это происходит с компилятором байт-кода. Система выполнения старается перехватывать переполнение стека и возбуждать исключение Stack_overflow, но иногда это не удаётся, и вместо этого возникает «ошибка сегментации» или другая системная ошибка.
© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/native.html