packaging and configuring apps
bookmark: dunno
TLDR
- ".nims", ".cfg", ".nimcfg", ".nimble" are valid configuration extensions.
- nimble
- shipped with nim isnt the nimbiest version
- install a nimbier nimble with nimble install nimble
- is package-level package manager, i.e. pnpm not apt-get
- parallel tasks are described in asyncPar
- nimscript defined here is strictly for app configuration and nimble support
- check targets/shell.nims for in depth nimscripting and tasks
links
- other
- high impact docs
- niche
- source
- abc
TODOs
- verify the different app cfg locations
- for some reason (oops) parseCfg is in shell.nims, it should be in this file
- this file has example of using @if... @end in a cfg file
- the packaging section should show examples of
- creating a package (compiled bin)
- creating a library (dont compile, install source files)
- creating a composite library + package (compiling + installing source files)
nimble
- nim package manager
nimble packages
- a directory with a .nimble file and one/more .nim files
- the .nimble filename should match the source codes mainFile.nim
- the .nimble file is executed as nimscript, thus you have full access to nims VM
- a package should generally define atleast a test task on install
- requires git/mercurial depending on where you're fetching remote packages from
- nimble package versions: nimble install blah bleh@123
- @123 | @>=0.1.2 | @#gitCommitHash | @#head (or any tag)
- @url
creating nimble packages
- by default nimble uses git repos as its primary source for packages
- each package contains a .nimble file with install & build directives
- check nimble api src for all .nimble options
- the .nimble file should (but not required to) have the same name as the package
- its interpreted using nimscript and supports any nim vm compatible features
- e.g. tasks can be used to define nimble package-specific commands
- packages install dirs
- libraries: copied to $nimbleDir/pkgs2/pkgname-ver-checksum
- binaries: compile -> copy to library dir > symlink to $nimbleDir/bin
# package metadata packageName = "if different from $project" version = "1.2.3" author = "rohtua" description = "6 pack of ramen" license = "TO KILL" # package directives # skipDirs, skipFiles, skipExt <-- deny list: will never be installed # installDirs, installFiles, installExt <-- allow list: will only be installed installExt = @["nim"] # required if your pkg is both a library & binary srcDir = "./src" bin = @["myMainFile"] # compile this file before installing skipExt = @["nim"] # dont install source .nim files (we only want to copy the compiled bin) binDir = "./bin" backend = "c" namedBin["main"] = "mymain" # rename binary namedBin = {"main": "mymain", "main2": "other-main"}.toTable() # rename binaries # package dependencies # ^= latest compatible semver # ~= latest version by increasing the last digit to highest version requires "nim >= 1.6.10", "sim ^= 10.6.1" requires "dim ~= 6.1.10" requires "wim > 0.1 & <= 0.5" requires "lim#head" # the latest commit requires "pim == 1.2.3" # not recommended; as transient deps could rely on a diff ver requires "https://github.com/user/pkg#abcd" # foreign deps: not managed by nimble, e.g. openssl when defined(nimdistros): import distros if detectOs(Ubuntu): foreignDep "libssl-dev" else: foreignDep "openssl" # package tasks: list a pkgs tasks via `nimble tasks` # see task section below
package directives
- author
- backend
- bin
- binDir
- description
- installDirs
- installExt
- installFiles
- license
- packageName
- skipDirs
- skipExt
- skipFiles
- srcDir
- version
- requires(varargsstring)
package dir structure
├── LICENSE ├── README.md ├── foobar.nimble # The project .nimble file ├── foobar.nim # only put it here if this is the only module └── src ├── foobar.nims # cfg specifically for sibling foobar.nim ├── foobar.nim # Imported via `import foobar` │ └── foobar # package module dir │ │ ├── utils.nim # Imported via `import foobar/utils` │ │ ├── common.nim # Imported via `import foobar/common` └── private # consumers cant import private modules │ │ │ ├── hidden.nim # internally you can `import foobar/private/hidden` └── tests # Contains the tests ├── config.nims ├── tfoo1.nim # First test └── tfoo2.nim # Second test
creating nimble libraries
- all previous info still stands correct, however pay attention to the following
- libraries arent pre-compiled, thus the directory structure most be obeyed
- if the library contains a single module, it can be in the root directory next to the .nimble file
- else create MyPackageName dir and put library files in there
- consumers can then import myPackageName / myModuleName
releasing and publishing packages
- be sure to compile with nimble and NOT nim
- nimble adds extra checks, e.g. package dependencies are listed in the .nimble file
- releasing
- increment the version in .nimble
- commit changes
- tag the commit git tag v1.2.3
- this MUST MATCH the version number in step 1, else nimble will refuse to install it
- git push --tags
- publishing
- use nimble publish
- or manually clone the packages repo and submit a PR
nimble configuration
- posix: ~/.config/nimble/nimble.ini
- windows: UserssomeuserAppDataRoamingnimblenimble.ini
# where to install pkgs nimbleDir = r"~/nimble/" # if true will add chcp 65001 to .cmd stubs generated in ~/.nimble/bin/ chcp = true # specify new custom package list(s) # over default with one named "Official" # multiple path/urls can be specified per name [PackageList] name = "My local list" path/url = r"/any/path/or/url" cloneUsingHttps = true # replace git:// with https:// httpProxy = ""
nimscript for app configuration
- subset of nim that can be evaluated by nims builtin VM
- see backends/shell.nim for indepth nimscript
- as well as tasks, as they can only be run in .nims and .nimble files
.nims as config files
- nim will automatically process .nims configs in the following order (later overrides previous)
# $project === name of the file being compiled # i.e. compiling blah.nim will automatically load blah.nims $XDG_CONFIG_HOME/nim/config.nims || ~/config/nim/config.nims $parentDir/config.nims $projectDir/config.nims $project.nims
- syntax for setting switches has 2 forms
switch("opt", "size") || hint(name, bool) || warning(name, bool) --opt:size # IMO the cleaner syntax
parsecfg
- high performance config parser in windows ini syntax
- fully supported in .nim files
- semi supported in .nims and .nimble files
- supports string literals, raw and triple quoted nim strings
parsecfg types
- CfgEvent object describing the parsing event
- kind enum CfgEventKind the type of line being parsed
- cfgSectionStart the start of config section
- section returns name
- cfgKeyValuePair in the form key=value
- key
- value
- cfgOption in the form --key=value
- key
- value
- cfgError failed to parse
- msg reason
- cfgEof end of file
- cfgSectionStart the start of config section
- kind enum CfgEventKind the type of line being parsed
- CfgParser object BaseLexor
- Config OrderedTableRef
parsecfg procs
- delSectionKey from in in a specific/empty str section
- getSectionValue from a key in a specific/empty str section
- loadConfig from a path
- newConfig() dictionary
- setSectionKey set key & value in a specific/empty str section
- writeConfig to a path
- close parser and its associated stream
- delSection and all associated keys
- errorStr of error event with line and column