Руководство пользователя компилятора Nim
Исходный кодИзменить"Посмотри на себя, хакер. Жалкая тварь из плоти и крови, задыхающаяся и потеющая, пока бежишь по моим коридорам. Как ты можешь бросить вызов совершенной, бессмертной машине?"
Введение
Этот документ описывает использование компилятора Nim на различных поддерживаемых платформах. Это не определение языка программирования Nim (которое описано в руководстве).
Nim — это свободное программное обеспечение; оно лицензировано по лицензии MIT.
Использование компилятора
Переключатели командной строки
Все параметры, принимающие аргумент PATH или DIR, подвержены подстановке путей:
-
$nim: Глобальный путь префикса nim -
$lib: Путь stdlib -
$homeи~: Путь домашней директории пользователя -
$config: Директория модуля, который компилируется в данный момент -
$projectname: Имя файла проекта без расширения -
$projectpathи$projectdir: Путь к файлу проекта -
$nimcache: Путь nimcache
Основные переключатели командной строки:
Использование:
nim command [options] [projectfile] [arguments]
Команда:
compile, crarguments с помощью бэкенда, указанного --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--opt:none|speed|size--debugger:native--app:console|gui|lib|staticlib-r, --run--eval:cmdnim --eval:"echo 1" по умолчанию e (nimscript), но настраиваемое: nim r --eval:'for a in stdin.lines: echo a'--fullhelp-h, --help-v, --versionОбратите внимание, что однобуквенные параметры, принимающие аргумент, требуют двоеточия. Например, -p:PATH.
Расширенные переключатели командной строки:
Расширенные команды:compileToC, cccompileToCpp, cppcompileToOC, objcjsemd2html--docCmd:skip, чтобы пропустить компиляцию фрагментовrst2html--docCmd:skip для пропуска компиляции фрагментовmd2texrst2texdoc2texjsondocctagsbuildIndexgenDependdump| jq)checkПроверки во время выполнения (см. -x):
--objChecks:on|off--fieldChecks:on|off--rangeChecks:on|off--boundChecks:on|off--overflowChecks:on|off--floatChecks:on|off--nanChecks:on|off--infChecks:on|offРасширенные параметры:
--defusages:FILE,LINE,COL-o:FILE, --out:FILE--outdir:DIR--usenimcacheoutdir=$$nimcache, какое значение оно получит после обработки всех опций--stdout:on|off--colors:on|off--filenames:abs|canonical|legacyRelProjabs (абсолютный путь)--processing:dots|filenames|off--unitsep:on|off--declaredLocs:on|off--spellSuggest:numnum >= 0 предложений по исправлению опечаток. Если num не указано (или auto), возвращается определённый реализацией набор предложений.--hints:on|off|list.on|off включает или отключает подсказки. list показывает, какие подсказки выбраны.--hint:X:on|offhint:X означает hint:X:on, как и у аналогичных флагов. all - набор всех подсказок (поддерживается только all:off).--hintAsError:X:on|off-w:on|off|list, --warnings:on|off|liston|off включает или отключает предупреждения. list показывает, какие предупреждения выбраны.--warning:X:on|offwarning:X означает warning:X:on, как и у аналогичных флагов. all - набор всех предупреждений (поддерживается только all:off).--warningAsError:X:on|off--styleCheck:off|hint|error--styleCheck:usages--showAllMismatches:on|off--lib:PATH--import:PATHpatchFile в nimscript, который предлагает больше гибкости.--include:PATH--nimcache:PATH-c, --compileOnly:on|off--noLinking:on|off--noMain:on|off--genScript:on|off--os:SYMBOL--cpu:SYMBOL--debuginfo:on|off-t, --passC:OPTION-l, --passL:OPTION--cc:SYMBOL--cincludes:DIR--clibdir:DIR--clib:LIBNAME--project--docRoot:pathnim 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|objcnim doc или nim r
--docCmd:cmdcmd == skip, пропускает runnableExamples иначе, запускает runnableExamples с заданными опциями, например: --docCmd:"-d:foo --threads:on"
--docSeeSrcUrl:url--docInternal--lineDir:on|off--embedsrc:on|off--tlsEmulation:on|off--implicitStatic:on|off--trmacros:on|off--multimethods:on|off--hotCodeReloading:on|off--excessiveStackTrace:on|off--stackTraceMsgs:on|offsetFrameMsg
--skipCfg:on|off--skipUserCfg:on|off--skipParentCfg:on|off--skipProjCfg:on|off--mm:orc|arc|refc|markAndSweep|boehm|go|none|regions--exceptions:setjmp|cpp|goto|quirky--index:on|off|onlyonly означает не генерировать выходные файлы, такие как HTML)--noImportdoc:on|off.idx--putenv:key=value--NimblePath:PATH--noNimblePath--clearNimblePath--cppCompileToNamespace:namespace--nimMainPrefix:prefix{prefix}NimMain вместо NimMain в сгенерированном коде C/C++--expandMacro:MACRO--expandArc:PROCNAME--excludePath:PATH--dynlibOverride:SYMBOL--dynlibOverrideAll--listCmd--hint:exec:on и --hint:link:on--asm--parallelBuild:0|1|...--incremental:on|off--verbosity:0|1|2|3--errorMax:N--maxLoopIterationsVM:N--experimental:$1--legacy:$2--benchmarkVM:on|off--profileVM:on|off--panics:on|off--deepcopy:on|off--mm:arc|orc--jsbigint64:on|off--nimBasePattern:nimbase.hnimbase.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 идентичны.
Символы времени компиляции, начинающиеся с префикса 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 обрабатывает файлы конфигурации в следующих каталогах (в этом порядке; более поздние файлы перезаписывают предыдущие настройки):
-
$nim/config/nim.cfg,/etc/nim/nim.cfg(UNIX) или<Nim's installation directory>\config\nim.cfg(Windows). Этот файл можно пропустить с помощью параметра командной строки--skipCfg. - Если переменная среды
XDG_CONFIG_HOMEопределена,$XDG_CONFIG_HOME/nim/nim.cfgили~/.config/nim/nim.cfg(POSIX) или%APPDATA%/nim/nim.cfg(Windows). Этот файл можно пропустить с помощью параметра командной строки--skipUserCfg. -
$parentDir/nim.cfgгде$parentDirобозначает любой родительский каталог пути к файлу проекта. Эти файлы можно пропустить с помощью параметра командной строки--skipParentCfg. -
$projectDir/nim.cfgгде$projectDirобозначает путь к файлу проекта. Этот файл можно пропустить с помощью параметра командной строки--skipProjCfg. - Проект также может иметь файл конфигурации, специфичный для проекта, с именем
$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 их не поддерживают. Это:
- Ожидание завершения дочернего процесса. Дочерний процесс может быть запущен, но на данный момент его нельзя ожидать, что немного затрудняет использование дочерних процессов.
- Динамические вызовы. Операционная система Switch (Horizon) не поддерживает динамические библиотеки, поэтому dlopen/dlclose недоступны.
- mqueue. К сожалению, нет заголовков mqueue.
- ucontext. Также нет заголовков для этих типов. Пока нет сопрограмм :(
- nl_types. Нет заголовков для этого.
- Поскольку 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 Cstdlibиstdio, которые должны быть доступны почти на любой платформе. - Параметр
-d:useMallocнастраивает Nim использовать только стандартные примитивы управления памятью Cmalloc(),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 часто является и самым эффективным.
Однако иногда приходится оптимизировать. Делайте это в следующей последовательности:
- выключите встроенный отладчик (он медленный!)
- включите оптимизатор и отключите проверки во время выполнения
- профилируйте свой код, чтобы найти узкие места
- попробуйте найти лучший алгоритм
- выполните оптимизации низкого уровня
Этот раздел может помочь вам только с последним пунктом.
Оптимизация обработки строк
Присваивание строк иногда является дорогостоящим в 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