- Docopt for CLI parsing
- Download, extract and Git checkout support - OS specific keys with -win, -lin and -osx - Force re-generation with -f flag
This commit is contained in:
parent
e5eb693d2e
commit
9bcabd23e3
4 changed files with 173 additions and 50 deletions
22
README.md
22
README.md
|
|
@ -38,11 +38,11 @@ __Config file__
|
|||
|
||||
_[n.global]_
|
||||
|
||||
output = name of the Nimble project once installed, also location to place generated .nim files
|
||||
```output``` = name of the Nimble project once installed, also location to place generated .nim files
|
||||
|
||||
quotes = pick up any headers included using "" (and not <> which is typically used for standard headers) [default: true]
|
||||
```quotes``` = pick up any headers included using "" (and not <> which is typically used for standard headers) [default: true]
|
||||
|
||||
filter = string to identify and recurse into library .h files in #include statements and exclude standard headers
|
||||
```filter``` = string to identify and recurse into library .h files in #include statements and exclude standard headers
|
||||
|
||||
_[n.include]_
|
||||
|
||||
|
|
@ -56,9 +56,23 @@ _[n.exclude]_
|
|||
|
||||
List of all directories or files to exclude from all parsing. If an entry here matches any portion of a file, it is excluded from recursive processing.
|
||||
|
||||
_[n.prepare]_
|
||||
|
||||
The following keys can be used to prepare dependencies such as downloading ZIP files, cloning Git repositories, etc. Multiple entries are possible by appending any .string to the key. E.g. download.file1. -win, -lin and -osx can be used for OS specific tasks. E.g. download-win
|
||||
|
||||
```download``` = url to download to the output directory. ZIP files are automatically extracted. Files are not redownloaded if already present but re-extracted
|
||||
|
||||
```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
|
||||
|
||||
```gitsparse``` = list of files and/or dirs to include in partial checkout, one per line. Resets to HEAD if already present
|
||||
|
||||
```execute``` = command to run during preparation
|
||||
|
||||
_[sourcefile]_
|
||||
|
||||
The following keys apply to library source code and help with generating the .nim files.
|
||||
The following keys apply to library source code and help with generating the .nim files. -win, -lin and -osx can be used for OS specific tasks. E.g. dynlib-win
|
||||
|
||||
```recurse``` = find #include files and process them [default: false]
|
||||
|
||||
|
|
|
|||
190
nimgen.nim
190
nimgen.nim
|
|
@ -1,3 +1,4 @@
|
|||
import docopt
|
||||
import nre
|
||||
import os
|
||||
import ospaths
|
||||
|
|
@ -18,6 +19,18 @@ var OUTPUT = ""
|
|||
var INCLUDES: seq[string] = @[]
|
||||
var EXCLUDES: seq[string] = @[]
|
||||
|
||||
const DOC = """
|
||||
Nimgen is a helper for c2nim to simpilfy and automate the wrapping of C libraries
|
||||
|
||||
Usage:
|
||||
nimgen [options] <file.cfg>...
|
||||
|
||||
Options:
|
||||
-f delete all artifacts and regenerate
|
||||
"""
|
||||
|
||||
let ARGS = docopt(DOC)
|
||||
|
||||
# ###
|
||||
# Helpers
|
||||
|
||||
|
|
@ -38,7 +51,88 @@ proc execProc(cmd: string): string =
|
|||
echo "Command failed: " & $x
|
||||
echo cmd
|
||||
echo result
|
||||
quit()
|
||||
quit(1)
|
||||
|
||||
proc extractZip(zipfile: string) =
|
||||
var cmd = "unzip $#"
|
||||
if defined(Windows):
|
||||
cmd = "powershell -nologo -noprofile -command \"& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('$#', '.'); }\""
|
||||
|
||||
setCurrentDir(OUTPUT)
|
||||
defer: setCurrentDir("..")
|
||||
|
||||
echo "Extracting " & zipfile
|
||||
discard execProc(cmd % zipfile)
|
||||
|
||||
proc downloadUrl(url: string) =
|
||||
let file = url.extractFilename()
|
||||
let ext = file.splitFile().ext.toLowerAscii()
|
||||
|
||||
var cmd = "curl $# -o $#"
|
||||
if defined(Windows):
|
||||
cmd = "powershell wget $# -OutFile $#"
|
||||
|
||||
if not (ext == ".zip" and fileExists(OUTPUT/file)):
|
||||
echo "Downloading " & file
|
||||
createDir(OUTPUT)
|
||||
discard execProc(cmd % [url, OUTPUT/file])
|
||||
|
||||
if ext == ".zip":
|
||||
extractZip(file)
|
||||
|
||||
proc gitReset() =
|
||||
echo "Resetting Git repo"
|
||||
|
||||
setCurrentDir(OUTPUT)
|
||||
defer: setCurrentDir("..")
|
||||
|
||||
discard execProc("git reset --hard HEAD")
|
||||
|
||||
proc gitRemotePull(url: string, pull=true) =
|
||||
if dirExists(OUTPUT):
|
||||
if pull:
|
||||
gitReset()
|
||||
return
|
||||
|
||||
createDir(OUTPUT)
|
||||
setCurrentDir(OUTPUT)
|
||||
defer: setCurrentDir("..")
|
||||
|
||||
echo "Setting up Git repo"
|
||||
discard execProc("git init .")
|
||||
discard execProc("git remote add origin " & url)
|
||||
|
||||
if pull:
|
||||
echo "Checking out artifacts"
|
||||
discard execProc("git pull --depth=1 origin master")
|
||||
|
||||
proc gitSparseCheckout(plist: string) =
|
||||
let sparsefile = ".git/info/sparse-checkout"
|
||||
if fileExists(OUTPUT/sparsefile):
|
||||
gitReset()
|
||||
return
|
||||
|
||||
setCurrentDir(OUTPUT)
|
||||
defer: setCurrentDir("..")
|
||||
|
||||
discard execProc("git config core.sparsecheckout true")
|
||||
writeFile(sparsefile, plist)
|
||||
|
||||
echo "Checking out artifacts"
|
||||
discard execProc("git pull --depth=1 origin master")
|
||||
|
||||
proc getKey(ukey: string): tuple[key: string, val: bool] =
|
||||
var kv = ukey.replace(re"\..*", "").split("-", 1)
|
||||
if kv.len() == 1:
|
||||
kv.add("")
|
||||
|
||||
if (kv[1] == "") or
|
||||
(kv[1] == "win" and defined(Windows)) or
|
||||
(kv[1] == "lin" and defined(Linux)) or
|
||||
(kv[1] == "osx" and defined(MacOSX)):
|
||||
return (kv[0], true)
|
||||
|
||||
return (kv[0], false)
|
||||
|
||||
# ###
|
||||
# File loction
|
||||
|
|
@ -72,7 +166,7 @@ proc search(file: string): string =
|
|||
break
|
||||
if not found:
|
||||
echo "File doesn't exist: " & file
|
||||
quit()
|
||||
quit(1)
|
||||
|
||||
return result.replace(re"[\\/]", $DirSep)
|
||||
|
||||
|
|
@ -275,18 +369,19 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define:
|
|||
var winlib, linlib, osxlib: string = ""
|
||||
for dl in dynlib:
|
||||
let lib = " const dynlib$# = \"$#\"\n" % [fname, dl]
|
||||
if dl.splitFile().ext == ".dll":
|
||||
let ext = dl.splitFile().ext
|
||||
if ext == ".dll":
|
||||
winlib &= lib
|
||||
if dl.splitFile().ext == ".so":
|
||||
elif ext == ".so":
|
||||
linlib &= lib
|
||||
if dl.splitFile().ext == ".dylib":
|
||||
elif ext == ".dylib":
|
||||
osxlib &= lib
|
||||
|
||||
if winlib != "":
|
||||
outlib &= win & winlib & "\n"
|
||||
if linlib != "":
|
||||
outlib &= lin & linlib & "\n"
|
||||
if winlib != "":
|
||||
if osxlib != "":
|
||||
outlib &= osx & osxlib & "\n"
|
||||
|
||||
if outlib != "":
|
||||
|
|
@ -336,13 +431,17 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define:
|
|||
proc runcfg(cfg: string) =
|
||||
if not fileExists(cfg):
|
||||
echo "Config doesn't exist: " & cfg
|
||||
quit()
|
||||
quit(1)
|
||||
|
||||
CONFIG = loadConfig(cfg)
|
||||
|
||||
if CONFIG.hasKey("n.global"):
|
||||
if CONFIG["n.global"].hasKey("output"):
|
||||
OUTPUT = CONFIG["n.global"]["output"]
|
||||
|
||||
if ARGS["-f"]:
|
||||
removeDir(OUTPUT)
|
||||
|
||||
if CONFIG["n.global"].hasKey("filter"):
|
||||
FILTER = CONFIG["n.global"]["filter"]
|
||||
if CONFIG["n.global"].hasKey("quotes"):
|
||||
|
|
@ -357,42 +456,57 @@ proc runcfg(cfg: string) =
|
|||
for excl in CONFIG["n.exclude"].keys():
|
||||
EXCLUDES.add(excl)
|
||||
|
||||
if CONFIG.hasKey("n.prepare"):
|
||||
for prep in CONFIG["n.prepare"].keys():
|
||||
let (key, val) = getKey(prep)
|
||||
if val == true:
|
||||
if key == "download":
|
||||
downloadUrl(CONFIG["n.prepare"][prep])
|
||||
elif key == "git":
|
||||
gitRemotePull(CONFIG["n.prepare"][prep])
|
||||
elif key == "gitremote":
|
||||
gitRemotePull(CONFIG["n.prepare"][prep], false)
|
||||
elif key == "gitsparse":
|
||||
gitSparseCheckout(CONFIG["n.prepare"][prep])
|
||||
elif key == "execute":
|
||||
discard execProc(CONFIG["n.prepare"][prep])
|
||||
|
||||
for file in CONFIG.keys():
|
||||
if file in @["n.global", "n.include", "n.exclude"]:
|
||||
if file in @["n.global", "n.include", "n.exclude", "n.prepare"]:
|
||||
continue
|
||||
|
||||
var sfile = search(file)
|
||||
|
||||
var srch = ""
|
||||
var action = ""
|
||||
var compile: seq[string] = @[]
|
||||
var dynlib: seq[string] = @[]
|
||||
for act in CONFIG[file].keys():
|
||||
action = act.replace(re"\..*", "")
|
||||
if action == "create":
|
||||
createDir(file.splitPath().head)
|
||||
writeFile(file, CONFIG[file][act])
|
||||
elif action in @["prepend", "append", "replace", "compile", "dynlib"] and sfile != "":
|
||||
if action == "prepend":
|
||||
if srch != "":
|
||||
prepend(sfile, CONFIG[file][act], CONFIG[file][srch])
|
||||
else:
|
||||
prepend(sfile, CONFIG[file][act])
|
||||
elif action == "append":
|
||||
if srch != "":
|
||||
append(sfile, CONFIG[file][act], CONFIG[file][srch])
|
||||
else:
|
||||
append(sfile, CONFIG[file][act])
|
||||
elif action == "replace":
|
||||
if srch != "":
|
||||
freplace(sfile, CONFIG[file][srch], CONFIG[file][act])
|
||||
elif action == "compile":
|
||||
compile.add(CONFIG[file][act])
|
||||
elif action == "dynlib":
|
||||
dynlib.add(CONFIG[file][act])
|
||||
srch = ""
|
||||
elif action == "search":
|
||||
srch = act
|
||||
let (action, val) = getKey(act)
|
||||
if val == true:
|
||||
if action == "create":
|
||||
createDir(file.splitPath().head)
|
||||
writeFile(file, CONFIG[file][act])
|
||||
elif action in @["prepend", "append", "replace", "compile", "dynlib"] and sfile != "":
|
||||
if action == "prepend":
|
||||
if srch != "":
|
||||
prepend(sfile, CONFIG[file][act], CONFIG[file][srch])
|
||||
else:
|
||||
prepend(sfile, CONFIG[file][act])
|
||||
elif action == "append":
|
||||
if srch != "":
|
||||
append(sfile, CONFIG[file][act], CONFIG[file][srch])
|
||||
else:
|
||||
append(sfile, CONFIG[file][act])
|
||||
elif action == "replace":
|
||||
if srch != "":
|
||||
freplace(sfile, CONFIG[file][srch], CONFIG[file][act])
|
||||
elif action == "compile":
|
||||
compile.add(CONFIG[file][act])
|
||||
elif action == "dynlib":
|
||||
dynlib.add(CONFIG[file][act])
|
||||
srch = ""
|
||||
elif action == "search":
|
||||
srch = act
|
||||
|
||||
if file.splitFile().ext != ".nim":
|
||||
var recurse = false
|
||||
|
|
@ -426,9 +540,5 @@ proc runcfg(cfg: string) =
|
|||
# ###
|
||||
# Main loop
|
||||
|
||||
if paramCount() == 0:
|
||||
echo "nimgen file.cfg"
|
||||
quit()
|
||||
|
||||
for i in 1..paramCount():
|
||||
runcfg(paramStr(i))
|
||||
for i in ARGS["<file.cfg>"]:
|
||||
runcfg(i)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
author = "genotrance"
|
||||
description = "c2nim helper to simpilfy and automate the wrapping of C libraries"
|
||||
license = "MIT"
|
||||
|
|
@ -9,7 +9,7 @@ skipDirs = @["tests"]
|
|||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 0.16.0", "c2nim >= 0.9.13"
|
||||
requires "nim >= 0.16.0", "c2nim >= 0.9.13", "docopt >= 0.6.5"
|
||||
|
||||
bin = @["nimgen"]
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import ospaths
|
|||
import strutils
|
||||
|
||||
for comp in @["nimbass", "nimfuzz", "nimssl"]:
|
||||
cd(".."/comp)
|
||||
exec "nimble install -y"
|
||||
exec "nimble test"
|
||||
cd(".."/"nimgen")
|
||||
withDir(".."/comp):
|
||||
exec "nimble install -y"
|
||||
exec "nimble test"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue