aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2019-02-06 14:47:09 -0600
committerGanesh Viswanathan <dev@genotrance.com>2019-02-06 14:47:09 -0600
commit10aef55dadfbb9a4a1b4cab5ce64242cc1a63d66 (patch)
tree1da683f201c3d002096ef979dde03161ad986ed9
parent61eb0457441a8cc7d45a6cad53ebac8a7cc0d4f9 (diff)
downloadnimterop-10aef55dadfbb9a4a1b4cab5ce64242cc1a63d66.tar.gz
nimterop-10aef55dadfbb9a4a1b4cab5ce64242cc1a63d66.zip
Add exclude to cCompile, fix duplicate filename compilation, mkDir fix, cp/mvFile, full relativePath
-rw-r--r--nimterop/ast.nim2
-rw-r--r--nimterop/cimport.nim61
-rw-r--r--nimterop/git.nim76
3 files changed, 110 insertions, 29 deletions
diff --git a/nimterop/ast.nim b/nimterop/ast.nim
index 1cc2c6c..94465a7 100644
--- a/nimterop/ast.nim
+++ b/nimterop/ast.nim
@@ -146,7 +146,7 @@ proc printNim*(fullpath: string, root: TSNode, astTable: AstTable) =
nimState.identifiers = newTable[string, string]()
nimState.currentHeader = getCurrentHeader(fullpath)
- nimState.constStr &= &"\n {nimState.currentHeader} = \"{fp}\""
+ nimState.constStr &= &"\n {nimState.currentHeader} {{.used.}} = \"{fp}\""
root.searchAst(astTable, nimState)
diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim
index 714cc93..443eca3 100644
--- a/nimterop/cimport.nim
+++ b/nimterop/cimport.nim
@@ -12,9 +12,9 @@ import hashes, macros, os, strformat, strutils
const CIMPORT {.used.} = 1
-include "." / globals
+include "."/globals
-import "." / [types, paths]
+import "."/[git, paths, types]
export types
proc interpPath(dir: string): string=
@@ -359,7 +359,7 @@ proc cAddStdDir*(mode = "c") {.compileTime.} =
if inc:
cAddSearchDir line.strip()
-macro cCompile*(path: static string, mode = "c"): untyped =
+macro cCompile*(path: static string, mode = "c", exclude = ""): untyped =
## Compile and link C/C++ implementation into resulting binary using ``{.compile.}``
##
## ``path`` can be a specific file or contain wildcards:
@@ -376,6 +376,13 @@ macro cCompile*(path: static string, mode = "c"): untyped =
## .. code-block:: nim
##
## cCompile("path/to/dir", "cpp")
+ ##
+ ## ``exclude`` can be used to exclude files by partial string match. Comma separated to
+ ## specify multiple exclude strings
+ ##
+ ## .. code-block:: nim
+ ##
+ ## cCompile("path/to/dir", exclude="test2.c")
result = newNimNode(nnkStmtList)
@@ -383,7 +390,8 @@ macro cCompile*(path: static string, mode = "c"): untyped =
stmt = ""
proc fcompile(file: string): string =
- let fn = file.splitFile().name
+ let
+ (_, fn, ext) = file.splitFile()
var
ufn = fn
uniq = 1
@@ -391,32 +399,53 @@ macro cCompile*(path: static string, mode = "c"): untyped =
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)
if fn == ufn:
- return "{.compile: \"$#\".}" % file.replace("\\", "/")
+ return "{.compile: \"$#\".}\n" % file.replace("\\", "/")
else:
- return "{.compile: (\"../$#\", \"$#.o\").}" % [file.replace("\\", "/"), ufn]
-
- proc dcompile(dir: string, ext=""): string =
+ # - https://github.com/nim-lang/Nim/issues/9370
+ let
+ hash = file.hash().abs()
+ tmpFile = file.parentDir() / &"_nimterop_{$hash}_{ufn}{ext}"
+ if not tmpFile.fileExists() or file.getFileDate() > tmpFile.getFileDate():
+ cpFile(file, tmpFile)
+ return "{.compile: \"$#\".}\n" % tmpFile.replace("\\", "/")
+
+ # Due to https://github.com/nim-lang/Nim/issues/9863
+ # cannot use seq[string] for excludes
+ proc notExcluded(file, exclude: string): bool =
+ result = true
+ if "_nimterop_" in file:
+ result = false
+ elif exclude.len != 0:
+ for excl in exclude.split(","):
+ if excl in file:
+ result = false
+
+ proc dcompile(dir, exclude: string, ext=""): string =
let
files = walkDirImpl(dir, ext)
for f in files:
- if f.len != 0:
- result &= fcompile(f) & "\n"
+ if f.len != 0 and f.notExcluded(exclude):
+ result &= fcompile(f)
if path.contains("*") or path.contains("?"):
- stmt &= dcompile(path)
+ stmt &= dcompile(path, exclude.strVal())
else:
let fpath = findPath(path)
- if fileExists(fpath):
- stmt &= fcompile(fpath) & "\n"
+ if fileExists(fpath) and fpath.notExcluded(exclude.strVal()):
+ stmt &= fcompile(fpath)
elif dirExists(fpath):
if mode.strVal().contains("cpp"):
- for i in @["*.C", "*.cpp", "*.c++", "*.cc", "*.cxx"]:
- stmt &= dcompile(fpath, i)
+ for i in @["*.cpp", "*.c++", "*.cc", "*.cxx"]:
+ stmt &= dcompile(fpath, exclude.strVal(), i)
+ when not defined(Windows):
+ stmt &= dcompile(fpath, exclude.strVal(), "*.C")
else:
- stmt &= dcompile(fpath, "*.c")
+ stmt &= dcompile(fpath, exclude.strVal(), "*.c")
result.add stmt.parseStmt()
diff --git a/nimterop/git.nim b/nimterop/git.nim
index f7de472..5b657b9 100644
--- a/nimterop/git.nim
+++ b/nimterop/git.nim
@@ -23,9 +23,70 @@ proc execAction*(cmd: string, nostderr=false): string =
doAssert false, msg
proc mkDir*(dir: string) =
+ if not dirExists(dir):
+ let
+ flag = when not defined(Windows): "-p" else: ""
+ discard execAction(&"mkdir {flag} {dir.quoteShell}")
+
+proc cpFile*(source, dest: string, move=false) =
let
- flag = when not defined(Windows): "-p" else: ""
- discard execAction(&"mkdir {flag} {dir.quoteShell}")
+ source = source.replace("/", $DirSep)
+ dest = dest.replace("/", $DirSep)
+ cmd =
+ when defined(Windows):
+ if move:
+ "move /y"
+ else:
+ "copy /y"
+ else:
+ if move:
+ "mv -f"
+ else:
+ "cp -f"
+
+ discard execAction(&"{cmd} {source.quoteShell} {dest.quoteShell}")
+
+proc mvFile*(source, dest: string) =
+ cpFile(source, dest, move=true)
+
+when (NimMajor, NimMinor, NimPatch) < (0, 19, 9):
+ proc relativePath*(path, base: string; sep = DirSep): string =
+ ## Copied from `os.relativePath` ; remove after nim >= 0.19.9
+ if path.len == 0: return ""
+ var f, b: PathIter
+ var ff = (0, -1)
+ var bb = (0, -1) # (int, int)
+ result = newStringOfCap(path.len)
+ while f.hasNext(path) and b.hasNext(base):
+ ff = next(f, path)
+ bb = next(b, base)
+ let diff = ff[1] - ff[0]
+ if diff != bb[1] - bb[0]: break
+ var same = true
+ for i in 0..diff:
+ if path[i + ff[0]] !=? base[i + bb[0]]:
+ same = false
+ break
+ if not same: break
+ ff = (0, -1)
+ bb = (0, -1)
+
+ while true:
+ if bb[1] >= bb[0]:
+ if result.len > 0 and result[^1] != sep:
+ result.add sep
+ result.add ".."
+ if not b.hasNext(base): break
+ bb = b.next(base)
+
+ while true:
+ if ff[1] >= ff[0]:
+ if result.len > 0 and result[^1] != sep:
+ result.add sep
+ for i in 0..ff[1] - ff[0]:
+ result.add path[i + ff[0]]
+ if not f.hasNext(path): break
+ ff = f.next(path)
proc extractZip*(zipfile, outdir: string) =
var cmd = "unzip -o $#"
@@ -62,18 +123,9 @@ proc gitReset*(outdir: string) =
sleep(1000)
echo " Retrying ..."
-proc relativePathNaive*(file, base: string): string =
- ## naive version of `os.relativePath` ; remove after nim >= 0.19.9
- runnableExamples:
- doAssert "/foo/bar/baz/log.txt".relativePathNaive("/foo/bar") == "baz/log.txt"
- var base = base
- if not base.endsWith "/": base.add "/"
- doAssert file.startsWith base
- result = file[base.len .. ^1]
-
proc gitCheckout*(file, outdir: string) =
echo "Resetting " & file
- let file2 = file.relativePathNaive outdir
+ let file2 = file.relativePath outdir
let cmd = &"cd {outdir.quoteShell} && git checkout {file2.quoteShell}"
while execAction(cmd).contains("Permission denied"):
sleep(500)