Forward pragmas to toast

This commit is contained in:
Ganesh Viswanathan 2020-07-14 18:08:59 -05:00
commit 6ffacf92fc
15 changed files with 162 additions and 306 deletions

View file

@ -139,6 +139,8 @@ cImport("clib.h") # Generate wrappers for header specified
cCompile("clib/src/*.c") # Compile in any implementation source files
```
All `{.compileTime.}` procs must be used in a compile time context, like `cDebug()` and `cDisableCaching()` above.
Module documentation for the wrapper API can be found [here](https://nimterop.github.io/nimterop/cimport.html).
#### Preprocessing

View file

@ -79,10 +79,6 @@ proc jsonGet(url: string): JsonNode =
discard
rmFile(file)
template fixOutDir() {.dirty.} =
let
outdir = if outdir.isAbsolute(): outdir else: getProjectDir() / outdir
proc `==`*(pkg1, pkg2: ConanPackage): bool =
## Check if two ConanPackage objects are equal
(not pkg1.isNil and not pkg2.isNil and
@ -282,9 +278,8 @@ proc getConanRevisions*(pkg: ConanPackage, bld: ConanBuild) =
proc loadConanInfo*(outdir: string): ConanPackage =
## Load cached package info from `outdir/conaninfo.json`
fixOutDir()
let
file = outdir / conanInfo
file = fixRelPath(outdir) / conanInfo
if fileExists(file):
when (NimMajor, NimMinor, NimPatch) < (1, 2, 0):
@ -297,9 +292,8 @@ proc loadConanInfo*(outdir: string): ConanPackage =
proc saveConanInfo*(pkg: ConanPackage, outdir: string) =
## Save downloaded package info to `outdir/conaninfo.json`
fixOutDir()
let
file = outdir / conanInfo
file = fixRelPath(outdir) / conanInfo
when (NimMajor, NimMinor, NimPatch) < (1, 2, 0):
writeFile(file, $$pkg)
@ -329,11 +323,11 @@ proc dlConanBuild*(pkg: ConanPackage, bld: ConanBuild, outdir: string, revision
## Download specific `revision` of `bld` to `outdir`
##
## If omitted, the latest revision (first) is downloaded
fixOutDir()
doAssert bld.revisions.len != 0, "No build revisions found for Conan.io package " & pkg.getUriFromConanPackage()
let
outdir = fixRelPath(outdir)
revision =
if revision.len != 0:
revision
@ -376,8 +370,9 @@ proc downloadConan*(pkg: ConanPackage, outdir: string, main = true) =
##
## High-level API that handles the end to end Conan process flow to find
## latest package binary and downloads and extracts it to `outdir`.
fixOutDir()
let
outdir = fixRelPath(outdir)
pkg =
if pkg.version.len == 0:
searchConan(pkg)
@ -415,7 +410,8 @@ proc dlConanRequires*(pkg: ConanPackage, bld: ConanBuild, outdir: string) =
##
## This is not required for shared libs since conan builds them
## with all dependencies statically linked in
fixOutDir()
let
outdir = fixRelPath(outdir)
if bld.options["shared"] == "False":
for req in bld.requires:
let

View file

@ -33,10 +33,6 @@ var
# Reuse dependencies already downloaded
gJBBRequires {.compileTime.}: Table[string, JBBPackage]
template fixOutDir() {.dirty.} =
let
outdir = if outdir.isAbsolute(): outdir else: getProjectDir() / outdir
proc `==`*(pkg1, pkg2: JBBPackage): bool =
## Check if two JBBPackage objects are equal
(not pkg1.isNil and not pkg2.isNil and
@ -164,9 +160,8 @@ proc getJBBRepo*(pkg: JBBPackage, outdir: string) =
proc loadJBBInfo*(outdir: string): JBBPackage =
## Load cached package info from `outdir/jbbinfo.json`
fixOutDir()
let
file = outdir / jbbInfo
file = fixRelPath(outdir) / jbbInfo
if fileExists(file):
when (NimMajor, NimMinor, NimPatch) < (1, 2, 0):
@ -179,9 +174,8 @@ proc loadJBBInfo*(outdir: string): JBBPackage =
proc saveJBBInfo*(pkg: JBBPackage, outdir: string) =
## Save downloaded package info to `outdir/jbbinfo.json`
fixOutDir()
let
file = outdir / jbbInfo
file = fixRelPath(outdir) / jbbInfo
when (NimMajor, NimMinor, NimPatch) < (1, 2, 0):
writeFile(file, $$pkg)
@ -194,7 +188,9 @@ proc downloadJBB*(pkg: JBBPackage, outdir: string, main = true) =
##
## High-level API that handles the end to end JBB process flow to find
## latest package binary and downloads and extracts it to `outdir`.
fixOutDir()
let
outdir = fixRelPath(outdir)
if main:
let
cpkg = loadJBBInfo(outdir)
@ -226,7 +222,8 @@ proc downloadJBB*(pkg: JBBPackage, outdir: string, main = true) =
proc dlJBBRequires*(pkg: JBBPackage, outdir: string) =
## Download all required dependencies of this `pkg`
fixOutDir()
let
outdir = fixRelPath(outdir)
for i in 0 ..< pkg.requires.len:
let
rpkg = pkg.requires[i]

View file

@ -234,3 +234,7 @@ proc getOutDir*(projectDir = ""): string =
proc getNimteropCacheDir*(): string =
## Get location to cache all nimterop artifacts
result = getNimcacheDir() / "nimterop"
proc fixRelPath*(path: string): string =
## If `path` is relative, consider relative to `projectPath`
if path.isAbsolute: path else: getProjectDir() / path

View file

@ -1,78 +1,17 @@
##[
This is the main nimterop import file to help with wrapping C/C++ source code.
Check out `template.nim <https://github.com/nimterop/nimterop/blob/master/nimterop/template.nim>`_
as a starting point for wrapping a new library. The template can be copied and
trimmed down and modified as required. `templite.nim <https://github.com/nimterop/nimterop/blob/master/nimterop/templite.nim>`_ is a shorter
version for more experienced users.
All `{.compileTime.}` procs must be used in a compile time context, e.g. using:
.. code-block:: c
static:
cAddStdDir()
]##
import hashes, macros, os, strformat, strutils
import "."/[globals, paths]
import "."/build/[ccompiler, misc, nimconf, shell]
proc interpPath(dir: string): string=
# TODO: more robust: needs a DirSep after "$projpath"
# disabling this interpolation as this is error prone, but other less
# interpolations can be added, eg see https://github.com/nim-lang/Nim/pull/10530
# result = dir.replace("$projpath", getProjectPath())
result = dir
proc joinPathIfRel(path1: string, path2: string): string =
if path2.isAbsolute:
result = path2
else:
result = joinPath(path1, path2)
proc findPath(path: string, fail = true): string =
# Relative to project path
result = joinPathIfRel(getProjectPath(), path).replace("\\", "/")
let
path = fixRelPath(path)
result = path.replace("\\", "/")
if not fileExists(result) and not dirExists(result):
doAssert (not fail), "File or directory not found: " & path
result = ""
proc walkDirImpl(indir, inext: string, file=true): seq[string] =
let
dir = joinPathIfRel(getProjectPath(), indir)
ext =
if inext.nBl:
when not defined(Windows):
"-name " & inext
else:
"\\" & inext
else:
""
let
cmd =
when defined(Windows):
if file:
"cmd /c dir /s/b/a-d " & dir.replace("/", "\\") & ext
else:
"cmd /c dir /s/b/ad " & dir.replace("/", "\\")
else:
if file:
"find $1 -type f $2" % [dir, ext]
else:
"find $1 -type d" % dir
(output, ret) = execAction(cmd, die = false)
if ret == 0:
result = output.splitLines()
proc fixRelFile(file: string): string =
if file.isAbsolute(): file else: getProjectDir() / file
proc getCacheValue(fullpath: string): string =
if not gStateCT.nocache:
result = fullpath.getFileDate()
@ -123,6 +62,15 @@ proc getToast(fullpaths: seq[string], recurse: bool = false, dynlib: string = ""
for i in gStateCT.exclude:
cmd.add &" --exclude+={i.sanitizePath}"
for i in gStateCT.passC:
cmd.add &" --passC+={i.quoteShell}"
for i in gStateCT.passL:
cmd.add &" --passL+={i.quoteShell}"
for i in gStateCT.compile:
cmd.add &" --compile+={i.sanitizePath}"
if not noNimout:
cmd.add &" --pnim"
@ -147,7 +95,7 @@ proc getToast(fullpaths: seq[string], recurse: bool = false, dynlib: string = ""
($(cmd & cacheKey).hash().abs()).addFileExt(ext)
if outFile.nBl:
result = fixRelFile(outFile)
result = fixRelPath(outFile)
else:
result = cacheFile
@ -384,7 +332,7 @@ macro cPluginPath*(path: static[string]): untyped =
doAssert fileExists(path), "Plugin file not found: " & path
cPluginHelper(readFile(path), imports = "")
proc cSearchPath*(path: string): string {.compileTime.}=
proc cSearchPath*(path: string): string {.compileTime.} =
## Get full path to file or directory `path` in search path configured
## using `cAddSearchDir()` and `cAddStdDir()`.
##
@ -416,27 +364,38 @@ proc cDisableCaching*() {.compileTime.} =
## `nim -f` can also be used to flush the cached content.
gStateCT.nocache = true
macro cDefine*(name: static string, val: static string = ""): untyped =
macro cDefine*(name: static[string], val: static[string] = ""): untyped =
## `#define` an identifer that is forwarded to the C/C++ preprocessor if
## called within `cImport()` or `c2nImport()` as well as to the C/C++
## compiler during Nim compilation using `{.passC: "-DXXX".}`
result = newNimNode(nnkStmtList)
var str = name
# todo: see https://github.com/nimterop/nimterop/issues/100 for
# edge case of empty strings
if val.nBl:
str &= &"={val.quoteShell}"
if str notin gStateCT.defines:
gStateCT.defines.add(str)
str = "-D" & str
result.add quote do:
{.passC: `str`.}
macro cDefine*(values: static seq[string]): untyped =
## `#define` multiple identifers that are forwarded to the C/C++ preprocessor
## if called within `cImport()` or `c2nImport()` as well as to the C/C++
## compiler during Nim compilation using `{.passC: "-DXXX".}`
for value in values:
let
spl = value.split("=", maxsplit = 1)
name = spl[0]
val = if spl.len == 2: spl[1] else: ""
discard quote do:
cDefine(`name`, `val`)
if gStateCT.debug:
gecho result.repr & "\n"
macro cPassC*(value: static string): untyped =
## Create a `{.passC.}` entry that gets forwarded to the C/C++ compiler
## during Nim compilation.
gStateCT.passC.add value
macro cPassL*(value: static string): untyped =
## Create a `{.passL.}` entry that gets forwarded to the C/C++ compiler
## during Nim compilation.
gStateCT.passL.add value
proc cAddSearchDir*(dir: string) {.compileTime.} =
## Add directory `dir` to the search path used in calls to
@ -445,8 +404,8 @@ proc cAddSearchDir*(dir: string) {.compileTime.} =
import nimterop/paths, os
static:
cAddSearchDir testsIncludeDir()
doAssert cSearchPath("test.h").existsFile
var dir = interpPath(dir)
doAssert cSearchPath("test.h").fileExists
if dir notin gStateCT.searchDirs:
gStateCT.searchDirs.add(dir)
@ -458,19 +417,11 @@ macro cIncludeDir*(dirs: static seq[string], exclude: static[bool] = false): unt
## Set `exclude = true` if the contents of these include directories should
## not be included in the wrapped output.
for dir in dirs:
var dir = interpPath(dir)
result = newNimNode(nnkStmtList)
let fullpath = findPath(dir)
if fullpath notin gStateCT.includeDirs:
gStateCT.includeDirs.add(fullpath)
if exclude:
gStateCT.exclude.add(fullpath)
let str = &"-I{fullpath.quoteShell}"
result.add quote do:
{.passC: `str`.}
if gStateCT.debug:
gecho result.repr
macro cIncludeDir*(dir: static[string], exclude: static[bool] = false): untyped =
## Add an include directory that is forwarded to the C/C++ preprocessor if
@ -501,16 +452,17 @@ proc cAddStdDir*(mode = "c") {.compileTime.} =
## Add the standard `c` [default] or `cpp` include paths to search
## path used in calls to `cSearchPath()`.
runnableExamples:
static: cAddStdDir()
import os
doAssert cSearchPath("math.h").existsFile
static:
cAddStdDir()
doAssert cSearchPath("math.h").fileExists
for inc in getGccPaths(mode):
cAddSearchDir inc
macro cCompile*(path: static string, mode = "c", exclude = ""): untyped =
macro cCompile*(path: static string, mode: static[string] = "c", exclude: static[string] = ""): untyped =
## Compile and link C/C++ implementation into resulting binary using `{.compile.}`
##
## `path` can be a specific file or contain wildcards:
## `path` can be a specific file or contain `*` wildcard for filename:
##
## .. code-block:: nim
##
@ -532,26 +484,21 @@ macro cCompile*(path: static string, mode = "c", exclude = ""): untyped =
##
## cCompile("path/to/dir", exclude="test2.c")
result = newNimNode(nnkStmtList)
var
stmt = ""
proc fcompile(file: string): string =
proc fcompile(file: string) =
let
(_, fn, ext) = file.splitFile()
var
ufn = fn
uniq = 1
while ufn in gStateCT.compile:
while ufn in gStateCT.compcache:
ufn = fn & $uniq
uniq += 1
# - https://github.com/nim-lang/Nim/issues/10299
# - https://github.com/nim-lang/Nim/issues/10486
gStateCT.compile.add(ufn)
gStateCT.compcache.add(ufn)
if fn == ufn:
return "{.compile: \"$#\".}\n" % file.replace("\\", "/")
gStateCT.compile.add file.replace("\\", "/")
else:
# - https://github.com/nim-lang/Nim/issues/9370
let
@ -559,7 +506,7 @@ macro cCompile*(path: static string, mode = "c", exclude = ""): untyped =
tmpFile = file.parentDir() / &"_nimterop_{$hash}_{ufn}{ext}"
if not tmpFile.fileExists() or file.getFileDate() > tmpFile.getFileDate():
cpFile(file, tmpFile)
return "{.compile: \"$#\".}\n" % tmpFile.replace("\\", "/")
gStateCT.compile.add tmpFile.replace("\\", "/")
# Due to https://github.com/nim-lang/Nim/issues/9863
# cannot use seq[string] for excludes
@ -572,33 +519,37 @@ macro cCompile*(path: static string, mode = "c", exclude = ""): untyped =
if excl in file:
result = false
proc dcompile(dir, exclude: string, ext=""): string =
proc dcompile(dir, exclude: string, ext="") =
let
files = walkDirImpl(dir, ext)
(dir, pat) =
if "*" in dir:
dir.splitPath()
else:
(dir, "")
for f in files:
if f.nBl and f.notExcluded(exclude):
result &= fcompile(f)
for file in walkDirRec(dir):
if ext.nBl or pat.nBl:
let
fext = file.splitFile().ext
if (ext.nBl and fext != ext) or (pat.nBl and fext != pat[1 .. ^1]):
continue
if file.notExcluded(exclude):
fcompile(file)
if path.contains("*") or path.contains("?"):
stmt &= dcompile(path, exclude.strVal())
if "*" in path:
dcompile(path, exclude)
else:
let fpath = findPath(path)
if fileExists(fpath) and fpath.notExcluded(exclude.strVal()):
stmt &= fcompile(fpath)
if fileExists(fpath) and fpath.notExcluded(exclude):
fcompile(fpath)
elif dirExists(fpath):
if mode.strVal().contains("cpp"):
for i in @["*.cpp", "*.c++", "*.cc", "*.cxx"]:
stmt &= dcompile(fpath, exclude.strVal(), i)
if mode.contains("cpp"):
for i in @[".cpp", ".c++", ".cc", ".cxx"]:
dcompile(fpath, exclude, i)
when not defined(Windows):
stmt &= dcompile(fpath, exclude.strVal(), "*.C")
dcompile(fpath, exclude, ".C")
else:
stmt &= dcompile(fpath, exclude.strVal(), "*.c")
result.add stmt.parseStmt()
if gStateCT.debug:
gecho result.repr
dcompile(fpath, exclude, ".c")
macro cImport*(filenames: static seq[string], recurse: static bool = false, dynlib: static string = "",
mode: static string = "c", flags: static string = "", nimFile: static string = ""): untyped =
@ -726,7 +677,7 @@ macro c2nImport*(filename: static string, recurse: static bool = false, dynlib:
let
hFile = getToast(@[fullpath], recurse, dynlib, mode, noNimout = true)
nimFile = if nimFile.nBl: fixRelFile(nimFile) else: hFile.changeFileExt("nim")
nimFile = if nimFile.nBl: fixRelPath(nimFile) else: hFile.changeFileExt("nim")
header = "header" & fullpath.splitFile().name.split(seps = {'-', '.'}).join()
if not fileExists(nimFile) or gStateCT.nocache or compileOption("forceBuild"):
@ -741,8 +692,29 @@ macro c2nImport*(filename: static string, recurse: static bool = false, dynlib:
if flags.nBl:
cmd.add &" {flags}"
# Have to create pragmas for c2nim since toast handles this at runtime
for i in gStateCT.defines:
cmd.add &" --assumedef:{i.quoteShell}"
let str = "-D" & i
result.add quote do:
{.passC: `str`.}
for i in gStateCT.includeDirs:
let str = &"-I{i.quoteShell}"
result.add quote do:
{.passC: `str`.}
for i in gStateCT.passC:
result.add quote do:
{.passC: `i`.}
for i in gStateCT.passL:
result.add quote do:
{.passL: `i`.}
for i in gStateCT.compile:
result.add quote do:
{.compile: `i`.}
let
(c2nimout, ret) = execAction(cmd)

View file

@ -15,6 +15,7 @@ type
State* = ref object
# Command line arguments to toast - some forwarded from cimport.nim
compile*: seq[string] # `--compile` to create `{.compile.}` entries in generated wrapper
convention*: string # `--convention | -C` to change calling convention from cdecl default
debug*: bool # `cDebug()` or `--debug | -d` to enable debug mode
defines*: seq[string] # Symbols added by `cDefine()` and `--define | -D` for C/C++ preprocessor/compiler
@ -26,6 +27,8 @@ type
nim*: string # `--nim` to specify full path to Nim compiler
noComments*: bool # `--noComments | -c` to disable rendering comments in wrappers
noHeader*: bool # `--noHeader | -H` to skip {.header.} pragma in wrapper
passC*: seq[string] # `--passC` to create `{.passC.}` entries in the generated wrapper
passL*: seq[string] # `--passL` to create `{.passL.}` entries in the generated wrapper
past*: bool # `--past | -a` to print tree-sitter AST of code
pluginSourcePath*: string # `--pluginSourcePath` specified path to plugin file to compile and load
pnim*: bool # `--pnim | -n` to render Nim wrapper for header
@ -77,7 +80,7 @@ type
wrapperHeader*: string
else:
# cimport.nim specific
compile*: seq[string] # `cCompile()` list of files already processed
compcache*: seq[string] # `cCompile()` list of files already processed
nocache*: bool # `cDisableCaching()` to disable caching of artifacts
overrides*: string # `cOverride()` code which gets added to `cPlugin()` output
pluginSource*: string # `cPlugin()` generated code to write to plugin file from

View file

@ -1,111 +0,0 @@
import os, strutils
import nimterop/[cimport, build, paths]
# Documentation:
# https://github.com/nimterop/nimterop
# https://nimterop.github.io/nimterop/cimport.html
const
# Location where any sources should get downloaded. Adjust depending on
# actual location of wrapper file relative to project.
baseDir = currentSourcePath.parentDir()/"build"
# All files and dirs should be inside to baseDir
srcDir = baseDir/"project"
static:
# Print generated Nim to output
cDebug()
# Disable caching so that wrapper is generated every time. Useful during
# development. Remove once wrapper is working as expected.
cDisableCaching()
# Download C/C++ source code from a git repository
gitPull("https://github.com/user/project", outdir = srcDir, plist = """
include/*.h
src/*.c
""", checkout = "tag/branch/hash")
# Download source from the web - zip files are auto extracted
downloadUrl("https://hostname.com/file.h", outdir = srcDir)
# Run GNU configure on the source
when defined(posix):
configure(srcDir, fileThatShouldGetGenerated, flagsToConfigure)
# Run cmake on the source
cmake(srcDir/"build", fileThatShouldGetGenerated, flagsToCmake)
# Run standard file/directory operations with mkDir(), cpFile(), mvFile()
# Edit file contents if required with readFile(), writeFile() and standard
# string operations
# Run any other external commands with execAction()
# Skip any symbols from being wrapped
cSkipSymbol(@["type1", "proc2"])
# Manually wrap any symbols since nimterop cannot or incorrectly wraps them
cOverride:
# Standard Nim code to wrap types, consts, procs, etc.
type
symbol = object
# Specify include directories for gcc and Nim
cIncludeDir(srcDir/"include")
# Define global symbols
cDefine("SYMBOL", "value")
# Any global compiler options
{.passC: "flags".}
# Any global linker options
{.passL: "flags".}
# Compile in any common source code
cCompile(srcDir/"file.c")
# Perform OS specific tasks
when defined(Windows):
# Windows specific symbols, options and files
# Dynamic library to link against
const dynlibFile =
when defined(cpu64):
"xyz64.dll"
else:
"xyz32.dll"
elif defined(posix):
# Common posix symbols, options and files
when defined(linux):
# Linux specific
const dynlibFile = "libxyz.so(.2|.1|)"
elif defined(osx):
# MacOSX specific
const dynlibFile = "libxyz(.2|.1|).dylib"
else:
static: doAssert false
else:
static: doAssert false
# Use cPlugin() to make any symbol changes
cPlugin:
import strutils
# Symbol renaming examples
proc onSymbol*(sym: var Symbol) {.exportc, dynlib.} =
# Get rid of leading and trailing underscores
sym.name = sym.name.strip(chars = {'_'})
# Remove prefixes or suffixes from procs
if sym.kind == nskProc and sym.name.contains("SDL_"):
sym.name = sym.name.replace("SDL_", "")
# Finally import wrapped header file. Recurse if #include files should also
# be wrapped. Set dynlib if binding to dynamic library.
cImport(srcDir/"include/file.h", recurse = true, dynlib="dynlibFile")

View file

@ -1,36 +0,0 @@
import os, strutils
import nimterop/[cimport, build, paths]
const
baseDir = currentSourcePath.parentDir()/"build"
srcDir = baseDir/"project"
static:
cDebug()
cDisableCaching()
gitPull("https://github.com/user/project", outdir = srcDir, plist = """
include/*.h
src/*.c
""", checkout = "tag/branch/hash")
downloadUrl("https://hostname.com/file.h", outdir = srcDir)
cIncludeDir(srcDir/"include")
cDefine("SYMBOL", "value")
{.passC: "flags".}
{.passL: "flags".}
cCompile(srcDir/"file.c")
cPlugin:
import strutils
proc onSymbol*(sym: var Symbol) {.exportc, dynlib.} =
sym.name = sym.name.strip(chars = {'_'})
cImport(srcDir/"include/file.h", recurse = true)

View file

@ -34,6 +34,7 @@ proc process(gState: State, path: string) =
# CLI processing with default values
proc main(
check = false,
compile: seq[string] = @[],
convention = "cdecl",
debug = false,
defines: seq[string] = @[],
@ -46,6 +47,8 @@ proc main(
noComments = false,
noHeader = false,
output = "",
passC: seq[string] = @[],
passL: seq[string] = @[],
past = false,
pluginSourcePath: string = "",
pnim = false,
@ -62,6 +65,7 @@ proc main(
# Setup global state with arguments
gState = State(
compile: compile,
convention: convention,
debug: debug,
defines: defines,
@ -73,6 +77,8 @@ proc main(
nim: nim.sanitizePath,
noComments: noComments,
noHeader: noHeader,
passC: passC,
passL: passL,
past: past,
pluginSourcePath: pluginSourcePath,
pnim: pnim,
@ -220,6 +226,7 @@ when isMainModule:
import cligen
dispatch(main, help = {
"check": "check generated wrapper with compiler",
"compile": "create {.compile.} entries in generated wrapper",
"convention": "calling convention for wrapped procs",
"debug": "enable debug output",
"defines": "definitions to pass to preprocessor",
@ -232,6 +239,8 @@ when isMainModule:
"noComments": "exclude top-level comments from output",
"noHeader": "skip {.header.} pragma in wrapper",
"output": "file to output content - default: stdout",
"passC": "create {.passC.} entries in generated wrapper",
"passL": "create {.passL.} entries in generated wrapper",
"past": "print AST output",
"pluginSourcePath": "nim file to build and load as a plugin",
"pnim": "print Nim output",

View file

@ -1881,11 +1881,31 @@ proc setupPragmas(gState: State, root: TSNode, fullpath: string) =
gState.pragmaSection.add dynPragma
count += 1
# Add `{.experimental: "codeReordering".} for #206
# Only if not already done
if gState.pragmaSection.len == count:
# Only if not already done
# Add `{.experimental: "codeReordering".} for #206
gState.pragmaSection.add gState.newPragma(root, "experimental", newStrNode(nkStrLit, "codeReordering"))
# Create `{.passC.}` from defines
for define in gState.defines:
gState.pragmaSection.add gState.newPragma(root, "passC", newStrNode(nkStrLit, "-D" & define))
# Create `{.passC.}` from include directories
for inc in gState.includeDirs:
gState.pragmaSection.add gState.newPragma(root, "passC", newStrNode(nkStrLit, "-I" & inc.quoteShell))
# Create `{.passC.}` from passC
for passC in gState.passC:
gState.pragmaSection.add gState.newPragma(root, "passC", newStrNode(nkStrLit, passC))
# Create `{.passL.}` from passL
for passL in gState.passL:
gState.pragmaSection.add gState.newPragma(root, "passL", newStrNode(nkStrLit, passL))
# Create `{.compile.}` for specified files
for file in gState.compile:
gState.pragmaSection.add gState.newPragma(root, "compile", newStrNode(nkStrLit, file))
proc initNim*(gState: State) =
# Initialize for parseNim() one time
gState.wrapperHeader = "{.push hint[ConvFromXtoItselfNotNeeded]: off.}\n"

View file

@ -22,13 +22,13 @@ when not libssh2Static:
when not defined(Windows) and not isDefined(libssh2JBB):
proc zlibVersion(): cstring {.importc, dynlib: libssh2LPath.}
else:
cPassL("-lpthread")
cImport(libssh2Path, recurse = true, flags = "-c -E_ -F_")
when not defined(Windows) and not isDefined(libssh2JBB):
proc zlibVersion(): cstring {.importc.}
{.passL: "-lpthread".}
assert libssh2_init(0) == 0
let

View file

@ -35,13 +35,13 @@ cPlugin:
cOverride:
proc OPENSSL_die*(assertion: cstring; file: cstring; line: cint) {.importc.}
cPassL(cryptoLPath)
# Skip comments for https://github.com/tree-sitter/tree-sitter-c/issues/44
cImport(@[
basePath / "rsa.h",
basePath / "err.h",
], recurse = true, flags = "-s -c " & FLAGS)
{.passL: cryptoLPath.}
OpensslInit()
echo $OPENSSL_VERSION_TEXT

View file

@ -2,7 +2,7 @@ import macros, os, sets, strutils
import nimterop/[cimport]
{.passC: "-DNIMTEROP".}
cPassC("-DNIMTEROP")
static:
# Skip casting on lower nim compilers because

View file

@ -24,15 +24,15 @@ cIncludeDir(incl)
when defined(osx):
cDefine("WITH_COREAUDIO")
{.passL: "-framework CoreAudio -framework AudioToolbox".}
cPassL("-framework CoreAudio -framework AudioToolbox")
cCompile(src/"backend/coreaudio/*.cpp")
elif defined(Linux):
{.passL: "-lpthread".}
cPassL("-lpthread")
cDefine("WITH_OSS")
cCompile(src/"backend/oss/*.cpp")
elif defined(Windows):
{.passC: "-msse".}
{.passL: "-lwinmm".}
cPassC("-msse")
cPassL("-lwinmm")
cDefine("WITH_WINMM")
cCompile(src/"backend/winmm/*.cpp")
else:

View file

@ -65,12 +65,12 @@ when zlibGit or zlibDL:
when dirExists(baseDir / "buildcache"):
cIncludeDir(baseDir / "buildcache")
when not zlibStatic:
when not isDefined(zlibStatic):
cImport(zlibPath, recurse = true, dynlib = "zlibLPath", flags = FLAGS)
else:
when isDefined(zlibJBB):
cPassL("-no-pie")
cImport(zlibPath, recurse = true, flags = FLAGS)
echo "zlib version = " & $zlibVersion()
when isDefined(zlibJBB) and isDefined(zlibStatic):
{.passL: "-no-pie".}
echo "zlib version = " & $zlibVersion()