Added inlining in place of recursion, extract existing ZIP file without downloading, delete/create output directory error handling
This commit is contained in:
parent
9b25a6d1db
commit
968e89f08e
3 changed files with 67 additions and 19 deletions
|
|
@ -74,6 +74,8 @@ The following keys can be used to prepare dependencies such as downloading ZIP f
|
|||
|
||||
```download``` = url to download to the output directory. ZIP files are automatically extracted. Files are not redownloaded if already present but re-extracted
|
||||
|
||||
```extract``` = ZIP file to extract in case they are local and don't need to be downloaded. Path is relative to output directory.
|
||||
|
||||
```git``` = url of Git repository to clone. Full repo is pulled so gitremote + gitsparse is preferable. Resets to HEAD if already present
|
||||
|
||||
```gitremote``` = url of Git repository to partially checkout. Use with gitsparse to pull only files and dirs of interest
|
||||
|
|
@ -94,6 +96,8 @@ The following keys apply to library source code and help with generating the .ni
|
|||
|
||||
```recurse``` = find #include files and process them [default: false]
|
||||
|
||||
```inline``` = include #include files into file being processed, alternative method to processing each header file separately with recurse. Multiple source files will get combined into the same .nim output files [default: false]
|
||||
|
||||
```preprocess``` = run preprocessor (gcc -E) on file to remove #defines, etc. [default: false] - this is especially useful when c2nim doesn't support complex preprocessor usage
|
||||
|
||||
```ctags``` = run ctags on file to filter out function definitions [default: false] - this requires the ctags executable and is an alternative to filter out preprocessor complexity
|
||||
|
|
|
|||
80
nimgen.nim
80
nimgen.nim
|
|
@ -11,6 +11,7 @@ import strutils
|
|||
import tables
|
||||
|
||||
var DONE: seq[string] = @[]
|
||||
var DONE_INLINE: seq[string] = @[]
|
||||
|
||||
var CONFIG: Config
|
||||
var FILTER = ""
|
||||
|
|
@ -75,7 +76,6 @@ proc downloadUrl(url: string) =
|
|||
|
||||
if not (ext == ".zip" and fileExists(OUTPUT/file)):
|
||||
echo "Downloading " & file
|
||||
createDir(OUTPUT)
|
||||
discard execProc(cmd % [url, OUTPUT/file])
|
||||
|
||||
if ext == ".zip":
|
||||
|
|
@ -95,7 +95,6 @@ proc gitRemotePull(url: string, pull=true) =
|
|||
gitReset()
|
||||
return
|
||||
|
||||
createDir(OUTPUT)
|
||||
setCurrentDir(OUTPUT)
|
||||
defer: setCurrentDir("..")
|
||||
|
||||
|
|
@ -257,8 +256,11 @@ proc fixFuncProtos(file: string) =
|
|||
# ###
|
||||
# Convert to Nim
|
||||
|
||||
proc getIncls(file: string): seq[string] =
|
||||
proc getIncls(file: string, inline=false): seq[string] =
|
||||
result = @[]
|
||||
if inline and file in DONE_INLINE:
|
||||
return
|
||||
|
||||
withFile(file):
|
||||
for f in content.findIter(re"(?m)^\s*#\s*include\s+(.*?)$"):
|
||||
var inc = f.captures[0].strip()
|
||||
|
|
@ -266,14 +268,35 @@ proc getIncls(file: string): seq[string] =
|
|||
result.add(inc.replace(re"""[<>"]""", "").strip())
|
||||
|
||||
result = result.deduplicate()
|
||||
|
||||
DONE_INLINE.add(file)
|
||||
|
||||
if inline:
|
||||
var sres = newSeq[string]()
|
||||
for incl in result:
|
||||
let sincl = search(incl)
|
||||
if sincl == "":
|
||||
continue
|
||||
|
||||
sres.add(getIncls(sincl, inline))
|
||||
result.add(sres)
|
||||
|
||||
proc getDefines(file: string): string =
|
||||
result = result.deduplicate()
|
||||
|
||||
proc getDefines(file: string, inline=false): string =
|
||||
result = ""
|
||||
if inline:
|
||||
var incls = getIncls(file, inline)
|
||||
for incl in incls:
|
||||
let sincl = search(incl)
|
||||
if sincl != "":
|
||||
echo "Inlining " & sincl
|
||||
result &= getDefines(sincl)
|
||||
withFile(file):
|
||||
result = ""
|
||||
for def in content.findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d.x]+)(?:\r|//|/*).*?$"):
|
||||
for def in content.findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d\-.xf]+)(?:\r|//|/*).*?$"):
|
||||
result &= def.captures[0] & "\n"
|
||||
|
||||
proc runPreprocess(file, ppflags, flags: string): string =
|
||||
proc runPreprocess(file, ppflags, flags: string, inline: bool): string =
|
||||
var pproc = "gcc"
|
||||
if flags.contains("cpp"):
|
||||
pproc = "g++"
|
||||
|
|
@ -287,7 +310,9 @@ proc runPreprocess(file, ppflags, flags: string): string =
|
|||
# Include content only from file
|
||||
var rdata: Rope
|
||||
var start = false
|
||||
let sfile = file.replace("\\", "/")
|
||||
var sfile = file.replace("\\", "/")
|
||||
if inline:
|
||||
sfile = sfile.parentDir()
|
||||
for line in data.splitLines():
|
||||
if line.strip() != "":
|
||||
if line[0] == '#' and not line.contains("#pragma"):
|
||||
|
|
@ -301,6 +326,7 @@ proc runPreprocess(file, ppflags, flags: string): string =
|
|||
.replace("(())", "")
|
||||
.replace("WINAPI", "")
|
||||
.replace("__attribute__", "")
|
||||
.replace("extern \"C\"", "")
|
||||
.replace(re"\(\([_a-z]+?\)\)", "")
|
||||
.replace(re"\(\(__format__[\s]*\(__[gnu_]*printf__, [\d]+, [\d]+\)\)\);", ";") & "\n"
|
||||
)
|
||||
|
|
@ -326,7 +352,7 @@ proc runCtags(file: string): string =
|
|||
|
||||
proc runFile(file: string, cfgin: OrderedTableRef)
|
||||
|
||||
proc c2nim(fl, outfile, flags, ppflags: string, recurse, preprocess, ctags, defines: bool, dynlib, compile, pragma: seq[string] = @[]) =
|
||||
proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, ctags, defines: bool, dynlib, compile, pragma: seq[string] = @[]) =
|
||||
var file = search(fl)
|
||||
if file == "":
|
||||
return
|
||||
|
|
@ -358,13 +384,13 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preprocess, ctags, defi
|
|||
var cfile = file
|
||||
if preprocess:
|
||||
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
||||
writeFile(cfile, runPreprocess(file, ppflags, flags))
|
||||
writeFile(cfile, runPreprocess(file, ppflags, flags, inline))
|
||||
elif ctags:
|
||||
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
||||
writeFile(cfile, runCtags(file))
|
||||
|
||||
if defines and (preprocess or ctags):
|
||||
prepend(cfile, getDefines(file))
|
||||
prepend(cfile, getDefines(file, inline))
|
||||
|
||||
var extflags = ""
|
||||
var passC = ""
|
||||
|
|
@ -496,6 +522,7 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
|
|||
|
||||
if file.splitFile().ext != ".nim":
|
||||
var recurse = false
|
||||
var inline = false
|
||||
var preprocess = false
|
||||
var ctags = false
|
||||
var defines = false
|
||||
|
|
@ -507,6 +534,8 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
|
|||
if cfg[act] == "true":
|
||||
if act == "recurse":
|
||||
recurse = true
|
||||
elif act == "inline":
|
||||
inline = true
|
||||
elif act == "preprocess":
|
||||
preprocess = true
|
||||
elif act == "ctags":
|
||||
|
|
@ -520,8 +549,12 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
|
|||
elif act == "ppflags":
|
||||
ppflags = cfg[act]
|
||||
|
||||
if recurse and inline:
|
||||
echo "Cannot use recurse and inline simultaneously"
|
||||
quit(1)
|
||||
|
||||
if not noprocess:
|
||||
c2nim(file, getNimout(file), flags, ppflags, recurse, preprocess, ctags, defines, dynlib, compile, pragma)
|
||||
c2nim(file, getNimout(file), flags, ppflags, recurse, inline, preprocess, ctags, defines, dynlib, compile, pragma)
|
||||
|
||||
proc runCfg(cfg: string) =
|
||||
if not fileExists(cfg):
|
||||
|
|
@ -533,12 +566,21 @@ proc runCfg(cfg: string) =
|
|||
if CONFIG.hasKey("n.global"):
|
||||
if CONFIG["n.global"].hasKey("output"):
|
||||
OUTPUT = CONFIG["n.global"]["output"]
|
||||
|
||||
if ARGS["-f"]:
|
||||
removeDir(OUTPUT)
|
||||
else:
|
||||
for f in walkFiles(OUTPUT/"*.nim"):
|
||||
removeFile(f)
|
||||
if dirExists(OUTPUT):
|
||||
if ARGS["-f"]:
|
||||
try:
|
||||
removeDir(OUTPUT)
|
||||
except OSError:
|
||||
echo "Directory in use: " & OUTPUT
|
||||
quit(1)
|
||||
else:
|
||||
for f in walkFiles(OUTPUT/"*.nim"):
|
||||
try:
|
||||
removeFile(f)
|
||||
except OSError:
|
||||
echo "Unable to delete: " & f
|
||||
quit(1)
|
||||
createDir(OUTPUT)
|
||||
|
||||
if CONFIG["n.global"].hasKey("filter"):
|
||||
FILTER = CONFIG["n.global"]["filter"]
|
||||
|
|
@ -560,6 +602,8 @@ proc runCfg(cfg: string) =
|
|||
if val == true:
|
||||
if key == "download":
|
||||
downloadUrl(CONFIG["n.prepare"][prep])
|
||||
elif key == "extract":
|
||||
extractZip(CONFIG["n.prepare"][prep])
|
||||
elif key == "git":
|
||||
gitRemotePull(CONFIG["n.prepare"][prep])
|
||||
elif key == "gitremote":
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
author = "genotrance"
|
||||
description = "c2nim helper to simplify and automate the wrapping of C libraries"
|
||||
license = "MIT"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue