Add exclude to cCompile, fix duplicate filename compilation, mkDir fix, cp/mvFile, full relativePath

This commit is contained in:
Ganesh Viswanathan 2019-02-06 14:47:09 -06:00
commit 10aef55dad
3 changed files with 109 additions and 28 deletions

View file

@ -146,7 +146,7 @@ proc printNim*(fullpath: string, root: TSNode, astTable: AstTable) =
nimState.identifiers = newTable[string, string]() nimState.identifiers = newTable[string, string]()
nimState.currentHeader = getCurrentHeader(fullpath) nimState.currentHeader = getCurrentHeader(fullpath)
nimState.constStr &= &"\n {nimState.currentHeader} = \"{fp}\"" nimState.constStr &= &"\n {nimState.currentHeader} {{.used.}} = \"{fp}\""
root.searchAst(astTable, nimState) root.searchAst(astTable, nimState)

View file

@ -14,7 +14,7 @@ const CIMPORT {.used.} = 1
include "."/globals include "."/globals
import "." / [types, paths] import "."/[git, paths, types]
export types export types
proc interpPath(dir: string): string= proc interpPath(dir: string): string=
@ -359,7 +359,7 @@ proc cAddStdDir*(mode = "c") {.compileTime.} =
if inc: if inc:
cAddSearchDir line.strip() 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.}`` ## 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 wildcards:
@ -376,6 +376,13 @@ macro cCompile*(path: static string, mode = "c"): untyped =
## .. code-block:: nim ## .. code-block:: nim
## ##
## cCompile("path/to/dir", "cpp") ## 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) result = newNimNode(nnkStmtList)
@ -383,7 +390,8 @@ macro cCompile*(path: static string, mode = "c"): untyped =
stmt = "" stmt = ""
proc fcompile(file: string): string = proc fcompile(file: string): string =
let fn = file.splitFile().name let
(_, fn, ext) = file.splitFile()
var var
ufn = fn ufn = fn
uniq = 1 uniq = 1
@ -391,32 +399,53 @@ macro cCompile*(path: static string, mode = "c"): untyped =
ufn = fn & $uniq ufn = fn & $uniq
uniq += 1 uniq += 1
# - https://github.com/nim-lang/Nim/issues/10299
# - https://github.com/nim-lang/Nim/issues/10486
gStateCT.compile.add(ufn) gStateCT.compile.add(ufn)
if fn == ufn: if fn == ufn:
return "{.compile: \"$#\".}" % file.replace("\\", "/") return "{.compile: \"$#\".}\n" % file.replace("\\", "/")
else: else:
return "{.compile: (\"../$#\", \"$#.o\").}" % [file.replace("\\", "/"), ufn] # - 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("\\", "/")
proc dcompile(dir: string, ext=""): string = # 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 let
files = walkDirImpl(dir, ext) files = walkDirImpl(dir, ext)
for f in files: for f in files:
if f.len != 0: if f.len != 0 and f.notExcluded(exclude):
result &= fcompile(f) & "\n" result &= fcompile(f)
if path.contains("*") or path.contains("?"): if path.contains("*") or path.contains("?"):
stmt &= dcompile(path) stmt &= dcompile(path, exclude.strVal())
else: else:
let fpath = findPath(path) let fpath = findPath(path)
if fileExists(fpath): if fileExists(fpath) and fpath.notExcluded(exclude.strVal()):
stmt &= fcompile(fpath) & "\n" stmt &= fcompile(fpath)
elif dirExists(fpath): elif dirExists(fpath):
if mode.strVal().contains("cpp"): if mode.strVal().contains("cpp"):
for i in @["*.C", "*.cpp", "*.c++", "*.cc", "*.cxx"]: for i in @["*.cpp", "*.c++", "*.cc", "*.cxx"]:
stmt &= dcompile(fpath, i) stmt &= dcompile(fpath, exclude.strVal(), i)
when not defined(Windows):
stmt &= dcompile(fpath, exclude.strVal(), "*.C")
else: else:
stmt &= dcompile(fpath, "*.c") stmt &= dcompile(fpath, exclude.strVal(), "*.c")
result.add stmt.parseStmt() result.add stmt.parseStmt()

View file

@ -23,10 +23,71 @@ proc execAction*(cmd: string, nostderr=false): string =
doAssert false, msg doAssert false, msg
proc mkDir*(dir: string) = proc mkDir*(dir: string) =
if not dirExists(dir):
let let
flag = when not defined(Windows): "-p" else: "" flag = when not defined(Windows): "-p" else: ""
discard execAction(&"mkdir {flag} {dir.quoteShell}") discard execAction(&"mkdir {flag} {dir.quoteShell}")
proc cpFile*(source, dest: string, move=false) =
let
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) = proc extractZip*(zipfile, outdir: string) =
var cmd = "unzip -o $#" var cmd = "unzip -o $#"
if defined(Windows): if defined(Windows):
@ -62,18 +123,9 @@ proc gitReset*(outdir: string) =
sleep(1000) sleep(1000)
echo " Retrying ..." 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) = proc gitCheckout*(file, outdir: string) =
echo "Resetting " & file echo "Resetting " & file
let file2 = file.relativePathNaive outdir let file2 = file.relativePath outdir
let cmd = &"cd {outdir.quoteShell} && git checkout {file2.quoteShell}" let cmd = &"cd {outdir.quoteShell} && git checkout {file2.quoteShell}"
while execAction(cmd).contains("Permission denied"): while execAction(cmd).contains("Permission denied"):
sleep(500) sleep(500)