diff options
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | nimgen.nim | 80 | ||||
| -rw-r--r-- | nimgen.nimble | 2 |
3 files changed, 67 insertions, 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 @@ -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": diff --git a/nimgen.nimble b/nimgen.nimble index dc96989..93aa3ae 100644 --- a/nimgen.nimble +++ b/nimgen.nimble @@ -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" |
