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
|
```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
|
```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
|
```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]
|
```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
|
```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
|
```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
|
import tables
|
||||||
|
|
||||||
var DONE: seq[string] = @[]
|
var DONE: seq[string] = @[]
|
||||||
|
var DONE_INLINE: seq[string] = @[]
|
||||||
|
|
||||||
var CONFIG: Config
|
var CONFIG: Config
|
||||||
var FILTER = ""
|
var FILTER = ""
|
||||||
|
|
@ -75,7 +76,6 @@ proc downloadUrl(url: string) =
|
||||||
|
|
||||||
if not (ext == ".zip" and fileExists(OUTPUT/file)):
|
if not (ext == ".zip" and fileExists(OUTPUT/file)):
|
||||||
echo "Downloading " & file
|
echo "Downloading " & file
|
||||||
createDir(OUTPUT)
|
|
||||||
discard execProc(cmd % [url, OUTPUT/file])
|
discard execProc(cmd % [url, OUTPUT/file])
|
||||||
|
|
||||||
if ext == ".zip":
|
if ext == ".zip":
|
||||||
|
|
@ -95,7 +95,6 @@ proc gitRemotePull(url: string, pull=true) =
|
||||||
gitReset()
|
gitReset()
|
||||||
return
|
return
|
||||||
|
|
||||||
createDir(OUTPUT)
|
|
||||||
setCurrentDir(OUTPUT)
|
setCurrentDir(OUTPUT)
|
||||||
defer: setCurrentDir("..")
|
defer: setCurrentDir("..")
|
||||||
|
|
||||||
|
|
@ -257,8 +256,11 @@ proc fixFuncProtos(file: string) =
|
||||||
# ###
|
# ###
|
||||||
# Convert to Nim
|
# Convert to Nim
|
||||||
|
|
||||||
proc getIncls(file: string): seq[string] =
|
proc getIncls(file: string, inline=false): seq[string] =
|
||||||
result = @[]
|
result = @[]
|
||||||
|
if inline and file in DONE_INLINE:
|
||||||
|
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()
|
||||||
|
|
@ -266,14 +268,35 @@ proc getIncls(file: string): seq[string] =
|
||||||
result.add(inc.replace(re"""[<>"]""", "").strip())
|
result.add(inc.replace(re"""[<>"]""", "").strip())
|
||||||
|
|
||||||
result = result.deduplicate()
|
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):
|
withFile(file):
|
||||||
result = ""
|
for def in content.findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d\-.xf]+)(?:\r|//|/*).*?$"):
|
||||||
for def in content.findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d.x]+)(?:\r|//|/*).*?$"):
|
|
||||||
result &= def.captures[0] & "\n"
|
result &= def.captures[0] & "\n"
|
||||||
|
|
||||||
proc runPreprocess(file, ppflags, flags: string): string =
|
proc runPreprocess(file, ppflags, flags: string, inline: bool): string =
|
||||||
var pproc = "gcc"
|
var pproc = "gcc"
|
||||||
if flags.contains("cpp"):
|
if flags.contains("cpp"):
|
||||||
pproc = "g++"
|
pproc = "g++"
|
||||||
|
|
@ -287,7 +310,9 @@ proc runPreprocess(file, ppflags, flags: string): string =
|
||||||
# Include content only from file
|
# Include content only from file
|
||||||
var rdata: Rope
|
var rdata: Rope
|
||||||
var start = false
|
var start = false
|
||||||
let sfile = file.replace("\\", "/")
|
var sfile = file.replace("\\", "/")
|
||||||
|
if inline:
|
||||||
|
sfile = sfile.parentDir()
|
||||||
for line in data.splitLines():
|
for line in data.splitLines():
|
||||||
if line.strip() != "":
|
if line.strip() != "":
|
||||||
if line[0] == '#' and not line.contains("#pragma"):
|
if line[0] == '#' and not line.contains("#pragma"):
|
||||||
|
|
@ -301,6 +326,7 @@ proc runPreprocess(file, ppflags, flags: string): string =
|
||||||
.replace("(())", "")
|
.replace("(())", "")
|
||||||
.replace("WINAPI", "")
|
.replace("WINAPI", "")
|
||||||
.replace("__attribute__", "")
|
.replace("__attribute__", "")
|
||||||
|
.replace("extern \"C\"", "")
|
||||||
.replace(re"\(\([_a-z]+?\)\)", "")
|
.replace(re"\(\([_a-z]+?\)\)", "")
|
||||||
.replace(re"\(\(__format__[\s]*\(__[gnu_]*printf__, [\d]+, [\d]+\)\)\);", ";") & "\n"
|
.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 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)
|
var file = search(fl)
|
||||||
if file == "":
|
if file == "":
|
||||||
return
|
return
|
||||||
|
|
@ -358,13 +384,13 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preprocess, ctags, defi
|
||||||
var cfile = file
|
var cfile = file
|
||||||
if preprocess:
|
if preprocess:
|
||||||
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
||||||
writeFile(cfile, runPreprocess(file, ppflags, flags))
|
writeFile(cfile, runPreprocess(file, ppflags, flags, inline))
|
||||||
elif ctags:
|
elif ctags:
|
||||||
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
||||||
writeFile(cfile, runCtags(file))
|
writeFile(cfile, runCtags(file))
|
||||||
|
|
||||||
if defines and (preprocess or ctags):
|
if defines and (preprocess or ctags):
|
||||||
prepend(cfile, getDefines(file))
|
prepend(cfile, getDefines(file, inline))
|
||||||
|
|
||||||
var extflags = ""
|
var extflags = ""
|
||||||
var passC = ""
|
var passC = ""
|
||||||
|
|
@ -496,6 +522,7 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
|
||||||
|
|
||||||
if file.splitFile().ext != ".nim":
|
if file.splitFile().ext != ".nim":
|
||||||
var recurse = false
|
var recurse = false
|
||||||
|
var inline = false
|
||||||
var preprocess = false
|
var preprocess = false
|
||||||
var ctags = false
|
var ctags = false
|
||||||
var defines = false
|
var defines = false
|
||||||
|
|
@ -507,6 +534,8 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
|
||||||
if cfg[act] == "true":
|
if cfg[act] == "true":
|
||||||
if act == "recurse":
|
if act == "recurse":
|
||||||
recurse = true
|
recurse = true
|
||||||
|
elif act == "inline":
|
||||||
|
inline = true
|
||||||
elif act == "preprocess":
|
elif act == "preprocess":
|
||||||
preprocess = true
|
preprocess = true
|
||||||
elif act == "ctags":
|
elif act == "ctags":
|
||||||
|
|
@ -520,8 +549,12 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
|
||||||
elif act == "ppflags":
|
elif act == "ppflags":
|
||||||
ppflags = cfg[act]
|
ppflags = cfg[act]
|
||||||
|
|
||||||
|
if recurse and inline:
|
||||||
|
echo "Cannot use recurse and inline simultaneously"
|
||||||
|
quit(1)
|
||||||
|
|
||||||
if not noprocess:
|
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) =
|
proc runCfg(cfg: string) =
|
||||||
if not fileExists(cfg):
|
if not fileExists(cfg):
|
||||||
|
|
@ -533,12 +566,21 @@ proc runCfg(cfg: string) =
|
||||||
if CONFIG.hasKey("n.global"):
|
if CONFIG.hasKey("n.global"):
|
||||||
if CONFIG["n.global"].hasKey("output"):
|
if CONFIG["n.global"].hasKey("output"):
|
||||||
OUTPUT = CONFIG["n.global"]["output"]
|
OUTPUT = CONFIG["n.global"]["output"]
|
||||||
|
if dirExists(OUTPUT):
|
||||||
if ARGS["-f"]:
|
if ARGS["-f"]:
|
||||||
removeDir(OUTPUT)
|
try:
|
||||||
else:
|
removeDir(OUTPUT)
|
||||||
for f in walkFiles(OUTPUT/"*.nim"):
|
except OSError:
|
||||||
removeFile(f)
|
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"):
|
if CONFIG["n.global"].hasKey("filter"):
|
||||||
FILTER = CONFIG["n.global"]["filter"]
|
FILTER = CONFIG["n.global"]["filter"]
|
||||||
|
|
@ -560,6 +602,8 @@ proc runCfg(cfg: string) =
|
||||||
if val == true:
|
if val == true:
|
||||||
if key == "download":
|
if key == "download":
|
||||||
downloadUrl(CONFIG["n.prepare"][prep])
|
downloadUrl(CONFIG["n.prepare"][prep])
|
||||||
|
elif key == "extract":
|
||||||
|
extractZip(CONFIG["n.prepare"][prep])
|
||||||
elif key == "git":
|
elif key == "git":
|
||||||
gitRemotePull(CONFIG["n.prepare"][prep])
|
gitRemotePull(CONFIG["n.prepare"][prep])
|
||||||
elif key == "gitremote":
|
elif key == "gitremote":
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
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"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue