Procs
proc sanitizePath(path: string; noQuote = false; sep = $'/'): string {...}{.raises: [], tags: [].}
proc getProjectDir(): string {...}{.raises: [], tags: [].}
- Get project directory for this compilation - returns "" at runtime
proc getNimcacheDir(projectDir = ""): string {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
- Get nimcache directory for current compilation or specified projectDir
proc getNimConfig(projectDir = ""): Config {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
proc getNimConfigFlags(projectDir = ""): string {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
-
Get Nim command line configuration flags for projectDir
If projectDir is not specified, it is detected if compile time or current directory is used.
proc writeNimConfig(cfgFile: string; projectDir = "") {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
-
Write Nim configuration for projectDir to specified cfgFile
If projectDir is not specified, it is detected if compile time or current directory is used.
proc sleep(milsecs: int) {...}{.raises: [], tags: [].}
- Sleep at compile time
proc getCurrentNimCompiler(): string {...}{.raises: [], tags: [].}
proc execAction(cmd: string; retry = 0; die = true; cache = false; cacheKey = ""): tuple[ output: string, ret: int] {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
-
Execute an external command - supported at compile time
Checks if command exits successfully before returning. If not, an error is raised. Always caches results to be used in nimsuggest or nimcheck mode.
retry - number of times command should be retried before error die = false - return on errors cache = true - cache results unless cleared with -f cacheKey - key to create unique cache entry
proc findExe(exe: string): string {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
- Find the specified executable using the which/where command - supported at compile time
proc mkDir(dir: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ ReadDirEffect, ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
-
Create a directory at compile time
The os module is not available at compile time so a few crucial helper functions are included with nimterop.
proc cpFile(source, dest: string; move = false) {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
- Copy a file from source to dest at compile time
proc mvFile(source, dest: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
- Move a file from source to dest at compile time
proc rmFile(source: string; dir = false) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ReadDirEffect, ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
- Remove a file or pattern at compile time
proc rmDir(dir: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ ReadDirEffect, ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
- Remove a directory or pattern at compile time
proc getProjectCacheDir(name: string; forceClean = true): string {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
-
Get a cache directory where all nimterop artifacts can be stored
Projects can use this location to download source code and build binaries that can be then accessed by multiple apps. This is created under the per-user Nim cache directory.
Use name to specify the subdirectory name for a project.
forceClean is enabled by default and effectively deletes the folder if Nim is compiled with the -f or --forceBuild flag. This allows any project to start out with a clean cache dir on a forced build.
NOTE: avoid calling getProjectCacheDir() multiple times on the same name when forceClean = true else checked out source might get deleted at the wrong time during build.
- E.g.
nimgit2 downloads libgit2 source so name = "libgit2"
nimarchive downloads libarchive, bzlib, liblzma and zlib so name = "nimarchive" / "libarchive" for libarchive, etc.
proc extractZip(zipfile, outdir: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
- Extract a zip file using powershell on Windows and unzip on other systems to the specified output directory
proc extractTar(tarfile, outdir: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
- Extract a tar file using tar, 7z or 7za to the specified output directory
proc downloadUrl(url, outdir: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ReadDirEffect, ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
-
Download a file using curl or wget (or powershell on Windows) to the specified directory
If an archive file, it is automatically extracted after download.
proc gitReset(outdir: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
- Hard reset the git repository at the specified directory
proc gitCheckout(file, outdir: string) {...}{.raises: [Exception, ValueError, OSError, IOError, KeyError], tags: [RootEffect, ExecIOEffect, ReadIOEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
-
Checkout the specified file in the git repository at outdir
This effectively resets all changes in the file and can be used to undo any changes that were made to source files to enable successful wrapping with cImport() or c2nImport().
proc gitPull(url: string; outdir = ""; plist = ""; checkout = "") {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ReadDirEffect, ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
-
Pull the specified git repository to the output directory
plist is the list of specific files and directories or wildcards to sparsely checkout. Multiple values can be specified one entry per line. It is optional and if omitted, the entire repository will be checked out.
checkout is the git tag, branch or commit hash to checkout once the repository is downloaded. This allows for pinning to a specific version of the code.
proc findFile(file: string; dir: string; recurse = true; first = false; regex = false): string {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
-
Find the file in the specified directory
file is a regular expression if regex is true
Turn off recursive search with recurse and stop on first match with first. Without it, the shortest match is returned.
proc flagBuild(base: string; flags: openArray[string]): string {...}{.raises: [ValueError], tags: [].}
-
Simple helper proc to generate flags for configure, cmake, etc.
Every entry in flags is replaced into the base string and concatenated to the result.
- E.g.
- base = "--disable-$#" flags = @["one", "two"]
flagBuild(base, flags) => " --disable-one --disable-two"
proc linkLibs(names: openArray[string]; staticLink = true): string {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
-
Create linker flags for specified libraries
Prepends lib to the name so you only need ssl for libssl.
proc configure(path, check: string; flags = "") {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ReadDirEffect, ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
-
Run the GNU configure command to generate all Makefiles or other build scripts in the specified path
If a configure script is not present and an autogen.sh script is present, it will be run before attempting configure.
Next, if configure.ac or configure.in exist, autoreconf will be executed.
check is a file that will be generated by the configure command. This is required to prevent configure from running on every build. It is relative to the path and should not be an absolute path.
flags are any flags that should be passed to the configure command.
proc getCmakeIncludePath(paths: openArray[string]): string {...}{.raises: [], tags: [].}
-
Create a cmake flag to specify custom include paths
Result can be included in the flag parameter for cmake() or the cmakeFlags parameter for getHeader().
proc setCmakeProperty(outdir, name, property, value: string) {...}{. raises: [IOError, ValueError], tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect].}
-
Set a cmake property in outdir / CMakeLists.txt - usable in the xxxPreBuild hook for getHeader()
set_target_properties(name PROPERTIES property "value")
proc setCmakeLibName(outdir, name, prefix = ""; oname = ""; suffix = "") {...}{. raises: [ValueError, IOError], tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect].}
-
Set a cmake property in outdir / CMakeLists.txt to specify a custom library output name - usable in the xxxPreBuild hook for getHeader()
prefix is typically lib oname is the library name suffix is typically .a
Sometimes, cmake generates non-standard library names - e.g. zlib compiles to libzlibstatic.a on Windows. This proc can help rename it to libzlib.a so that getHeader() can find it after the library is compiled.
set_target_properties(name PROPERTIES PREFIX "prefix") set_target_properties(name PROPERTIES OUTPUT_NAME "oname") set_target_properties(name PROPERTIES SUFFIX "suffix")
proc setCmakePositionIndependentCode(outdir: string) {...}{.raises: [IOError], tags: [ReadDirEffect, ReadIOEffect, WriteIOEffect].}
- Set a cmake directive to create libraries with -fPIC enabled
proc cmake(path, check, flags: string) {...}{.raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ReadDirEffect, ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect].}
-
Run the cmake command to generate all Makefiles or other build scripts in the specified path
path will be created since typically cmake is run in an empty directory.
check is a file that will be generated by the cmake command. This is required to prevent cmake from running on every build. It is relative to the path and should not be an absolute path.
flags are any flags that should be passed to the cmake command. Unlike configure, it is required since typically it will be the path to the repository, typically .. when path is a subdir.
proc make(path, check: string; flags = ""; regex = false) {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
-
Run the make command to build all binaries in the specified path
check is a file that will be generated by the make command. This is required to prevent make from running on every build. It is relative to the path and should not be an absolute path.
flags are any flags that should be passed to the make command.
regex can be set to true if check is a regular expression.
If make.exe is missing and mingw32-make.exe is available, it will be copied over to make.exe in the same location.
proc getCompilerMode(path: string): string {...}{.raises: [], tags: [].}
- Determines a target language mode from an input filename, if one is not already specified.
proc getGccModeArg(mode: string): string {...}{.raises: [], tags: [].}
- Produces a GCC argument that explicitly sets the language mode to be used by the compiler.
proc getCompiler(): string {...}{.raises: [], tags: [ReadEnvEffect].}
proc getGccPaths(mode: string): seq[string] {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
proc getGccLibPaths(mode: string): seq[string] {...}{. raises: [ValueError, OSError, Exception, IOError, KeyError], tags: [ExecIOEffect, ReadIOEffect, RootEffect, WriteIOEffect, ReadEnvEffect, ReadDirEffect].}
Macros
macro setDefines(defs: static openArray[string]): untyped
-
Specify -d:xxx values in code instead of having to rely on the command line or cfg or nims files.
At this time, Nim does not allow creation of -d:xxx defines in code. In addition, Nim only loads config files for the module being compiled but not for imported packages. This becomes a challenge when wanting to ship a wrapper library that wants to control getHeader() for an underlying package.
E.g. nimarchive wanting to set -d:lzmaStatic
The consumer of nimarchive would need to set such defines as part of their project, making it inconvenient.
By calling this proc with the defines preferred before importing such a module, the caller can set the behavior in code instead.
setDefines(@["lzmaStatic", "lzmaDL", "lzmaSetVer=5.2.4"]) import lzma
macro clearDefines(): untyped
- Clear all defines set using setDefines().
macro isDefined(def: untyped): untyped
- Check if -d:xxx is set globally or via setDefines()
macro getHeader(header: static[string]; giturl: static[string] = ""; dlurl: static[string] = ""; outdir: static[string] = ""; conFlags: static[string] = ""; cmakeFlags: static[string] = ""; makeFlags: static[string] = ""; altNames: static[string] = ""; buildTypes: static[openArray[BuildType]] = [btCmake, btAutoconf]): untyped
-
Get the path to a header file for wrapping with cImport() or c2nImport().
This proc checks -d:xxx defines based on the header name (e.g. lzma from lzma.h), and accordingly employs different ways to obtain the source.
-d:xxxStd - search standard system paths. E.g. /usr/include and /usr/lib on Linux -d:xxxGit - clone source from a git repo specified in giturl -d:xxxDL - download source from dlurl and extract if required
This allows a single wrapper to be used in different ways depending on the user's needs. If no -d:xxx defines are specified, outdir will be searched for the header as is.
If multiple -d:xxx defines are specified, precedence is Std and then Git or DL. This allows using a system installed library if available before falling back to manual building.
-d:xxxSetVer=x.y.z can be used to specify which version to use. It is used as a tag name for Git whereas for DL, it replaces $1 in the URL defined.
All defines can also be set in code using setDefines().
The library is then configured (with cmake or autotools if possible) and built using make, unless using -d:xxxStd which presumes that the system package manager was used to install prebuilt headers and binaries.
The header path is stored in const xxxPath and can be used in a cImport() call in the calling wrapper. The dynamic library path is stored in const xxxLPath and can be used for the dynlib parameter (within quotes) or with {.passL.}.
-d:xxxStatic can be specified to statically link with the library instead. This will automatically add a {.passL.} call to the static library for convenience.
conFlags, cmakeFlags and makeFlags allow sending custom parameters to configure, cmake and make in case additional configuration is required as part of the build process.
altNames is a list of alternate names for the library - e.g. zlib uses zlib.h for the header but the typical lib name is libz.so and not libzlib.so. However, it is libzlib.dll on Windows if built with cmake. In this case, altNames = "z,zlib". Comma separate for multiple alternate names without spaces.
buildTypes specifies a list of in order build strategies to use when building the downloaded source files. Default is [btCmake, btAutoconf]
The original header name is not included by default if altNames is set since it could cause the wrong lib to be selected. E.g. SDL2/SDL.h could pick libSDL.so even if altNames = "SDL2". Explicitly include it in altNames like the zlib example when required.
xxxPreBuild is a hook that is called after the source code is pulled from Git or downloaded but before the library is built. This might be needed if some initial prep needs to be done before compilation. A few values are provided to the hook to help provide context:
outdir is the same outdir passed in and header is the discovered header path in the downloaded source code.
Simply define proc xxxPreBuild(outdir, header: string) in the wrapper and it will get called prior to the build process.