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.currentHeader = getCurrentHeader(fullpath)
nimState.constStr &= &"\n {nimState.currentHeader} = \"{fp}\""
nimState.constStr &= &"\n {nimState.currentHeader} {{.used.}} = \"{fp}\""
root.searchAst(astTable, nimState)

View file

@ -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]
# - 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
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()

View file

@ -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)