Copy files during prepare, NEP1 conformance

This commit is contained in:
Ganesh Viswanathan 2018-06-11 09:42:41 -05:00
commit 4b91f1bbbe
3 changed files with 93 additions and 73 deletions

View file

@ -101,6 +101,8 @@ The following keys can be used to prepare dependencies such as downloading ZIP f
```execute``` = command to run during preparation ```execute``` = command to run during preparation
```copy``` = copy a file to another location. Preferred over moving to preserve original. Comma separate for multiple entries. E.g. copy = "output/config.h.in=output/config.h"
_[n.wildcard]_ _[n.wildcard]_
File wildcards such as *.nim, ssl*.h, etc. can be used to perform tasks across a group of files. This is useful to define common operations such as global text replacements without having to specify an explicit section for every single file. These operations will be performed on every matching file that is defined as a _sourcefile_ or recursed files. Only applies on source files following the wildcard declarations. File wildcards such as *.nim, ssl*.h, etc. can be used to perform tasks across a group of files. This is useful to define common operations such as global text replacements without having to specify an explicit section for every single file. These operations will be performed on every matching file that is defined as a _sourcefile_ or recursed files. Only applies on source files following the wildcard declarations.

View file

@ -1,17 +1,17 @@
import nre, os, ospaths, osproc, parsecfg, pegs, ropes, sequtils, streams, strutils, tables import nre, os, ospaths, osproc, parsecfg, pegs, ropes, sequtils, streams, strutils, tables
var var
DONE: seq[string] = @[] gDoneRecursive: seq[string] = @[]
DONE_INLINE: seq[string] = @[] gDoneInline: seq[string] = @[]
CONFIG: Config gConfig: Config
FILTER = "" gFilter = ""
QUOTES = true gQuotes = true
OUTPUT = "" gOutput = ""
INCLUDES: seq[string] = @[] gIncludes: seq[string] = @[]
EXCLUDES: seq[string] = @[] gExcludes: seq[string] = @[]
RENAMES = initTable[string, string]() gRenames = initTable[string, string]()
WILDCARDS = newConfig() gWildcards = newConfig()
const DOC = """ const DOC = """
Nimgen is a helper for c2nim to simpilfy and automate the wrapping of C libraries Nimgen is a helper for c2nim to simpilfy and automate the wrapping of C libraries
@ -52,7 +52,7 @@ proc extractZip(zipfile: string) =
if defined(Windows): if defined(Windows):
cmd = "powershell -nologo -noprofile -command \"& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('$#', '.'); }\"" cmd = "powershell -nologo -noprofile -command \"& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('$#', '.'); }\""
setCurrentDir(OUTPUT) setCurrentDir(gOutput)
defer: setCurrentDir("..") defer: setCurrentDir("..")
echo "Extracting " & zipfile echo "Extracting " & zipfile
@ -67,9 +67,9 @@ proc downloadUrl(url: string) =
if defined(Windows): if defined(Windows):
cmd = "powershell wget $# -OutFile $#" cmd = "powershell wget $# -OutFile $#"
if not (ext == ".zip" and fileExists(OUTPUT/file)): if not (ext == ".zip" and fileExists(gOutput/file)):
echo "Downloading " & file echo "Downloading " & file
discard execProc(cmd % [url, OUTPUT/file]) discard execProc(cmd % [url, gOutput/file])
if ext == ".zip": if ext == ".zip":
extractZip(file) extractZip(file)
@ -77,18 +77,18 @@ proc downloadUrl(url: string) =
proc gitReset() = proc gitReset() =
echo "Resetting Git repo" echo "Resetting Git repo"
setCurrentDir(OUTPUT) setCurrentDir(gOutput)
defer: setCurrentDir("..") defer: setCurrentDir("..")
discard execProc("git reset --hard HEAD") discard execProc("git reset --hard HEAD")
proc gitRemotePull(url: string, pull=true) = proc gitRemotePull(url: string, pull=true) =
if dirExists(OUTPUT/".git"): if dirExists(gOutput/".git"):
if pull: if pull:
gitReset() gitReset()
return return
setCurrentDir(OUTPUT) setCurrentDir(gOutput)
defer: setCurrentDir("..") defer: setCurrentDir("..")
echo "Setting up Git repo" echo "Setting up Git repo"
@ -101,11 +101,11 @@ proc gitRemotePull(url: string, pull=true) =
proc gitSparseCheckout(plist: string) = proc gitSparseCheckout(plist: string) =
let sparsefile = ".git/info/sparse-checkout" let sparsefile = ".git/info/sparse-checkout"
if fileExists(OUTPUT/sparsefile): if fileExists(gOutput/sparsefile):
gitReset() gitReset()
return return
setCurrentDir(OUTPUT) setCurrentDir(gOutput)
defer: setCurrentDir("..") defer: setCurrentDir("..")
discard execProc("git config core.sparsecheckout true") discard execProc("git config core.sparsecheckout true")
@ -114,6 +114,20 @@ proc gitSparseCheckout(plist: string) =
echo "Checking out artifacts" echo "Checking out artifacts"
discard execProc("git pull --depth=1 origin master") discard execProc("git pull --depth=1 origin master")
proc doCopy(flist: string) =
for pair in flist.split(","):
let spl = pair.split("=")
if spl.len() != 2:
echo "Bad copy syntax: " & flist
quit(1)
let
lfile = spl[0].strip()
rfile = spl[1].strip()
copyFile(lfile, rfile)
echo "Copied $# to $#" % [lfile, rfile]
proc getKey(ukey: string): tuple[key: string, val: bool] = proc getKey(ukey: string): tuple[key: string, val: bool] =
var kv = ukey.replace(re"\..*", "").split("-", 1) var kv = ukey.replace(re"\..*", "").split("-", 1)
if kv.len() == 1: if kv.len() == 1:
@ -132,20 +146,20 @@ proc getKey(ukey: string): tuple[key: string, val: bool] =
proc getNimout(file: string, rename=true): string = proc getNimout(file: string, rename=true): string =
result = file.splitFile().name.replace(re"[\-\.]", "_") & ".nim" result = file.splitFile().name.replace(re"[\-\.]", "_") & ".nim"
if OUTPUT != "": if gOutput != "":
result = OUTPUT/result result = gOutput/result
if not rename: if not rename:
return return
if RENAMES.hasKey(file): if gRenames.hasKey(file):
result = RENAMES[file] result = gRenames[file]
if not dirExists(parentDir(result)): if not dirExists(parentDir(result)):
createDir(parentDir(result)) createDir(parentDir(result))
proc exclude(file: string): bool = proc exclude(file: string): bool =
for excl in EXCLUDES: for excl in gExcludes:
if excl in file: if excl in file:
return true return true
return false return false
@ -159,7 +173,7 @@ proc search(file: string): string =
result = getNimout(file) result = getNimout(file)
elif not fileExists(result) and not dirExists(result): elif not fileExists(result) and not dirExists(result):
var found = false var found = false
for inc in INCLUDES: for inc in gIncludes:
result = inc/file result = inc/file
if fileExists(result) or dirExists(result): if fileExists(result) or dirExists(result):
found = true found = true
@ -265,7 +279,6 @@ proc rename(file: string, renfile: string) =
nimout = getNimout(file, false) nimout = getNimout(file, false)
newname = renfile.replace("$nimout", extractFilename(nimout)) newname = renfile.replace("$nimout", extractFilename(nimout))
#if newname =~ peg"(!\$.)*{'$replace'\s*'('\s*{(!\,\S)+}\s*','\s*{(!\)\S)+}\s*')'}":
if newname =~ peg"(!\$.)*{'$replace'\s*'('\s*{(!\)\S)+}')'}": if newname =~ peg"(!\$.)*{'$replace'\s*'('\s*{(!\)\S)+}')'}":
var final = nimout.extractFilename() var final = nimout.extractFilename()
for entry in matches[1].split(","): for entry in matches[1].split(","):
@ -274,14 +287,14 @@ proc rename(file: string, renfile: string) =
echo "Bad replace syntax: " & renfile echo "Bad replace syntax: " & renfile
quit(1) quit(1)
var let
srch = spl[0].strip() srch = spl[0].strip()
repl = spl[1].strip() repl = spl[1].strip()
final = final.replace(srch, repl) final = final.replace(srch, repl)
newname = newname.replace(matches[0], final) newname = newname.replace(matches[0], final)
RENAMES[file] = OUTPUT/newname gRenames[file] = gOutput/newname
proc compile(dir="", file=""): string = proc compile(dir="", file=""): string =
proc fcompile(file: string): string = proc fcompile(file: string): string =
@ -309,19 +322,19 @@ proc fixFuncProtos(file: string) =
proc getIncls(file: string, inline=false): seq[string] = proc getIncls(file: string, inline=false): seq[string] =
result = @[] result = @[]
if inline and file in DONE_INLINE: if inline and file in gDoneInline:
return return
withFile(file): withFile(file):
for f in content.findIter(re"(?m)^\s*#\s*include\s+(.*?)$"): for f in content.findIter(re"(?m)^\s*#\s*include\s+(.*?)$"):
var inc = f.captures[0].strip() var inc = f.captures[0].strip()
if ((QUOTES and inc.contains("\"")) or (FILTER != "" and FILTER in inc)) and (not exclude(inc)): if ((gQuotes and inc.contains("\"")) or (gFilter != "" and gFilter in inc)) and (not exclude(inc)):
result.add( result.add(
inc.replace(re"""[<>"]""", "").replace(re"\/[\*\/].*$", "").strip()) inc.replace(re"""[<>"]""", "").replace(re"\/[\*\/].*$", "").strip())
result = result.deduplicate() result = result.deduplicate()
DONE_INLINE.add(file) gDoneInline.add(file)
if inline: if inline:
var sres = newSeq[string]() var sres = newSeq[string]()
@ -353,7 +366,7 @@ proc runPreprocess(file, ppflags, flags: string, inline: bool): string =
pproc = if flags.contains("cpp"): "g++" else: "gcc" pproc = if flags.contains("cpp"): "g++" else: "gcc"
cmd = "$# -E $# $#" % [pproc, ppflags, file] cmd = "$# -E $# $#" % [pproc, ppflags, file]
for inc in INCLUDES: for inc in gIncludes:
cmd &= " -I " & inc cmd &= " -I " & inc
# Run preprocessor # Run preprocessor
@ -414,11 +427,11 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
if file == "": if file == "":
return return
if file in DONE: if file in gDoneRecursive:
return return
echo "Processing $# => $#" % [file, outfile] echo "Processing $# => $#" % [file, outfile]
DONE.add(file) gDoneRecursive.add(file)
fixFuncProtos(file) fixFuncProtos(file)
@ -455,10 +468,11 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
passC = "" passC = ""
outlib = "" outlib = ""
outpragma = "" outpragma = ""
outcompile = ""
passC = "import strutils\n" passC = "import strutils\n"
for inc in INCLUDES: for inc in gIncludes:
passC &= ("""{.passC: "-I\"" & gorge("nimble path $#").strip() & "/$#\"".}""" % [OUTPUT, inc]) & "\n" passC &= ("""{.passC: "-I\"" & gorge("nimble path $#").strip() & "/$#\"".}""" % [gOutput, inc]) & "\n"
for prag in pragma: for prag in pragma:
outpragma &= "{." & prag & ".}\n" outpragma &= "{." & prag & ".}\n"
@ -517,6 +531,8 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
freplace(outfile, " {.cdecl.})", ")") freplace(outfile, " {.cdecl.})", ")")
# Include {.compile.} directives # Include {.compile.} directives
outcompile = compile(compile)
for cpl in compile: for cpl in compile:
let fcpl = search(cpl) let fcpl = search(cpl)
if getFileInfo(fcpl).kind == pcFile: if getFileInfo(fcpl).kind == pcFile:
@ -544,12 +560,12 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
cfg = cfgin cfg = cfgin
sfile = search(file) sfile = search(file)
for pattern in WILDCARDS.keys(): for pattern in gWildcards.keys():
let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?") let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?")
if file.find(re(pat)).isSome(): if file.find(re(pat)).isSome():
echo "Appending " & file & " " & pattern echo "Appending " & file & " " & pattern
for key in WILDCARDS[pattern].keys(): for key in gWildcards[pattern].keys():
cfg[key & "." & pattern] = WILDCARDS[pattern][key] cfg[key & "." & pattern] = gWildcards[pattern][key]
var var
srch = "" srch = ""
@ -634,73 +650,75 @@ proc runCfg(cfg: string) =
echo "Config doesn't exist: " & cfg echo "Config doesn't exist: " & cfg
quit(1) quit(1)
CONFIG = loadConfig(cfg) gConfig = loadConfig(cfg)
if CONFIG.hasKey("n.global"): if gConfig.hasKey("n.global"):
if CONFIG["n.global"].hasKey("output"): if gConfig["n.global"].hasKey("output"):
OUTPUT = CONFIG["n.global"]["output"] gOutput = gConfig["n.global"]["output"]
if dirExists(OUTPUT): if dirExists(gOutput):
if "-f" in commandLineParams(): if "-f" in commandLineParams():
try: try:
removeDir(OUTPUT) removeDir(gOutput)
except OSError: except OSError:
echo "Directory in use: " & OUTPUT echo "Directory in use: " & gOutput
quit(1) quit(1)
else: else:
for f in walkFiles(OUTPUT/"*.nim"): for f in walkFiles(gOutput/"*.nim"):
try: try:
removeFile(f) removeFile(f)
except OSError: except OSError:
echo "Unable to delete: " & f echo "Unable to delete: " & f
quit(1) quit(1)
createDir(OUTPUT) createDir(gOutput)
if CONFIG["n.global"].hasKey("filter"): if gConfig["n.global"].hasKey("filter"):
FILTER = CONFIG["n.global"]["filter"] gFilter = gConfig["n.global"]["filter"]
if CONFIG["n.global"].hasKey("quotes"): if gConfig["n.global"].hasKey("quotes"):
if CONFIG["n.global"]["quotes"] == "false": if gConfig["n.global"]["quotes"] == "false":
QUOTES = false gQuotes = false
if CONFIG.hasKey("n.include"): if gConfig.hasKey("n.include"):
for inc in CONFIG["n.include"].keys(): for inc in gConfig["n.include"].keys():
INCLUDES.add(inc) gIncludes.add(inc)
if CONFIG.hasKey("n.exclude"): if gConfig.hasKey("n.exclude"):
for excl in CONFIG["n.exclude"].keys(): for excl in gConfig["n.exclude"].keys():
EXCLUDES.add(excl) gExcludes.add(excl)
if CONFIG.hasKey("n.prepare"): if gConfig.hasKey("n.prepare"):
for prep in CONFIG["n.prepare"].keys(): for prep in gConfig["n.prepare"].keys():
let (key, val) = getKey(prep) let (key, val) = getKey(prep)
if val == true: if val == true:
if key == "download": if key == "download":
downloadUrl(CONFIG["n.prepare"][prep]) downloadUrl(gConfig["n.prepare"][prep])
elif key == "extract": elif key == "extract":
extractZip(CONFIG["n.prepare"][prep]) extractZip(gConfig["n.prepare"][prep])
elif key == "git": elif key == "git":
gitRemotePull(CONFIG["n.prepare"][prep]) gitRemotePull(gConfig["n.prepare"][prep])
elif key == "gitremote": elif key == "gitremote":
gitRemotePull(CONFIG["n.prepare"][prep], false) gitRemotePull(gConfig["n.prepare"][prep], false)
elif key == "gitsparse": elif key == "gitsparse":
gitSparseCheckout(CONFIG["n.prepare"][prep]) gitSparseCheckout(gConfig["n.prepare"][prep])
elif key == "execute": elif key == "execute":
discard execProc(CONFIG["n.prepare"][prep]) discard execProc(gConfig["n.prepare"][prep])
elif key == "copy":
doCopy(gConfig["n.prepare"][prep])
if CONFIG.hasKey("n.wildcard"): if gConfig.hasKey("n.wildcard"):
var wildcard = "" var wildcard = ""
for wild in CONFIG["n.wildcard"].keys(): for wild in gConfig["n.wildcard"].keys():
let (key, val) = getKey(wild) let (key, val) = getKey(wild)
if val == true: if val == true:
if key == "wildcard": if key == "wildcard":
wildcard = CONFIG["n.wildcard"][wild] wildcard = gConfig["n.wildcard"][wild]
else: else:
WILDCARDS.setSectionKey(wildcard, wild, CONFIG["n.wildcard"][wild]) gWildcards.setSectionKey(wildcard, wild, gConfig["n.wildcard"][wild])
for file in CONFIG.keys(): for file in gConfig.keys():
if file in @["n.global", "n.include", "n.exclude", "n.prepare", "n.wildcard"]: if file in @["n.global", "n.include", "n.exclude", "n.prepare", "n.wildcard"]:
continue continue
runFile(file, CONFIG[file]) runFile(file, gConfig[file])
# ### # ###
# Main loop # Main loop

View file

@ -1,6 +1,6 @@
# Package # Package
version = "0.2.0" version = "0.2.1"
author = "genotrance" author = "genotrance"
description = "c2nim helper to simplify and automate the wrapping of C libraries" description = "c2nim helper to simplify and automate the wrapping of C libraries"
license = "MIT" license = "MIT"