Skip to content
This repository has been archived by the owner on Jun 23, 2023. It is now read-only.

feat(allow-symbols): Better symbol selection #14

Merged
merged 1 commit into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "lerna workspace for clangffi, libclang-bindings tools",
"scripts": {
"clangffi": "node packages/clangffi/dist/bin/clangffi.js",
"generate-dogfood": "npm run clangffi -- -i vendor/llvm-project/clang/include/clang-c/Index.h -I vendor/llvm-project/clang/include/ -o packages/libclang-bindings/src/libclang.ts",
"generate-dogfood": "npm run clangffi -- -i vendor/llvm-project/clang/include/clang-c/Index.h -I vendor/llvm-project/clang/include/ -o packages/libclang-bindings/src/libclang.ts --allow-symbol time_t --allow-symbol __time32_t --allow-symbol __time64_t",
"bootstrap": "lerna bootstrap",
"build": "lerna run build --stream",
"test": "lerna run test --stream -- -- --passWithNoTests"
Expand Down
12 changes: 10 additions & 2 deletions packages/clangffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ Options:
-I, --include-directory Additional include directories to use during parsing
[array] [default: []]
--lib-path The path to the libclang binary to load. [string]
--allow Additional file paths to allow symbols from
--allow-file Additional file paths to allow symbols from
[array] [default: []]
--allow-symbol Additional symbol name to allow regardless of it's
location [array] [default: []]
--crlf Use crlf endings instead of lf
[boolean] [default: false]
--no-sibling Does not include sibling file symbols in the
Expand All @@ -49,7 +51,13 @@ Options:
Generate typescript ffi-napi bindings for any c/c++ library using libclang.
```

Note that by default, only symbols that are directly sourced from the `input` header or included files that are next to the input header on disk (e.g. "sibling" files) will be included in the bindings. To include other symbols, specify the `--allow` flag, passing other source files. E.g. `--input path/to/initial/header.h --allow path/to/included/header.h`.
## Selecting symbols

By default, only symbols that are directly sourced from the `input` header or included files that are next to the input header on disk (e.g. "sibling" files) will be included in the bindings.

To include other symbols, specify the `--allow-file` flag, passing other source files. E.g. `--input path/to/initial/header.h --allow-file path/to/included/header.h`. It is also possible to allow specific symbols with the `--allow-symbol` flag, which includes symbols with a particular name regardless of their source location. E.g. `--input path/to/initial/header.h --allow-symbol YourSymbolName`.

When both `--allow-file` and `--allow-symbol` are used, all symbols from the `--allow-file` files are included, as well as any symbols that are specified from `--allow-symbol`. Further - Just to clarify - if a symbol matches both `--allow-file` and `--allow-symbol` it's included (hopefully that's what you'd expect).

## Logging

Expand Down
19 changes: 14 additions & 5 deletions packages/clangffi/src/bin/clangffi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,18 @@ const args = yargs(hideBin(process.argv))
.string("I")
.array("I")
.alias("I", "include-directory")
.string("allow")
.array("allow")
.string("allow-file")
.array("allow-file")
.string("allow-symbol")
.array("allow-symbol")
.default({
crlf: false,
"no-prettier": false,
"no-sibling": false,
L: "c",
I: [],
allow: [],
"allow-file": [],
"allow-symbol": [],
})
.demandOption("input")
.demandOption("output")
Expand All @@ -51,7 +54,9 @@ const args = yargs(hideBin(process.argv))
L: "Language to parse input as",
I: "Additional include directories to use during parsing",
"lib-path": "The path to the libclang binary to load.",
allow: "Additional file paths to allow symbols from",
"allow-file": "Additional file paths to allow symbols from",
"allow-symbol":
"Additional symbol name to allow regardless of it's location",
crlf: "Use crlf endings instead of lf",
"no-sibling":
"Does not include sibling file symbols in the generated bindings",
Expand All @@ -66,6 +71,7 @@ if (!(args instanceof Promise)) {
const fileDir = path.dirname(args.input);
const lang: Language = args.language == "c" ? Language.C : Language.Cpp;
const includeDirectories: string[] = args.includeDirectory ?? [];
const additionalSymbols: string[] = args.allowSymbol ?? [];

const includeFiles = includeDirectories.flatMap((includeDir) =>
fs
Expand All @@ -81,7 +87,9 @@ if (!(args instanceof Promise)) {
.map((f) => path.join(fileDir, f))
.filter((f) => path.extname(f) == ".h");

const additionalFiles = siblingFiles.concat(includeFiles);
const additionalFiles = siblingFiles
.concat(includeFiles)
.concat(args.allowFile ?? []);

const defaultLibPath =
process.platform == "win32" ? "libclang.dll" : "libclang";
Expand All @@ -96,6 +104,7 @@ if (!(args instanceof Promise)) {
language: lang,
additionalFiles,
includeDirectories,
additionalSymbols,
generator: new TsGen({
lineEndings: args.crlf ? LineEndings.CRLF : LineEndings.LF,
usePrettier: args["no-prettier"] ? false : true,
Expand Down
22 changes: 14 additions & 8 deletions packages/clangffi/src/lib/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ export interface ParserOptions extends Omit<ParseOptions, "index"> {
*/
additionalFiles: string[];

/**
* Additional symbols to include (by name)
*/
additionalSymbols: string[];

/**
* The source generator to use
*/
Expand Down Expand Up @@ -97,18 +102,19 @@ export class Parser {
}

const sp = formatPath(decl.sourcePath);
const logSymbolName = resolveName(decl);
const symbolName = resolveName(decl);

const isAllowedSymbol =
this.opts.additionalFiles.some((f) => formatPath(f) == sp) ||
this.opts.additionalSymbols.some((s) => s == symbolName);

// skip symbols that aren't in our purview
if (
sp != this.opts.path &&
!this.opts.additionalFiles.some((f) => formatPath(f) == sp)
) {
log(`skip '${logSymbolName}' from '${sp}'.`);
if (sp != this.opts.path && !isAllowedSymbol) {
log(`skip '${symbolName}' from '${sp}'.`);
return CXChildVisitResult.CXChildVisit_Continue;
}

log(`processing '${logSymbolName}'`);
log(`processing '${symbolName}'`);

// openers
if (decl instanceof EnumDecl) {
Expand Down Expand Up @@ -164,7 +170,7 @@ export class Parser {
this.opts.generator.closeFunctionParam(decl as ParamDecl);
}

log(`finished '${logSymbolName}'`);
log(`finished '${symbolName}'`);
} catch (e) {
log(e);

Expand Down