* refs #68 macro=>proc cSkipSymbol * refs #68 macro=>proc cDebug * refs #68 macro=>proc cDisableCaching * refs #68 notes for cDefine * refs #68 macro=>proc cAddSearchDir ; improve some runnableExamples * refs #68 macro=>proc cAddStdDir * $projpath/include => testsIncludeDir() everywhere * disable $projpath interpolation (error prone) * fix tests * make nim doc part of test suite; fix for 0.19.2
This commit is contained in:
parent
74f4485ecd
commit
9fe45ac32b
11 changed files with 99 additions and 77 deletions
|
|
@ -36,6 +36,7 @@ __Usage__
|
||||||
```nim
|
```nim
|
||||||
import nimterop/cimport
|
import nimterop/cimport
|
||||||
|
|
||||||
|
static:
|
||||||
cDebug()
|
cDebug()
|
||||||
cDefine("HAS_ABC")
|
cDefine("HAS_ABC")
|
||||||
cDefine("HAS_ABC", "DEF")
|
cDefine("HAS_ABC", "DEF")
|
||||||
|
|
|
||||||
|
|
@ -43,14 +43,18 @@ proc testAll() =
|
||||||
if defined(OSX) or defined(Windows) or not existsEnv("TRAVIS"):
|
if defined(OSX) or defined(Windows) or not existsEnv("TRAVIS"):
|
||||||
tsoloud() # requires some libraries on linux, need them installed in TRAVIS
|
tsoloud() # requires some libraries on linux, need them installed in TRAVIS
|
||||||
|
|
||||||
|
const htmldocsDir = "build/htmldocs"
|
||||||
|
|
||||||
|
proc runNimDoc() =
|
||||||
|
execCmd &"nim doc -o:{htmldocsDir} --project --index:on nimterop/all.nim"
|
||||||
|
|
||||||
task test, "Test":
|
task test, "Test":
|
||||||
for options in ["", "-d:release"]:
|
for options in ["", "-d:release"]:
|
||||||
buildToast(options)
|
buildToast(options)
|
||||||
testAll()
|
testAll()
|
||||||
|
runNimDoc()
|
||||||
|
|
||||||
task docs, "Generate docs":
|
task docs, "Generate docs":
|
||||||
# Uses: pip install ghp-import
|
# Uses: pip install ghp-import
|
||||||
execCmd "nim doc --project --index:on nimterop/cimport"
|
runNimDoc()
|
||||||
execCmd "nim doc --project --index:on nimterop/git"
|
execCmd &"ghp-import --no-jekyll -fp {htmldocsDir}"
|
||||||
execCmd "nim doc --project --index:on nimterop/plugin"
|
|
||||||
execCmd "ghp-import --no-jekyll -fp nimterop/htmldocs"
|
|
||||||
|
|
|
||||||
7
nimterop/all.nim
Normal file
7
nimterop/all.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
##[
|
||||||
|
Module that should import everything so that `nim doc --project nimtero/all` runs docs on everything.
|
||||||
|
]##
|
||||||
|
|
||||||
|
# TODO: make sure it does import everything.
|
||||||
|
|
||||||
|
import "."/[cimport,git,plugin]
|
||||||
|
|
@ -1,3 +1,13 @@
|
||||||
|
##[
|
||||||
|
Main import file to write wrappers.
|
||||||
|
Each `compileTime` proc must be used in a compile time context, eg using:
|
||||||
|
|
||||||
|
```
|
||||||
|
static:
|
||||||
|
cAddStdDir()
|
||||||
|
```
|
||||||
|
]##
|
||||||
|
|
||||||
import hashes, macros, os, strformat, strutils
|
import hashes, macros, os, strformat, strutils
|
||||||
|
|
||||||
const CIMPORT {.used.} = 1
|
const CIMPORT {.used.} = 1
|
||||||
|
|
@ -9,7 +19,10 @@ export types
|
||||||
|
|
||||||
proc interpPath(dir: string): string=
|
proc interpPath(dir: string): string=
|
||||||
# TODO: more robust: needs a DirSep after "$projpath"
|
# TODO: more robust: needs a DirSep after "$projpath"
|
||||||
result = dir.replace("$projpath", getProjectPath())
|
# 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 =
|
proc joinPathIfRel(path1: string, path2: string): string =
|
||||||
if path2.isAbsolute:
|
if path2.isAbsolute:
|
||||||
|
|
@ -184,18 +197,15 @@ macro cOverride*(body): untyped =
|
||||||
if gStateCT.debug:
|
if gStateCT.debug:
|
||||||
echo "Overriding " & gStateCT.symOverride.join(" ")
|
echo "Overriding " & gStateCT.symOverride.join(" ")
|
||||||
|
|
||||||
macro cSkipSymbol*(skips: varargs[string]): untyped =
|
proc cSkipSymbol*(skips: seq[string]) {.compileTime.} =
|
||||||
## Similar to `cOverride() <cimport.html#cOverride.m,>`_, this macro allows
|
## Similar to `cOverride() <cimport.html#cOverride.m,>`_, this macro allows
|
||||||
## filtering out symbols not of interest from the generated output.
|
## filtering out symbols not of interest from the generated output.
|
||||||
##
|
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
cSkipSymbol "proc1", "Type2"
|
static: cSkipSymbol @["proc1", "Type2"]
|
||||||
|
gStateCT.symOverride.add skips
|
||||||
for skip in skips:
|
|
||||||
gStateCT.symOverride.add skip.strVal
|
|
||||||
|
|
||||||
macro cPlugin*(body): untyped =
|
macro cPlugin*(body): untyped =
|
||||||
## When `cOverride() <cimport.html#cOverride.m,>`_ and `cSkipSymbol() <cimport.html#cSkipSymbol.m%2Cvarargs[string]>`_
|
## When `cOverride() <cimport.html#cOverride.m,>`_ and `cSkipSymbol() <cimport.html#cSkipSymbol.m%2Cseq[string]>`_
|
||||||
## are not adequate, the `cPlugin() <cimport.html#cPlugin.m,>`_ macro can be used
|
## are not adequate, the `cPlugin() <cimport.html#cPlugin.m,>`_ macro can be used
|
||||||
## to customize the generated Nim output. The following callbacks are available at
|
## to customize the generated Nim output. The following callbacks are available at
|
||||||
## this time.
|
## this time.
|
||||||
|
|
@ -242,8 +252,8 @@ macro cPlugin*(body): untyped =
|
||||||
|
|
||||||
proc cSearchPath*(path: string): string {.compileTime.}=
|
proc cSearchPath*(path: string): string {.compileTime.}=
|
||||||
## Get full path to file or directory ``path`` in search path configured
|
## Get full path to file or directory ``path`` in search path configured
|
||||||
## using `cAddSearchDir() <cimport.html#cAddSearchDir.m,>`_ and
|
## using `cAddSearchDir() <cimport.html#cAddSearchDir,>`_ and
|
||||||
## `cAddStdDir() <cimport.html#cAddStdDir.m,string>`_.
|
## `cAddStdDir() <cimport.html#cAddStdDir,string>`_.
|
||||||
##
|
##
|
||||||
## This can be used to locate files or directories that can be passed onto
|
## This can be used to locate files or directories that can be passed onto
|
||||||
## `cCompile() <cimport.html#cCompile.m,,string>`_,
|
## `cCompile() <cimport.html#cCompile.m,,string>`_,
|
||||||
|
|
@ -261,23 +271,25 @@ proc cSearchPath*(path: string): string {.compileTime.}=
|
||||||
doAssert found, "File or directory not found: " & path &
|
doAssert found, "File or directory not found: " & path &
|
||||||
" gStateCT.searchDirs: " & $gStateCT.searchDirs
|
" gStateCT.searchDirs: " & $gStateCT.searchDirs
|
||||||
|
|
||||||
macro cDebug*(): untyped =
|
proc cDebug*() {.compileTime.} =
|
||||||
## Enable debug messages and display the generated Nim code
|
## Enable debug messages and display the generated Nim code
|
||||||
|
|
||||||
gStateCT.debug = true
|
gStateCT.debug = true
|
||||||
|
|
||||||
macro cDisableCaching*(): untyped =
|
proc cDisableCaching*() {.compileTime.} =
|
||||||
## Disable caching of generated Nim code - useful during wrapper development
|
## Disable caching of generated Nim code - useful during wrapper development
|
||||||
##
|
##
|
||||||
## If files included by header being processed by `cImport() <cimport.html#cImport.m,>`_
|
## If files included by header being processed by `cImport() <cimport.html#cImport.m,>`_
|
||||||
## change and affect the generated content, they will be ignored and the cached
|
## change and affect the generated content, they will be ignored and the cached
|
||||||
## value will continue to be used . Use `cDisableCaching() <cimport.html#cDisableCaching.m,>`_
|
## value will continue to be used . Use `cDisableCaching() <cimport.html#cDisableCaching,>`_
|
||||||
## to avoid this scenario during development.
|
## to avoid this scenario during development.
|
||||||
##
|
##
|
||||||
## ``nim -f`` was broken prior to 0.19.4 but can also be used to flush the cached content.
|
## ``nim -f`` was broken prior to 0.19.4 but can also be used to flush the cached content.
|
||||||
|
|
||||||
gStateCT.nocache = true
|
gStateCT.nocache = true
|
||||||
|
|
||||||
|
# TODO: `passC` should be delayed and inserted inside `cImport`, `cCompile`
|
||||||
|
# and this should be made a proc:
|
||||||
|
# proc cDefine*(name: string, val = "") {.compileTime.} =
|
||||||
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++ compiler
|
## ``#define`` an identifer that is forwarded to the C/C++ compiler
|
||||||
## using ``{.passC: "-DXXX".}``
|
## using ``{.passC: "-DXXX".}``
|
||||||
|
|
@ -285,6 +297,8 @@ macro cDefine*(name: static string, val: static string = ""): untyped =
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
|
|
||||||
var str = name
|
var str = name
|
||||||
|
# todo: see https://github.com/genotrance/nimterop/issues/100 for
|
||||||
|
# edge case of empty strings
|
||||||
if val.nBl:
|
if val.nBl:
|
||||||
str &= &"={val.quoteShell}"
|
str &= &"={val.quoteShell}"
|
||||||
|
|
||||||
|
|
@ -292,24 +306,20 @@ macro cDefine*(name: static string, val: static string = ""): untyped =
|
||||||
gStateCT.defines.add(str)
|
gStateCT.defines.add(str)
|
||||||
str = "-D" & str
|
str = "-D" & str
|
||||||
|
|
||||||
result.add(quote do:
|
result.add quote do:
|
||||||
{.passC: `str`.}
|
{.passC: `str`.}
|
||||||
)
|
|
||||||
|
|
||||||
if gStateCT.debug:
|
if gStateCT.debug:
|
||||||
echo result.repr
|
echo result.repr
|
||||||
|
|
||||||
macro cAddSearchDir*(dir: static string): untyped =
|
proc cAddSearchDir*(dir: string) {.compileTime.} =
|
||||||
## Add directory ``dir`` to the search path used in calls to
|
## Add directory ``dir`` to the search path used in calls to
|
||||||
## `cSearchPath() <cimport.html#cSearchPath,string>`_.
|
## `cSearchPath() <cimport.html#cSearchPath,string>`_.
|
||||||
##
|
runnableExamples:
|
||||||
## This allows something like this:
|
import paths, os
|
||||||
##
|
static:
|
||||||
## .. code-block:: nim
|
cAddSearchDir testsIncludeDir()
|
||||||
##
|
doAssert cSearchPath("test.h").existsFile
|
||||||
## cAddSearchDir("path/to/includes")
|
|
||||||
## cImport cSearchPath("file.h")
|
|
||||||
|
|
||||||
var dir = interpPath(dir)
|
var dir = interpPath(dir)
|
||||||
if dir notin gStateCT.searchDirs:
|
if dir notin gStateCT.searchDirs:
|
||||||
gStateCT.searchDirs.add(dir)
|
gStateCT.searchDirs.add(dir)
|
||||||
|
|
@ -322,46 +332,32 @@ macro cIncludeDir*(dir: static string): untyped =
|
||||||
var dir = interpPath(dir)
|
var dir = interpPath(dir)
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
|
|
||||||
let
|
let fullpath = findPath(dir)
|
||||||
fullpath = findPath(dir)
|
|
||||||
str = &"-I{fullpath.quoteShell}"
|
|
||||||
|
|
||||||
if fullpath notin gStateCT.includeDirs:
|
if fullpath notin gStateCT.includeDirs:
|
||||||
gStateCT.includeDirs.add(fullpath)
|
gStateCT.includeDirs.add(fullpath)
|
||||||
|
let str = &"-I{fullpath.quoteShell}"
|
||||||
result.add(quote do:
|
result.add quote do:
|
||||||
{.passC: `str`.}
|
{.passC: `str`.}
|
||||||
)
|
|
||||||
|
|
||||||
if gStateCT.debug:
|
if gStateCT.debug:
|
||||||
echo result.repr
|
echo result.repr
|
||||||
|
|
||||||
macro cAddStdDir*(mode = "c"): untyped =
|
proc cAddStdDir*(mode = "c") {.compileTime.} =
|
||||||
## Add the standard ``c`` [default] or ``cpp`` include paths to search
|
## Add the standard ``c`` [default] or ``cpp`` include paths to search
|
||||||
## path used in calls to `cSearchPath() <cimport.html#cSearchPath,string>`_
|
## path used in calls to `cSearchPath() <cimport.html#cSearchPath,string>`_
|
||||||
##
|
|
||||||
## This allows something like this:
|
|
||||||
##
|
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
cAddStdDir()
|
static: cAddStdDir()
|
||||||
echo cSearchPath("math.h")
|
import os
|
||||||
|
doAssert cSearchPath("math.h").existsFile
|
||||||
result = newNimNode(nnkStmtList)
|
|
||||||
|
|
||||||
var
|
var
|
||||||
inc = false
|
inc = false
|
||||||
|
for line in getGccPaths(mode).splitLines():
|
||||||
for line in getGccPaths(mode.strVal()).splitLines():
|
|
||||||
if "#include <...> search starts here" in line:
|
if "#include <...> search starts here" in line:
|
||||||
inc = true
|
inc = true
|
||||||
continue
|
continue
|
||||||
elif "End of search list" in line:
|
elif "End of search list" in line:
|
||||||
break
|
break
|
||||||
|
|
||||||
if inc:
|
if inc:
|
||||||
let sline = line.strip()
|
cAddSearchDir line.strip()
|
||||||
result.add quote do:
|
|
||||||
cAddSearchDir(`sline`)
|
|
||||||
|
|
||||||
macro cCompile*(path: static string, mode = "c"): untyped =
|
macro cCompile*(path: static string, mode = "c"): untyped =
|
||||||
## Compile and link C/C++ implementation into resulting binary using ``{.compile.}``
|
## Compile and link C/C++ implementation into resulting binary using ``{.compile.}``
|
||||||
|
|
@ -430,7 +426,7 @@ macro cCompile*(path: static string, mode = "c"): untyped =
|
||||||
macro cImport*(filename: static string, recurse: static bool = false): untyped =
|
macro cImport*(filename: static string, recurse: static bool = false): untyped =
|
||||||
## Import all supported definitions from specified header file. Generated
|
## Import all supported definitions from specified header file. Generated
|
||||||
## content is cached in ``nimcache`` until ``filename`` changes unless
|
## content is cached in ``nimcache`` until ``filename`` changes unless
|
||||||
## `cDisableCaching() <cimport.html#cDisableCaching.m,>`_ is set. ``nim -f``
|
## `cDisableCaching() <cimport.html#cDisableCaching,>`_ is set. ``nim -f``
|
||||||
## can also be used after Nim v0.19.4 to flush the cache.
|
## can also be used after Nim v0.19.4 to flush the cache.
|
||||||
##
|
##
|
||||||
## ``recurse`` can be used to generate Nim wrappers from ``#include`` files
|
## ``recurse`` can be used to generate Nim wrappers from ``#include`` files
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,7 @@ proc toastExePath*(): string =
|
||||||
|
|
||||||
proc incDir*(): string =
|
proc incDir*(): string =
|
||||||
nimteropBuildDir() / "inc"
|
nimteropBuildDir() / "inc"
|
||||||
|
|
||||||
|
proc testsIncludeDir*(): string =
|
||||||
|
nimteropRoot() / "tests" / "include"
|
||||||
|
|
||||||
|
|
|
||||||
7
tests/config.nims.disabled
Normal file
7
tests/config.nims.disabled
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#[
|
||||||
|
pending https://github.com/nim-lang/Nim/pull/10530
|
||||||
|
note: nimble init installs something like this (maybe without src in this case)
|
||||||
|
switch("path", "$projectDir/../src")
|
||||||
|
but it doesn't seem robust in case tests have subdirs, so, changing to ../ seems better
|
||||||
|
]#
|
||||||
|
switch("path", "..")
|
||||||
2
tests/nim.cfg
Normal file
2
tests/nim.cfg
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
# TODO: pending https://github.com/nimterop/nimterop/issues/110 remove in favor of config.nims
|
||||||
|
--path:".."
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import nimterop/cimport
|
|
||||||
import unittest
|
import unittest
|
||||||
|
import nimterop/cimport
|
||||||
|
|
||||||
type
|
type
|
||||||
locale_t = object
|
locale_t = object
|
||||||
mingw_ldbl_type_t = object
|
mingw_ldbl_type_t = object
|
||||||
mingw_dbl_type_t = object
|
mingw_dbl_type_t = object
|
||||||
|
|
||||||
|
static:
|
||||||
cDebug()
|
cDebug()
|
||||||
cDisableCaching()
|
cDisableCaching()
|
||||||
|
|
||||||
cAddStdDir()
|
cAddStdDir()
|
||||||
|
|
||||||
cPlugin:
|
cPlugin:
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import std/unittest
|
import std/unittest
|
||||||
import nimterop/cimport
|
import nimterop/cimport
|
||||||
|
import nimterop/paths
|
||||||
|
|
||||||
|
static:
|
||||||
cDebug()
|
cDebug()
|
||||||
cDisableCaching()
|
cDisableCaching()
|
||||||
|
cAddSearchDir testsIncludeDir()
|
||||||
|
|
||||||
cDefine("FORCE")
|
cDefine("FORCE")
|
||||||
cIncludeDir "$projpath/include"
|
cIncludeDir testsIncludeDir()
|
||||||
cAddSearchDir "$projpath/include"
|
|
||||||
cCompile cSearchPath("test.c")
|
cCompile cSearchPath("test.c")
|
||||||
|
|
||||||
cPlugin:
|
cPlugin:
|
||||||
|
|
@ -137,8 +139,6 @@ var
|
||||||
k: uKernel
|
k: uKernel
|
||||||
kp: Kernel
|
kp: Kernel
|
||||||
|
|
||||||
cAddStdDir()
|
|
||||||
|
|
||||||
## failing tests
|
## failing tests
|
||||||
when false:
|
when false:
|
||||||
static: # Error: undeclared identifier: 'foobar1'
|
static: # Error: undeclared identifier: 'foobar1'
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import nimterop/cimport
|
|
||||||
import unittest
|
import unittest
|
||||||
|
import nimterop/cimport
|
||||||
|
import nimterop/paths
|
||||||
|
|
||||||
|
static:
|
||||||
cDebug()
|
cDebug()
|
||||||
cDisableCaching()
|
cDisableCaching()
|
||||||
|
cAddSearchDir testsIncludeDir()
|
||||||
|
|
||||||
cIncludeDir "$projpath/include"
|
cIncludeDir testsIncludeDir()
|
||||||
cAddSearchDir "$projpath/include"
|
|
||||||
cCompile cSearchPath "test2.cpp"
|
cCompile cSearchPath "test2.cpp"
|
||||||
cImport cSearchPath "test2.hpp"
|
cImport cSearchPath "test2.hpp"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ const
|
||||||
|
|
||||||
static:
|
static:
|
||||||
gitPull("https://github.com/jarikomppa/soloud", baseDir, "include/*\nsrc/*\n")
|
gitPull("https://github.com/jarikomppa/soloud", baseDir, "include/*\nsrc/*\n")
|
||||||
|
|
||||||
cDebug()
|
cDebug()
|
||||||
cDisableCaching()
|
cDisableCaching()
|
||||||
|
|
||||||
|
|
@ -18,7 +17,7 @@ cOverride:
|
||||||
|
|
||||||
proc Soloud_destroy*(aSoloud: ptr Soloud) {.importc: "Soloud_destroy", header: cSearchPath(incl/"soloud_c.h").}
|
proc Soloud_destroy*(aSoloud: ptr Soloud) {.importc: "Soloud_destroy", header: cSearchPath(incl/"soloud_c.h").}
|
||||||
|
|
||||||
cSkipSymbol("WavStream_stop", "WavStream_setFilter")
|
static: cSkipSymbol @["WavStream_stop", "WavStream_setFilter"]
|
||||||
|
|
||||||
cIncludeDir(incl)
|
cIncludeDir(incl)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue