Spec-Zone.ru › Nim

Руководство пользователя компилятора Nim

Исходный кодИзменить

"Посмотри на себя, хакер. Жалкая тварь из плоти и крови, задыхающаяся и потеющая, пока бежишь по моим коридорам. Как ты можешь бросить вызов совершенной, бессмертной машине?"

Введение

Этот документ описывает использование компилятора Nim на различных поддерживаемых платформах. Это не определение языка программирования Nim (которое описано в руководстве).

Nim — это свободное программное обеспечение; оно лицензировано по лицензии MIT.

Использование компилятора

Переключатели командной строки

Все параметры, принимающие аргумент PATH или DIR, подвержены подстановке путей:

  • $nim: Глобальный путь префикса nim
  • $lib: Путь stdlib
  • $home и ~: Путь домашней директории пользователя
  • $config: Директория модуля, который компилируется в данный момент
  • $projectname: Имя файла проекта без расширения
  • $projectpath и $projectdir: Путь к файлу проекта
  • $nimcache: Путь nimcache

Основные переключатели командной строки:

Использование:

nim command [options] [projectfile] [arguments]

Команда:

compile, c
компиляция проекта с использованием по умолчанию кодогенератора (C)
r
компиляция в $nimcache/projname, запуск с arguments с помощью бэкенда, указанного --backend (по умолчанию: c)
doc
генерирует документацию для входного файла для бэкенда, указанного --backend (по умолчанию: c)

Аргументы: аргументы передаются выполняемой программе (если выбран параметр --run)

Параметры:

-p, --path:PATH
добавление пути в пути поиска
-d, --define:SYMBOL(:VAL)
определение условного символа (необязательно: определение значения этого символа, см.: «макросы времени компиляции»)
-u, --undef:SYMBOL
отключение условного символа
-f, --forceBuild:on|off
принудительная перекомпиляция всех модулей
--stackTrace:on|off
включение/выключение отслеживания стека
--lineTrace:on|off
включение/выключение отслеживания строк
--threads:on|off
включение/выключение поддержки многопоточности
-x, --checks:on|off
включение/выключение всех проверок во время выполнения
-a, --assertions:on|off
включение/выключение проверок assert
--opt:none|speed|size
оптимизация не совсем или для скорости/размера. Примечание: используйте -d:release для сборки релизной версии!
--debugger:native
использование встроенного отладчика (gdb)
--app:console|gui|lib|staticlib
генерация консольного приложения/приложения GUI/DLL/статической библиотеки
-r, --run
запуск скомпилированной программы с заданными аргументами
--eval:cmd
прямая оценка кода nim; например: nim --eval:"echo 1" по умолчанию e (nimscript), но настраиваемое: nim r --eval:'for a in stdin.lines: echo a'
--fullhelp
отображение всех переключателей командной строки
-h, --help
отображение этого справки
-v, --version
отображение подробной информации о версии

Обратите внимание, что однобуквенные параметры, принимающие аргумент, требуют двоеточия. Например, -p:PATH.


Расширенные переключатели командной строки:

Расширенные команды:
compileToC, cc
компиляция проекта с использованием кодогенератора C
compileToCpp, cpp
компиляция проекта в код C++
compileToOC, objc
компиляция проекта в код Objective C
js
компиляция проекта в Javascript
e
запуск файла Nimscript
md2html
преобразование файла Markdown в HTML, используйте --docCmd:skip, чтобы пропустить компиляцию фрагментов
rst2html
преобразование файла reStructuredText в HTML, используйте --docCmd:skip для пропуска компиляции фрагментов
md2tex
преобразование файла Markdown в LaTeX
rst2tex
преобразование файла reStructuredText в LaTeX
doc2tex
извлечение документации в файл LaTeX
jsondoc
извлечение документации в файл json
ctags
создание файла тегов
buildIndex
создание индекса для всей документации
genDepend
генерация файла DOT, содержащего граф зависимостей модулей
dump
вывод всех определенных условных символов и путей поиска, см. также: --dump.format:json (полезно с: | jq)
check
проверка проекта на синтаксические и семантические ошибки (можно сочетать с --defusages)

Проверки во время выполнения (см. -x):

--objChecks:on|off
включение/выключение проверок преобразования obj
--fieldChecks:on|off
включение/выключение проверок полей вариантов case
--rangeChecks:on|off
включение/выключение проверок диапазонов
--boundChecks:on|off
включение/выключение проверок границ
--overflowChecks:on|off
включение/выключение проверок переполнения/потерь целочисленных значений
--floatChecks:on|off
включение/выключение всех проверок чисел с плавающей точкой (NaN/Inf)
--nanChecks:on|off
включение/выключение проверок NaN
--infChecks:on|off
включение/выключение проверок Inf

Расширенные параметры:

--defusages:FILE,LINE,COL
найти определение и все использования символа
-o:FILE, --out:FILE
установить имя выходного файла
--outdir:DIR
указать путь, куда будет записан выходной файл
--usenimcache
использует outdir=$$nimcache, какое значение оно получит после обработки всех опций
--stdout:on|off
вывод в стандартный поток
--colors:on|off
включить/выключить цветной вывод сообщений компилятора
--filenames:abs|canonical|legacyRelProj
настроить отображение имен файлов в сообщениях компилятора, по умолчанию abs (абсолютный путь)
--processing:dots|filenames|off
отображать файлы по мере их обработки компилятором Nim
--unitsep:on|off
использовать ASCII-разделитель (31) между сообщениями об ошибках, полезно для инструментов типа IDE
--declaredLocs:on|off
отображать местоположения объявлений в сообщениях
--spellSuggest:num
отображать не более num >= 0 предложений по исправлению опечаток. Если num не указано (или auto), возвращается определённый реализацией набор предложений.
--hints:on|off|list.
on|off включает или отключает подсказки. list показывает, какие подсказки выбраны.
--hint:X:on|off
включить/выключить конкретную подсказку X. hint:X означает hint:X:on, как и у аналогичных флагов. all - набор всех подсказок (поддерживается только all:off).
--hintAsError:X:on|off
превратить конкретную подсказку X в ошибку на/отключить
-w:on|off|list, --warnings:on|off|list
on|off включает или отключает предупреждения. list показывает, какие предупреждения выбраны.
--warning:X:on|off
включить/выключить конкретное предупреждение X. warning:X означает warning:X:on, как и у аналогичных флагов. all - набор всех предупреждений (поддерживается только all:off).
--warningAsError:X:on|off
превратить конкретное предупреждение X в ошибку на/отключить
--styleCheck:off|hint|error
создавать подсказки или ошибки для идентификаторов Nim, которые не соответствуют официальному стилистическому руководству Nim https://nim-lang.org/docs/nep1.html
--styleCheck:usages
только применять согласованные написания идентификаторов, не применять стили к объявлениям
--showAllMismatches:on|off
отображать все несовпадающие кандидаты в разрешении перегрузки
--lib:PATH
установить путь к системной библиотеке
--import:PATH
добавить автоматически импортируемый модуль, см. также patchFile в nimscript, который предлагает больше гибкости.
--include:PATH
добавить автоматически включаемый модуль
--nimcache:PATH
установить путь, используемый для сгенерированных файлов, см. также https://nim-lang.org/docs/nimc.html#compiler-usage-generated-c-code-directory
-c, --compileOnly:on|off
скомпилировать только файлы Nim; не собирать и не линкувать
--noLinking:on|off
скомпилировать файлы Nim и сгенерированные файлы, но не линкувать
--noMain:on|off
не генерировать главную процедуру
--genScript:on|off
сгенерировать скрипт компиляции (в подкаталоге 'nimcache' с именем 'compile_$$project$$scriptext') и файл '.deps', содержащий зависимости; подразумевает --compileOnly
--os:SYMBOL
установить целевую операционную систему (кросс-компиляция)
--cpu:SYMBOL
установить целевой процессор (кросс-компиляция)
--debuginfo:on|off
включает отладочную информацию
-t, --passC:OPTION
передать опцию компилятору C
-l, --passL:OPTION
передать опцию линку
--cc:SYMBOL
указать компилятор C
--cincludes:DIR
изменить путь поиска заголовков компилятора C
--clibdir:DIR
изменить путь поиска библиотек линковщика
--clib:LIBNAME
подключить дополнительную библиотеку C (следует опустить платформозависимые расширения)
--project
документировать весь проект (doc)
--docRoot:path
nim doc --docRoot:/foo --project --outdir:docs /foo/sub/main.nim генерирует: docs/sub/main.html если path == @pkg, будет использоваться директория файла nimble если path == @path, будет использоваться первая подходящая директория в --path если path == @default (по умолчанию и наиболее полезно), будет использоваться наилучшее соответствие среди @pkg,@path. Если эти директории не существуют, будет использован путь к проекту
-b, --backend:c|cpp|js|objc
устанавливает бэкенд для использования с командами, такими как nim doc или nim r
--docCmd:cmd
если cmd == skip, пропускает runnableExamples иначе, запускает runnableExamples с заданными опциями, например: --docCmd:"-d:foo --threads:on"
--docSeeSrcUrl:url
активировать 'посмотреть исходный код' для команды doc (см. doc.item.seesrc в config/nimdoc.cfg)
--docInternal
также сгенерировать документацию для неэкспортируемых символов
--lineDir:on|off
генерация директивы #line включена/выключена
--embedsrc:on|off
встраивает исходный код в комментарии в сгенерированный вывод
--tlsEmulation:on|off
включить/выключить эмуляцию локального хранилища потоков
--implicitStatic:on|off
включить/выключить неявную вычислительную оценку во время компиляции
--trmacros:on|off
включить/выключить макросы переписывания терминов
--multimethods:on|off
включить/выключить многометоды
--hotCodeReloading:on|off
включить/выключить поддержку перезагрузки кода в реальном времени
--excessiveStackTrace:on|off
в стековых следах используются полные пути к файлам
--stackTraceMsgs:on|off
включить пользовательские сообщения о кадрах стека через setFrameMsg
--skipCfg:on|off
не читать файл конфигурации Nim-установки
END_OF_DOCUMENT_MARKER
--skipUserCfg:on|off
не читать конфигурационный файл пользователя
--skipParentCfg:on|off
не читать конфигурационные файлы родительских каталогов
--skipProjCfg:on|off
не читать конфигурационный файл проекта
--mm:orc|arc|refc|markAndSweep|boehm|go|none|regions
выбор реализации управления памятью; по умолчанию — 'orc'
--exceptions:setjmp|cpp|goto|quirky
выбор реализации обработки исключений
--index:on|off|only
docgen: включить/отключить генерацию файла индекса (only означает не генерировать выходные файлы, такие как HTML)
--noImportdoc:on|off
включить/отключить загрузку файлов документации .idx
--putenv:key=value
установка переменной среды
--NimblePath:PATH
добавление пути для поддержки Nimble
--noNimblePath
отключение пути Nimble
--clearNimblePath
очистка списка путей поиска пакетов Nimble
--cppCompileToNamespace:namespace
использование предоставленного пространства имён для сгенерированного кода C++, если пространство имён не указано, будет использовано "Nim"
--nimMainPrefix:prefix
использование {prefix}NimMain вместо NimMain в сгенерированном коде C/C++
--expandMacro:MACRO
вывод каждого сгенерированного AST из MACRO
--expandArc:PROCNAME
показ того, как PROCNAME выглядит после различных оптимизаций перед последней фазой бэкенда (в основном специфично для ARC/ORC)
--excludePath:PATH
исключение пути из списка путей поиска
--dynlibOverride:SYMBOL
помечает SYMBOL таким образом, что dynlib:SYMBOL не имеет эффекта и может быть статически связан вместо этого; соответствие символов является размытым, поэтому --dynlibOverride:lua соответствует dynlib: "liblua.so.3"
--dynlibOverrideAll
отключает эффекты директивы dynlib
--listCmd
вывод команд компиляции; может быть объединён с --hint:exec:on и --hint:link:on
--asm
генерация кода ассемблера
--parallelBuild:0|1|...
параллельная сборка с количеством процессоров = число процессоров (0 для автоматического определения)
--incremental:on|off
перекомпилировать только изменённые модули (экспериментально!)
--verbosity:0|1|2|3
установка уровня подробности Nim (1 — по умолчанию)
--errorMax:N
остановка компиляции после N ошибок; 0 означает без ограничений
--maxLoopIterationsVM:N
установка максимального числа итераций для всех циклов виртуальной машины
--experimental:$1
включить экспериментальную языковую возможность
--legacy:$2
включить устаревшую/старую языковую возможность
--benchmarkVM:on|off
включение/выключение бенчмаркинга кода виртуальной машины с cpuTime()
--profileVM:on|off
включение/выключение профилировщика виртуальной машины во время компиляции
--panics:on|off
преобразование паники в завершение процесса (по умолчанию: выключено)
--deepcopy:on|off
включить 'system.deepCopy' для --mm:arc|orc
--jsbigint64:on|off
включение/выключение использования BigInt для 64-битных целых чисел для бэкенда JavaScript (по умолчанию: включено)
--nimBasePattern:nimbase.h
позволяет указать собственный шаблон для nimbase.h

Список предупреждений

Каждое предупреждение может быть активировано индивидуально с помощью --warning:NAME:on|off или в директиве push с {.warning[NAME]:on|off.}.

Название Описание
CannotOpenFile Не удалось открыть некоторые файлы, не критически необходимые для работы компилятора.
OctalEscape Код содержит неподдерживаемую восьмеричную последовательность.
Deprecated Код использует устаревший символ.
ConfigDeprecated Проект использует устаревший конфигурационный файл.
SmallLshouldNotBeUsed Буква 'l' не должна использоваться в качестве идентификатора.
EachIdentIsTuple Код содержит путающую var декларацию.
CStringConv Предупреждение об опасных неявных преобразованиях в cstring.
EnumConv Предупреждение о преобразованиях из перечисления в перечисление.
AnyEnumConv Предупреждение о любых преобразованиях в тип перечисления.
HoleEnumConv Предупреждение о преобразовании в перечисление с дырами. Эти преобразования небезопасны.
ResultUsed Предупреждение об использовании встроенной переменной result.
User Некоторые пользовательские предупреждения.

Список подсказок

Каждая подсказка может быть активирована индивидуально с помощью --hint:NAME:on|off или в директиве push с {.hint[NAME]:on|off.}.

Название Описание
CC Показ вызова компилятора C.
CodeBegin
CodeEnd
CondTrue
Conf Загружен конфигурационный файл.
ConvToBaseNotNeeded
ConvFromXtoItselfNotNeeded
Dependency
Exec Программа выполняется.
ExprAlwaysX
ExtendedContext
GCStats Выводит статистику о сборщике мусора.
GlobalVar Отображает объявления глобальных переменных.
Link Фаза компоновки.
Name
Path Изменения путей поиска.
Pattern
Performance
Processing Компилируемый артефакт.
QuitCalled
Source Строка исходного кода, которая сгенерировала диагностическое сообщение.
StackTrace
Success, SuccessX Успешная компиляция библиотеки или исполняемого файла.
User
UserRaw
XDeclaredButNotUsed Неиспользуемые символы в коде.

