diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2020-04-22 22:11:30 -0500 |
|---|---|---|
| committer | Ganesh Viswanathan <dev@genotrance.com> | 2020-04-22 22:11:30 -0500 |
| commit | c1f46680f77d077bfc7abebea8b289e9b8bac043 (patch) | |
| tree | fa01b07d028f058b18cbfe38bd68ff1e11f0222b | |
| parent | f17b958f47686f41a20045ea089295841a6845d6 (diff) | |
| download | nimterop-c1f46680f77d077bfc7abebea8b289e9b8bac043.tar.gz nimterop-c1f46680f77d077bfc7abebea8b289e9b8bac043.zip | |
Add cImport for multiple headers
| -rw-r--r-- | nimterop.nimble | 3 | ||||
| -rw-r--r-- | nimterop/cimport.nim | 91 | ||||
| -rw-r--r-- | tests/rsa.nim | 42 |
3 files changed, 99 insertions, 37 deletions
diff --git a/nimterop.nimble b/nimterop.nimble index 37c395d..9cb79b1 100644 --- a/nimterop.nimble +++ b/nimterop.nimble @@ -51,6 +51,9 @@ task test, "Test": execTest "tests/tpcre.nim" execTest "tests/tpcre.nim", "-d:FLAGS=\"-f:ast2\"" + execTest "tests/rsa.nim" + execTest "tests/rsa.nim", "-d:FLAGS=\"-H\"" + # Platform specific tests when defined(Windows): execTest "tests/tmath.nim" diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim index 52d1892..3e58bc8 100644 --- a/nimterop/cimport.nim +++ b/nimterop/cimport.nim @@ -91,6 +91,11 @@ proc getCacheValue(fullpath: string): string = if not gStateCT.nocache: result = fullpath.getFileDate() +proc getCacheValue(fullpaths: seq[string]): string = + if not gStateCT.nocache: + for fullpath in fullpaths: + result &= getCacheValue(fullpath) + proc getToastError(output: string): string = # Filter out preprocessor errors for line in output.splitLines(): @@ -121,7 +126,7 @@ proc getNimCheckError(output: string): tuple[tmpFile, errors: string] = result.errors = "\n\n" & check -proc getToast(fullpath: string, recurse: bool = false, dynlib: string = "", +proc getToast(fullpaths: seq[string], recurse: bool = false, dynlib: string = "", mode = "c", flags = "", noNimout = false): string = var ret = 0 @@ -158,11 +163,12 @@ proc getToast(fullpath: string, recurse: bool = false, dynlib: string = "", if gStateCT.pluginSourcePath.nBl: cmd.add &" --pluginSourcePath={gStateCT.pluginSourcePath.sanitizePath}" - cmd.add &" {fullpath.sanitizePath}" + for fullpath in fullpaths: + cmd.add &" {fullpath.sanitizePath}" # see https://github.com/nimterop/nimterop/issues/69 (result, ret) = execAction(cmd, die = false, cache = (not gStateCT.nocache), - cacheKey = getCacheValue(fullpath)) + cacheKey = getCacheValue(fullpaths)) doAssert ret == 0, getToastError(result) macro cOverride*(body): untyped = @@ -555,6 +561,46 @@ macro cCompile*(path: static string, mode = "c", exclude = ""): untyped = if gStateCT.debug: echo result.repr +macro cImport*(filenames: static seq[string], recurse: static bool = false, dynlib: static string = "", + mode: static string = "c", flags: static string = ""): untyped = + ## Import multiple headers in one shot + ## + ## This macro is preferable over multiple individual `cImport()` calls, especially + ## when the headers might `#include` the same headers and result in duplicate symbols. + result = newNimNode(nnkStmtList) + + var + fullpaths: seq[string] + + for filename in filenames: + fullpaths.add findPath(filename) + + # In case cOverride called after cPlugin + if gStateCT.pluginSourcePath.Bl: + cPluginHelper(gStateCT.pluginSource) + + echo "# Importing " & fullpaths.join(", ").sanitizePath + + let + output = getToast(fullpaths, recurse, dynlib, mode, flags) + + # Reset plugin and overrides for next cImport + if gStateCT.overrides.nBl: + gStateCT.pluginSourcePath = "" + gStateCT.overrides = "" + + if gStateCT.debug: + echo output + + try: + let body = parseStmt(output) + + result.add body + except: + let + (tmpFile, errors) = getNimCheckError(output) + doAssert false, errors & "\n\nNimterop codegen limitation or error - review 'nim check' output above generated for " & tmpFile + macro cImport*(filename: static string, recurse: static bool = false, dynlib: static string = "", mode: static string = "c", flags: static string = ""): untyped = ## Import all supported definitions from specified header file. Generated @@ -590,8 +636,8 @@ macro cImport*(filename: static string, recurse: static bool = false, dynlib: st ## with `cCompile() <cimport.html#cCompile.m%2C%2Cstring%2Cstring>`_, or the ## `{.passL.}` pragma can be used to specify the static lib to link. ## - ## `mode` is purely for forward compatibility when toast adds C++ support. It can - ## be ignored for the foreseeable future. + ## `mode` selects the preprocessor and tree-sitter parser to be used to process + ## the header. ## ## `flags` can be used to pass any other command line arguments to `toast`. A ## good example would be `--prefix` and `--suffix` which strip leading and @@ -600,37 +646,8 @@ macro cImport*(filename: static string, recurse: static bool = false, dynlib: st ## `cImport()` consumes and resets preceding `cOverride()` calls. `cPlugin()` ## is retained for the next `cImport()` call unless a new `cPlugin()` call is ## defined. - - result = newNimNode(nnkStmtList) - - let - fullpath = findPath(filename) - - # In case cOverride called after cPlugin - if gStateCT.pluginSourcePath.Bl: - cPluginHelper(gStateCT.pluginSource) - - echo "# Importing " & fullpath.sanitizePath - - let - output = getToast(fullpath, recurse, dynlib, mode, flags) - - # Reset plugin and overrides for next cImport - if gStateCT.overrides.nBl: - gStateCT.pluginSourcePath = "" - gStateCT.overrides = "" - - if gStateCT.debug: - echo output - - try: - let body = parseStmt(output) - - result.add body - except: - let - (tmpFile, errors) = getNimCheckError(output) - doAssert false, errors & "\n\nNimterop codegen limitation or error - review 'nim check' output above generated for " & tmpFile + return quote do: + cImport(@[`filename`], bool(`recurse`), `dynlib`, `mode`, `flags`) macro c2nImport*(filename: static string, recurse: static bool = false, dynlib: static string = "", mode: static string = "c", flags: static string = ""): untyped = @@ -661,7 +678,7 @@ macro c2nImport*(filename: static string, recurse: static bool = false, dynlib: echo "# Importing " & fullpath & " with c2nim" let - output = getToast(fullpath, recurse, dynlib, noNimout = true) + output = getToast(@[fullpath], recurse, dynlib, noNimout = true) hash = output.hash().abs() hpath = getProjectCacheDir("c2nimCache", forceClean = false) / "nimterop_" & $hash & ".h" npath = hpath[0 .. hpath.rfind('.')] & "nim" diff --git a/tests/rsa.nim b/tests/rsa.nim new file mode 100644 index 0000000..638c490 --- /dev/null +++ b/tests/rsa.nim @@ -0,0 +1,42 @@ +import os +import strutils + +import nimterop/[build, cimport] + +setDefines(@["cryptoStd"]) +getHeader("openssl/crypto.h") + +const + basePath = cryptoPath.parentDir + FLAGS {.strdefine.} = "" + +cPlugin: + import strutils + + proc onSymbol*(sym: var Symbol) {.exportc, dynlib.} = + sym.name = sym.name.strip(chars = {'_'}).replace("__", "_") + + if sym.name in [ + "AES_ENCRYPT", "AES_DECRYPT", + "BIO_CTRL_PENDING", "BIO_CTRL_WPENDING", + "BN_F_BNRAND", "BN_F_BNRAND_RANGE", + "CRYPTO_THREADID", + "EVP_CIPHER", + "OPENSSL_VERSION", + "PKCS7_ENCRYPT", "PKCS7_STREAM", + "SSL_TXT_ADH", "SSL_TXT_AECDH", "SSL_TXT_kECDHE" + ]: + sym.name = "C_" & sym.name + +cOverride: + proc OPENSSL_die*(assertion: cstring; file: cstring; line: cint) {.importc.} + +cImport(@[ + basePath / "rsa.h", + basePath / "err.h", +], recurse = true, flags = "-f:ast2 -s " & FLAGS) + +{.passL: cryptoLPath.} + +OpensslInit() +echo $OPENSSL_VERSION_TEXT
\ No newline at end of file |
