Add ability to exclude files or directories from wrapped output

This commit is contained in:
Ganesh Viswanathan 2020-07-12 17:35:29 -05:00
commit a9887cc6b2
6 changed files with 70 additions and 15 deletions

View file

@ -41,12 +41,16 @@ https://github.com/nimterop/nimterop/compare/v0.5.9...v0.6.3
- `xxxJBB` now allows for customizing the base location to search packages with the `jbbFlags` param to `getHeader()`. Specifying `giturl=xxx` where `xxx` could be a full Git URL or just the username for Github.com allows changing the default Git repo. In addition, `url=xxx` is also supported to download project info and binaries compiled with BinaryBuilder.org but hosted at another non-Git location. (since v0.6.3)
- It is now possible to exclude the contents of specific files or entire directories from the wrapped output using `--exclude | -X` with `toast` or `cExclude()` from a wrapper. This might be required when a header uses `#include` to pull in external dependencies. E.g. `sciter` has a `#include <gtk/gtk.h>` which pulls in the entire GTK ecosystem which is needed for successful preprocessing but we do not want to include those headers in the wrapped output when using `--recurse | -r`.
### Other improvements
- Generated wrappers no longer depend on nimterop being present - no more `import nimterop/types`. Supporting code is directly included in the wrapper output and only when required. E.g. enum macro is only included if wrapper contains enums. [#125][i125] (since v0.6.1)
- `cImport()` now includes wrapper output from a file rather than inline. Errors in generated wrappers will no longer point to a line in `macros.nim` making debugging easier. (since v0.6.1)
- `cIncludeDir()` can now accept a `seq[string]` of directories and an optional `exclude` param which sets those include directories to not be included in the wrapped output.
## Version 0.5.0

View file

@ -132,6 +132,7 @@ cDefine("HAS_ABC") # Set #defines for preprocessor and compiler
cDefine("HAS_ABC", "DEF")
cIncludeDir("clib/include") # Setup any include directories
cExclude("clib/file.h") # Exclude file from wrapped output
cImport("clib.h") # Generate wrappers for header specified
@ -219,6 +220,7 @@ Options:
-d, --debug bool false enable debug output
-D=, --defines= strings {} definitions to pass to preprocessor
-l=, --dynlib= string "" {.dynlib.} pragma to import symbols - Nim const string or file path
-X=, --exclude= strings {} files or directories to exclude from the wrapped output
-f=, --feature= Features {} flags to enable experimental features
-I=, --includeDirs= strings {} include directory to pass to preprocessor
-m=, --mode= string "" language parser: c or cpp

View file

@ -120,6 +120,9 @@ proc getToast(fullpaths: seq[string], recurse: bool = false, dynlib: string = ""
for i in gStateCT.includeDirs:
cmd.add &" --includeDirs+={i.sanitizePath}"
for i in gStateCT.exclude:
cmd.add &" --exclude+={i.sanitizePath}"
if not noNimout:
cmd.add &" --pnim"
@ -415,21 +418,52 @@ proc cAddSearchDir*(dir: string) {.compileTime.} =
if dir notin gStateCT.searchDirs:
gStateCT.searchDirs.add(dir)
macro cIncludeDir*(dir: static string): untyped =
macro cIncludeDir*(dirs: static seq[string], exclude: static[bool] = false): untyped =
## Add include directories that are forwarded to the C/C++ preprocessor if
## called within `cImport()` or `c2nImport()` as well as to the C/C++
## compiler during Nim compilation using `{.passC: "-IXXX".}`.
##
## Set `exclude = true` if the contents of these include directories should
## not be included in the wrapped output.
for dir in dirs:
var dir = interpPath(dir)
result = newNimNode(nnkStmtList)
let fullpath = findPath(dir)
if fullpath notin gStateCT.includeDirs:
gStateCT.includeDirs.add(fullpath)
if exclude:
gStateCT.exclude.add(fullpath)
let str = &"-I{fullpath.quoteShell}"
result.add quote do:
{.passC: `str`.}
if gStateCT.debug:
gecho result.repr
macro cIncludeDir*(dir: static[string], exclude: static[bool] = false): untyped =
## Add an include directory that is forwarded to the C/C++ preprocessor if
## called within `cImport()` or `c2nImport()` as well as to the C/C++
## compiler during Nim compilation using `{.passC: "-IXXX".}`.
var dir = interpPath(dir)
result = newNimNode(nnkStmtList)
##
## Set `exclude = true` if the contents of this include directory should
## not be included in the wrapped output.
return quote do:
cIncludeDir(@[`dir`], `exclude` == 1)
let fullpath = findPath(dir)
if fullpath notin gStateCT.includeDirs:
gStateCT.includeDirs.add(fullpath)
let str = &"-I{fullpath.quoteShell}"
result.add quote do:
{.passC: `str`.}
if gStateCT.debug:
gecho result.repr
macro cExclude*(paths: static seq[string]): untyped =
## Exclude specified paths - files or directories from the wrapped output
##
## Full path to file or directory is required.
result = newNimNode(nnkStmtList)
for path in paths:
gStateCT.exclude.add path
macro cExclude*(path: static string): untyped =
## Exclude specified path - file or directory from the wrapped output.
##
## Full path to file or directory is required.
return quote do:
cExclude(@[`path`])
proc cAddStdDir*(mode = "c") {.compileTime.} =
## Add the standard `c` [default] or `cpp` include paths to search

View file

@ -19,6 +19,7 @@ type
debug*: bool # `cDebug()` or `--debug | -d` to enable debug mode
defines*: seq[string] # Symbols added by `cDefine()` and `--define | -D` for C/C++ preprocessor/compiler
dynlib*: string # `cImport(dynlib)` or `--dynlib | -l` to specify variable containing library name
exclude*: seq[string] # files or directories to exclude from the wrapped output
feature*: seq[Feature] # `--feature | -f` feature flags enabled
includeDirs*: seq[string] # Paths added by `cIncludeDir()` and `--includeDirs | -I` for C/C++ preprocessor/compiler
mode*: string # `cImport(mode)` or `--mode | -m` to override detected compiler mode - c or cpp

View file

@ -13,7 +13,7 @@ var
preMainOut = ""
proc process(gState: State, path: string) =
doAssert existsFile(path), &"Invalid path {path}"
doAssert fileExists(path), &"Invalid path {path}"
if gState.mode.Bl:
gState.mode = getCompilerMode(path)
@ -38,6 +38,7 @@ proc main(
debug = false,
defines: seq[string] = @[],
dynlib: string = "",
exclude: seq[string] = @[],
feature: seq[Feature] = @[],
includeDirs: seq[string] = @[],
mode = "",
@ -65,6 +66,7 @@ proc main(
debug: debug,
defines: defines,
dynlib: dynlib,
exclude: exclude,
feature: feature,
includeDirs: includeDirs,
mode: mode,
@ -222,6 +224,7 @@ when isMainModule:
"debug": "enable debug output",
"defines": "definitions to pass to preprocessor",
"dynlib": "{.dynlib.} pragma to import symbols - Nim const string or file path",
"exclude": "files or directories to exclude from the wrapped output",
"feature": "flags to enable experimental features",
"includeDirs": "include directory to pass to preprocessor",
"mode": "language parser: c or cpp",
@ -247,6 +250,7 @@ when isMainModule:
"debug": 'd',
"defines": 'D',
"dynlib": 'l',
"exclude": 'X',
"feature": 'f',
"includeDirs": 'I',
"noComments": 'c',

View file

@ -286,7 +286,16 @@ proc getKeyword*(kind: NimSymKind): string =
proc getCurrentHeader*(fullpath: string): string =
("header" & fullpath.splitFile().name.multiReplace([(".", ""), ("-", "")]))
proc isIncluded(gState: State, file: string): bool {.inline.} =
# Check if the specified file should be excluded from wrapped output
if gState.exclude.nBl:
for excl in gState.exclude:
if file.startsWith(excl):
return
result = true
proc getPreprocessor*(gState: State, fullpath: string) =
# Get preprocessed output from the C/C++ compiler
var
args: seq[string]
start = false
@ -332,14 +341,15 @@ proc getPreprocessor*(gState: State, fullpath: string) =
start = true
elif gState.recurse:
if (pDir.Bl or pDir in line) and line notin gState.headersProcessed:
start = true
newHeaders.incl line
start = gState.isIncluded(line)
else:
for inc in includeDirs:
if line.startsWith(inc) and line notin gState.headersProcessed:
start = true
newHeaders.incl line
break
start = gState.isIncluded(line)
if start:
break
elif ": fatal error:" in line:
doAssert false,
"\n\nFailed in preprocessing, check if `cIncludeDir()` is needed or compiler `mode` is correct (c/cpp)" &