Уровни подробности

Уровень Описание
0 Минимальный уровень вывода для компилятора.
1 Отображает компиляцию всех файлов, включая те, которые импортируются другими модулями или через директиву compile. Это уровень по умолчанию.
2 Отображает статистику компиляции, перечисляет динамические библиотеки, которые будут загружены конечным исполняемым файлом, и выводит в стандартный вывод результат применения фильтра к исходному коду, если такой фильтр использовался во время компиляции.
3 В дополнение к предыдущим уровням выводит отладочный стек вызовов для разработчиков компилятора.

Символы времени компиляции

С помощью переключателя -d:x или --define:x вы можете определить символы времени компиляции для условной компиляции. Определённые переключатели могут быть проверены в исходном коде с помощью оператора when и процедуры defined. Типичное использование этого переключателя — включение сборки в режиме релиз (-d:release), где включены оптимизации для лучшей производительности. Ещё одним распространённым использованием является переключатель -d:ssl для активации сокетов SSL.

Кроме того, вы можете передать значение вместе со символом: -d:x=y, что может быть использовано в сочетании с директивами определения времени компиляции для переопределения символов во время сборки.

Символы времени компиляции полностью нечувствительны к регистру и знаки подчёркивания также игнорируются. --define:FOO и --define:foo идентичны.

END_OF_DOCUMENT_MARKER

Символы времени компиляции, начинающиеся с префикса nim, зарезервированы для реализации и не должны использоваться в других местах.

Имя Описание
nimStdSetjmp Используйте стандартные функции библиотеки setjmp()/longjmp() для исключений на основе setjmp. Это значение по умолчанию на большинстве платформ.
nimSigSetjmp Используйте sigsetjmp()/siglongjmp() для исключений на основе setjmp.
nimRawSetjmp Используйте _setjmp()/_longjmp() на POSIX и _setjmp()/longjmp() на Windows для исключений на основе setjmp. Это значение по умолчанию на платформах BSD и подобных BSD, где оно значительно быстрее стандартных функций.
nimBuiltinSetjmp Используйте __builtin_setjmp()/__builtin_longjmp() для исключений на основе setjmp. Это не будет работать, если исключение выбрасывается и перехватывается внутри одной и той же процедуры. Полезно для тестирования производительности.

Файлы конфигурации

Примечание: Имя файла проекта — это имя файла .nim, передаваемого в качестве аргумента командной строки компилятору.

Исполняемый файл nim обрабатывает файлы конфигурации в следующих каталогах (в этом порядке; более поздние файлы перезаписывают предыдущие настройки):

  1. $nim/config/nim.cfg, /etc/nim/nim.cfg (UNIX) или <Nim's installation directory>\config\nim.cfg (Windows). Этот файл можно пропустить с помощью параметра командной строки --skipCfg.
  2. Если переменная среды XDG_CONFIG_HOME определена, $XDG_CONFIG_HOME/nim/nim.cfg или ~/.config/nim/nim.cfg (POSIX) или %APPDATA%/nim/nim.cfg (Windows). Этот файл можно пропустить с помощью параметра командной строки --skipUserCfg.
  3. $parentDir/nim.cfg где $parentDir обозначает любой родительский каталог пути к файлу проекта. Эти файлы можно пропустить с помощью параметра командной строки --skipParentCfg.
  4. $projectDir/nim.cfg где $projectDir обозначает путь к файлу проекта. Этот файл можно пропустить с помощью параметра командной строки --skipProjCfg.
  5. Проект также может иметь файл конфигурации, специфичный для проекта, с именем $project.nim.cfg, расположенный в той же директории, что и $project.nim. Этот файл можно пропустить с помощью параметра командной строки --skipProjCfg.

Параметры командной строки имеют приоритет над настройками файлов конфигурации.

По умолчанию сборка проекта — это сборка отладки. Чтобы скомпилировать сборку релиза, определите символ release.

nim c -d:release myproject.nim

Чтобы скомпилировать опасную сборку релиза, определите символ danger.

nim c -d:danger myproject.nim

Обработка пути поиска

Nim имеет понятие глобального пути поиска (PATH), который используется для определения местоположения импортированных модулей или файлов включения. Если найдено несколько файлов, возникает ошибка неоднозначности.

nim dump показывает содержимое PATH.

Однако перед использованием PATH проверяется текущий каталог на предмет существования файла. Таким образом, если PATH содержит $lib и $lib/bar, и структура каталогов выглядит следующим образом:

$lib/x.nim
$lib/bar/x.nim
foo/x.nim
foo/main.nim
other.nim

И main импортирует x, то импортируется foo/x. Если other импортирует x, то $lib/x.nim и $lib/bar/x.nim соответствуют, но используется $lib/x.nim, поскольку это первое совпадение.

Каталог сгенерированного кода C

Все сгенерированные Nim файлы помещаются в подкаталог nimcache. Полный путь:

  • $XDG_CACHE_HOME/nim/$projectname(_r|_d) или ~/.cache/nim/$projectname(_r|_d) на Posix
  • $HOME\nimcache\$projectname(_r|_d) на Windows.

Суффикс _r используется для сборок релиза, _d — для сборок отладки.

Это упрощает удаление всех сгенерированных файлов.

Параметр --nimcache переключатель компилятора может использоваться для изменения каталога nimcache.

Однако сгенерированный C-код не является независимым от платформы. C-код, сгенерированный для Linux, не компилируется на Windows, например. В комментарии вверху файла C перечислены операционная система, процессор и CC, для которых был скомпилирован файл.

Выбор компилятора

Чтобы изменить компилятор с компилятора по умолчанию (в командной строке):

nim c --cc:llvm_gcc --compile_only myfile.nim

Это использует конфигурацию, определенную в config\nim.cfg для llvm_gcc.

Если nimcache уже содержит скомпилированный код другого компилятора для того же проекта, добавьте флаг -f для принудительной перекомпиляции всех файлов.

Компилятор по умолчанию определяется в верхней части config\nim.cfg. Изменение этой настройки влияет на компилятор, используемый koch для (пере)сборки Nim.

Для использования переменной среды CC используйте nim c --cc:env myfile.nim. Для использования переменной среды CXX используйте nim cpp --cc:env myfile.nim. --cc:env доступен начиная с версии Nim 1.4.

Кросс-компиляция

Для кросс-компиляции, например:

nim c --cpu:i386 --os:linux --compileOnly --genScript myproject.nim

Затем переместите C-код и скрипт компиляции compile_myproject.sh на вашу машину Linux i386 и запустите скрипт.

Другой способ — заставить Nim вызывать кросс-компиляторную цепочку инструментов:

nim c --cpu:arm --os:linux myproject.nim

Для кросс-компиляции компилятор вызывает C-компилятор с именем, подобным $cpu.$os.$cc (например, arm.linux.gcc) с опциями, определенными в $cpu.$os.$cc.options.always. Система конфигурации используется для предоставления осмысленных значений по умолчанию. Например, для Linux на 32-битном процессоре ARM ваш файл конфигурации должен содержать что-то вроде:

arm.linux.gcc.path = "/usr/bin"
arm.linux.gcc.exe = "arm-linux-gcc"
arm.linux.gcc.linkerexe = "arm-linux-gcc"
arm.linux.gcc.options.always = "-w -fmax-errors=3"

Кросс-компиляция для Windows

Для кросс-компиляции для Windows из Linux или macOS с помощью цепочки инструментов MinGW-w64:

nim c -d:mingw myproject.nim
# `nim r` also works, running the binary via `wine` or `wine64`:
nim r -d:mingw --eval:'import os; echo "a" / "b"'

Используйте --cpu:i386 или --cpu:amd64 для переключения архитектуры процессора.

Цепочка инструментов MinGW-w64 может быть установлена следующим образом:

apt install mingw-w64   # Ubuntu
yum install mingw32-gcc
yum install mingw64-gcc # CentOS - requires EPEL
brew install mingw-w64  # OSX

Кросс-компиляция для Android

Есть два способа компиляции для Android: программы терминала (Termux) и с помощью NDK (Android Native Development Kit).

Первый способ — рассматривать Android как обычный Linux и использовать Termux для подключения и непосредственного запуска компилятора Nim на Android, как если бы это был Linux. Эти программы — только консольные и не могут быть распространяться в Play Store.

Используйте обычные nim c внутри Termux, чтобы создать программы терминала для Android.

Обычные приложения Android написаны на Java. Чтобы использовать Nim внутри приложения Android, вам нужен небольшой Java-заглушка, который вызывает нативный библиотеку, написанную на Nim, используя NDK. Вы также можете использовать native-activity, чтобы заглушка Java генерировалась автоматически.

Используйте nim c -c --cpu:arm --os:android -d:androidNDK --noMain:on для генерации необходимых файлов исходного кода C, которые нужно включить в ваш проект Android Studio. Добавьте сгенерированные C-файлы в скрипт сборки CMake в вашем проекте Android. Затем выполните окончательную компиляцию с помощью Android Studio, которая использует Gradle для вызова CMake для компиляции проекта.

Поскольку Nim является частью библиотеки, он не может иметь собственный C-стиль main(), поэтому вам нужно будет определить свой собственный android_main и инициализировать среду Java или использовать библиотеку, например, SDL2 или GLFM. После завершения настройки Android крайне важно вызвать NimMain() для инициализации сборщика мусора Nim и выполнения основных операторов вашей программы.

proc NimMain() {.importc.}
proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} =
  NimMain() # initialize garbage collector memory, types and stack

Имя NimMain может быть изменено с помощью переключателя --nimMainPrefix:prefix. Используйте --nimMainPrefix:MyLib и имя вызываемой функции — MyLibNimMain.

Кросс-компиляция для iOS

Для кросс-компиляции для iOS необходимо использовать компьютер macOS и Xcode. Обычные языки для разработки iOS — Swift и Objective-C. Оба используют LLVM и могут быть скомпилированы в объектные файлы, соединённые с C, C++ или Objective-C-кодом, сгенерированным Nim.

Используйте nim c -c --os:ios --noMain:on для генерации файлов C и их включения в ваш проект Xcode. Затем вы можете использовать Xcode для компиляции, компоновки, упаковки и подписания всего.

Поскольку Nim является частью библиотеки, он не может иметь свой собственный C-стиль main(), поэтому вам нужно определить main, который вызовет autoreleasepool и UIApplicationMain для выполнения, или использовать библиотеку, например, SDL2 или GLFM. После завершения настройки iOS крайне важно вызвать NimMain() для инициализации сборщика мусора Nim и выполнения основных операторов вашей программы.

proc NimMain() {.importc.}
proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} =
  NimMain() # initialize garbage collector memory, types and stack

Примечание: "make clean" в Xcode путается с сгенерированными файлами nim.c, поэтому вам нужно очистить эти файлы вручную, чтобы выполнить чистую сборку.

Имя NimMain может быть изменено с помощью переключателя --nimMainPrefix:prefix. Используйте --nimMainPrefix:MyLib и имя вызываемой функции — MyLibNimMain.

Кросс-компиляция для Nintendo Switch

Просто добавьте --os:nintendoswitch к вашей обычной команде nim c или nim cpp и установите параметры командной строки passC и passL на значения, подобные:

nim c ... --d:nimAllocPagesViaMalloc --mm:orc --passC="-I$DEVKITPRO/libnx/include" ...
--passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx"

или настройте файл nim.cfg следующим образом:

#nim.cfg
--mm:orc
--d:nimAllocPagesViaMalloc
--define:nimInheritHandles
--passC="-I$DEVKITPRO/libnx/include"
--passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx"

Настройка devkitPro должна быть такой же, как по умолчанию, с их новым установщиком здесь для Mac/Linux или здесь для Windows.

Например, с вышеуказанной конфигурацией:

nim c --os:nintendoswitch switchhomebrew.nim

Это сгенерирует файл с именем switchhomebrew.elf, который затем можно преобразовать в файл nro с помощью инструмента elf2nro в релизе devkitPro. Примеры можно найти в репозитории nim-libnx github repo.

Есть несколько вещей, которые не работают, потому что библиотеки devkitPro их не поддерживают. Это:

  1. Ожидание завершения дочернего процесса. Дочерний процесс может быть запущен, но на данный момент его нельзя ожидать, что немного затрудняет использование дочерних процессов.
  2. Динамические вызовы. Операционная система Switch (Horizon) не поддерживает динамические библиотеки, поэтому dlopen/dlclose недоступны.
  3. mqueue. К сожалению, нет заголовков mqueue.
  4. ucontext. Также нет заголовков для этих типов. Пока нет сопрограмм :(
  5. nl_types. Нет заголовков для этого.
  6. Поскольку mmap не поддерживается, необходимо использовать параметр nimAllocPagesViaMalloc.

Компиляция для GPU

Компиляция для вычислений на GPU может быть выполнена с помощью --cc:nvcc для CUDA с nvcc или --cc:hipcc для графических процессоров AMD с HIP. Оба компилятора требуют сборки для C++ с nim cpp.

Вот очень простой пример CUDA ядра с использованием emit, который можно скомпилировать с помощью nim cpp --cc:nvcc --define:"useMalloc" hello_kernel.nim, предполагая, что у вас установлен CUDA toolkit.

{.emit: """
__global__ void add(int a, int b) {
  int c;
  c = a + b;
}
""".}

proc main() =
  {.emit: """
  add<<<1,1>>>(2,7);
  """.}

main()

Генерация DLL

Примечание: Те же правила применяются к lib*.so файлам shared object на UNIX. Для лучшей читабельности здесь описана только версия DLL.

Nim поддерживает генерацию DLL. Однако должен быть только один экземпляр GC на процесс/адресное пространство. Этот экземпляр содержится в nimrtl.dll. Это означает, что каждая сгенерированная DLL Nim зависит от nimrtl.dll. Для генерации файла "nimrtl.dll" используйте команду:

nim c -d:release lib/nimrtl.nim

Для ссылки на nimrtl.dll используйте команду:

nim c -d:useNimRtl myprog.nim

Дополнительные переключатели компиляции

Стандартная библиотека поддерживает всё больше useX условных определений, влияющих на реализацию некоторых функций. Этот раздел пытается дать полный список.

Определение Эффект
release Включает оптимизатор. Возможны более агрессивные оптимизации, например: --passC:-ffast-math (но см. вопрос #10305)
danger Отключает все проверки во время выполнения и включает оптимизатор.
useFork Заставляет osproc использовать fork вместо posix_spawn.
useNimRtl Компилировать и линковать против nimrtl.dll.
useMalloc Заставляет Nim использовать malloc C вместо собственного менеджера памяти Nim, хотя перед каждым выделением памяти добавляет его размер для поддержки очистки памяти при перевыделении. Это работает только с --mm:none, --mm:arc и --mm:orc.
useRealtimeGC Включает поддержку GC Nim для мягких систем реального времени. Для получения дополнительной информации см. документацию refc.
logGC Включить регистрацию GC в stdout.
nodejs Целевой JS фактически node.js.
ssl Включает поддержку OpenSSL для модуля сокетов.
memProfiler Включает профилирование памяти для native GC.
uClibc Использовать uClibc вместо libc. (Актуально для Unix-подобных ОС)
checkAbi При использовании типов из заголовков C добавляются проверки, которые сравнивают то, что находится в файле Nim, с тем, что находится в заголовке C. В будущем это может быть включено по умолчанию.
tempDir Этот символ принимает строку в качестве значения, например, --define:tempDir:/some/temp/path, чтобы переопределить временную директорию, возвращаемую os.getTempDir(). Значение должно заканчиваться символом разделителя директорий. (Актуально для платформы Android)
useShPath Этот символ принимает строку в качестве значения, например, --define:useShPath:/opt/sh/bin/sh, чтобы переопределить путь к бинарному файлу sh, в случаях, когда он не находится в стандартном расположении /bin/sh.
noSignalHandler Отключить обработчик ошибок от system.nim.
globalSymbols Загрузить все {.dynlib.} библиотеки с флагом RTLD_GLOBAL на системах Posix для разрешения символов в последующих загруженных библиотеках.
lto Включить оптимизацию в момент компиляции в компиляторе и линковщике back-end.
lto_incremental Включить оптимизацию в момент компиляции и дополнительно включить инкрементальную линковку для компиляторов, которые её поддерживают. В настоящее время только clang и vcc.
strip Удалить символы отладки, добавленные компилятором back-end из исполняемого файла.

Дополнительные возможности

В этом разделе описаны дополнительные функции Nim, которые не указаны в руководстве по Nim. Некоторые из функций здесь имеют смысл только для генератора кода C и могут быть изменены.

Параметр LineDir

Параметр --lineDir может быть включён или выключён. Если он включён, сгенерированный код C содержит директивы #line. Это может быть полезно для отладки с помощью GDB.

Параметр StackTrace

Если включён параметр --stackTrace, сгенерированный C содержит код, который гарантирует, что будут предоставлены правильные трассировки стека, если программа аварийно завершит работу или произойдёт какое-то необработанное исключение.

Параметр LineTrace

Параметр --lineTrace подразумевает параметр stackTrace. Если он включён, сгенерированный C содержит код, который гарантирует, что при аварийном завершении работы программы или возникновении необработанного исключения будут предоставлены правильные трассировки стека с информацией о номере строки.

DynlibOverride

По умолчанию директива dynlib в Nim приводит к генерации вызовов GetProcAddress (или их Unix-аналогов) для привязки к DLL. С помощью командной строки dynlibOverride это можно предотвратить, а затем с помощью --passL статическая библиотека может быть подключена. Например, для статической ссылки на Lua на Linux эта команда может сработать:

nim c --dynlibOverride:lua --passL:liblua.lib program.nim

Параметры языка back-end

Типичное использование компилятора включает использование команд compile или c для преобразования файла .nim в один или несколько файлов .c, которые затем компилируются с помощью компилятора C платформы в статический двоичный файл. Однако есть и другие команды для компиляции в C++, Objective-C или JavaScript. Более подробную информацию можно найти в документе Интеграция Nim Backend.

Инструменты документации Nim

Nim предоставляет команду doc для генерации HTML-документации из файлов исходного кода .nim. В выходных данных будут отображаться только экспортированные символы. Более подробную информацию см. на странице документации docgen.

Интеграция Nim idetools

Nim предоставляет языковую интеграцию с внешними IDE через команду idetools. Подробности см. в документации idetools.

Nim для встраиваемых систем

Хотя стандартная конфигурация Nim нацелена на оптимальную производительность на современном ПК и операционных системах с достаточным объёмом памяти, вполне возможно запустить код Nim и большую часть стандартных библиотек Nim на небольших встраиваемых микропроцессорах с несколькими килобайтами памяти.

Хорошим началом является использование целевого оператора any вместе с менеджером памяти malloc и сборщиком мусора arc. Например:

nim c --os:any --mm:arc -d:useMalloc [...] x.nim
  • --mm:arc включит управление памятью с помощью подсчёта ссылок вместо сборщика мусора по умолчанию. Это позволит Nim использовать кучу памяти, которая требуется, например, для строк и seq.
  • Целевой параметр --os:any гарантирует, что Nim не зависит от каких-либо специфических функций операционной системы. Ваша платформа должна поддерживать только некоторые основные функции библиотеки ANSI C stdlib и stdio , которые должны быть доступны почти на любой платформе.
  • Параметр -d:useMalloc настраивает Nim использовать только стандартные примитивы управления памятью C malloc(), free(), realloc().

Если ваша платформа не предоставляет эти функции, то должна быть тривиальной задачей предоставить их реализацию и связать их с вашей программой.

Для платформ с очень ограниченной памятью может быть полезно передать некоторые дополнительные флаги как компилятору Nim, так и компилятору C и/или линковщику, чтобы оптимизировать сборку по размеру. Например, следующие флаги могут быть использованы при нацеливании на компилятор gcc:

--opt:size -d:lto -d:strip

Флаг --opt:size указывает Nim оптимизировать генерацию кода для уменьшения размера (с помощью компилятора C), флаги -d:lto включают оптимизацию в момент линковки в компиляторе и линковщике, флаг -d:strip удаляет символы отладки.

См. раздел Перекрёстная компиляция для инструкций по компиляции программы для вашей целевой платформы.

nimAllocPagesViaMalloc

По умолчанию аллокатор Nim основан на TLSF, этот алгоритм был разработан для встраиваемых устройств. Этот аллокатор получает блоки/страницы памяти через в настоящее время не документированный osalloc API, который обычно использует вызов POSIX mmap. На многих средах mmap недоступен, но функция C malloc есть. Вы можете использовать определение nimAllocPagesViaMalloc для использования malloc вместо mmap. nimAllocPagesViaMalloc в настоящее время поддерживается только с --mm:arc или --mm:orc. (С версии 1.6)

nimPage256 / nimPage512 / nimPage1k

Измените размер страницы для аллокатора GC Nim. Это позволяет использовать nimAllocPagesViaMalloc на устройствах с меньшим объёмом оперативной памяти. Размер страницы по умолчанию требует слишком много оперативной памяти для работы.

Рекомендованные значения:

  • < 32 КБ ОЗУ использовать nimPage256
  • < 512 КБ ОЗУ использовать nimPage512
  • < 2 МБ ОЗУ использовать nimPage1k

Первоначальные тесты не показали значительной разницы между размерами страниц 512B или 1 КБ с точки зрения производительности или задержки. Использование nimPages256 ограничит общее количество выделяемой оперативной памяти.

nimMemAlignTiny

Устанавливает MemAlign на 4 байт, что уменьшает выравнивание памяти, чтобы лучше соответствовать некоторым встраиваемым устройствам.

Размер стека потока

API потоков Nim предоставляет простой интерфейс к более сложным функциям задач RTOS. Настройка размера стека и размера защищённого стека может быть выполнена путём задания -d:nimThreadStackSize=16384 или -d:nimThreadStackGuard=32.

В настоящее время только Zephyr, NuttX и FreeRTOS поддерживают эти настройки.

Nim для систем реального времени

См. настройки управления памятью --mm:arc или --mm:orc в MM для получения дополнительной информации.

Обработка сигналов в Nim

Язык программирования Nim не имеет понятия о механизмах обработки сигналов Posix. Однако стандартная библиотека предлагает некоторую ограниченную поддержку обработки сигналов, в частности, ошибки сегментации преобразуются в критические ошибки, которые генерируют трассировку стека. Это можно отключить с помощью переключателя -d:noSignalHandler.

Оптимизация для Nim

В Nim нет отдельного оптимизатора, но генерируемый C-код очень эффективен. Большинство C-компиляторов имеют отличные оптимизаторы, поэтому обычно оптимизация кода не требуется. Nim разработан для поощрения эффективного кода: самый читабельный код на Nim часто является и самым эффективным.

Однако иногда приходится оптимизировать. Делайте это в следующей последовательности:

  1. выключите встроенный отладчик (он медленный!)
  2. включите оптимизатор и отключите проверки во время выполнения
  3. профилируйте свой код, чтобы найти узкие места
  4. попробуйте найти лучший алгоритм
  5. выполните оптимизации низкого уровня

Этот раздел может помочь вам только с последним пунктом.

Оптимизация обработки строк

Присваивание строк иногда является дорогостоящим в Nim: требуется скопировать всю строку. Однако компилятор часто достаточно умен, чтобы не копировать строки. Из-за семантики передачи аргументов, строки никогда не копируются при передаче в подпрограммы. Компилятор не копирует строки, которые являются результатом вызова процедуры, потому что вызываемая процедура возвращает новую строку в любом случае. Таким образом, эффективно делать:

var s = procA() # assignment will not copy the string; procA allocates a new
                # string already

Однако неэффективно делать:

var s = varA    # assignment has to copy the whole string into a new buffer!

Для let символов копия не всегда необходима:

let s = varA    # may only copy a pointer if it safe to do so

Компилятор оптимизирует операторы case со строками: если используется несколько различных строковых констант, для них используется схема хеширования. Поэтому код подобный этому достаточно эффективен:

case normalize(k.key)
of "name": c.name = v
of "displayname": c.displayName = v
of "version": c.version = v
of "os": c.oses = split(v, {';'})
of "cpu": c.cpus = split(v, {';'})
of "authors": c.authors = split(v, {';'})
of "description": c.description = v
of "app":
  case normalize(v)
  of "console": c.app = appConsole
  of "gui": c.app = appGUI
  else: quit(errorStr(p, "expected: console or gui"))
of "license": c.license = UnixToNativePath(k.value)
else: quit(errorStr(p, "unknown variable: " & k.key))

© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/nimc.html

Spec-Zone.ru

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