Skip to content

Commit

Permalink
feat: add actual cli
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbash authored Jul 30, 2022
1 parent 4cb6239 commit 80ea311
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 51 deletions.
41 changes: 21 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Try it out though, it might just work.
Following sections assume that [[C_LIB]] is the name of the library you are
generating bindings for.

## Extract definitions from [[C_LIB]].h
### Extract definitions from [[C_LIB]].h

```sh
docker run -v $(pwd):/data glebbash/deno-ffigen-c2ffi /data/input/[[C_LIB]].h > input/[[C_LIB]].json
Expand All @@ -31,7 +31,7 @@ This will use prebuilt docker image of [c2ffi](https://github.com/rpav/c2ffi) to
generate `input/[[C_LIB]].json` file containing all symbols found in
`input/[[C_LIB]].h`.

## Extract symbols from [[C_LIB]].so
### Extract symbols from [[C_LIB]].so

```sh
readelf -Ws --dyn-syms input/[[C_LIB]].so > input/[[C_LIB]]_symbols.txt
Expand All @@ -43,27 +43,28 @@ exposed symbols of `input/[[C_LIB]].so`.
## Generate bindings

```sh
deno run -A https://raw.githubusercontent.com/glebbash/deno-ffigen/main/mod.ts \
input/[[C_LIB]].json \
input/[[C_LIB]]_symbols.txt \
[[OUTPUT_FOLDER]] \
[[LIB_PREFIX]] \
[[SOURCE_BASE_URL]]
deno run -A https://deno.land/x/ffigen/cli.ts \
--definitions input/[[C_LIB]].json \
--symbols input/[[C_LIB]]_symbols.txt \
--headers [[HEADERS_BASE_URL]] \
--lib-name [[LIB_NAME]]
```

- [[LIB_PREFIX]]: Prefix of the C library, will be stripped from all functions
and used as a namespace.
- [[OUTPUT_FOLDER]]: Folder where generated bindings will be placed.
- [[SOURCE_BASE_URL]]: Base url for the target library, will be used to generate
links in description of each function. Example:
`"https://github.com/llvm/llvm-project/blob/315072/llvm/include/"`

Using `input/[[C_LIB]].json` and `input/[[C_LIB]]_symbols.txt` as inputs
deno-ffigen generates the following files:

- `[[OUTPUT_FOLDER]]/mod.ts` - Bindings entry that also dlopens the shared lib
- `[[OUTPUT_FOLDER]]/types.ts` - Namespace with all type/enum/function
definitions
- `[[OUTPUT_FOLDER]]/symbols.ts` - Exports object with lib definition for
- `[[LIB_NAME]]/mod.ts` - Bindings entry that also dlopens the shared lib
- `[[LIB_NAME]]/types.ts` - Namespace with all type/enum/function definitions
- `[[LIB_NAME]]/symbols.ts` - Exports object with lib definition for
`Deno.dlopen`
- `[[OUTPUT_FOLDER]]/safe-ffi.ts` - Type utils for making pointers typesafe
- `[[LIB_NAME]]/safe-ffi.ts` - Type utils for making pointers typesafe

For all the available options run

```bash
deno run -A https://deno.land/x/ffigen/cli.ts --help
```

## Programmatic usage

See [mod.ts](./mod.ts) for a list of available functions.
66 changes: 66 additions & 0 deletions cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Command } from "https://deno.land/x/[email protected]/command/mod.ts";
import { m } from "https://raw.githubusercontent.com/glebbash/multiline-str/master/src/multiline-str.ts";

import { generateBindings, getFunctionsFromSharedLib } from "./mod.ts";

const cmd = new Command()
.name("ffigen")
.description("FFI Bindings generator for Deno.")
.version("v0.0.1beta")
.option(
"-s, --symbols <symbols-file>",
"Exposed symbols file (readelf output).",
{
required: true,
},
)
.option(
"-d, --definitions <definitions-file>",
"Definitions file. (c2ffi json output).",
{
required: true,
},
)
.option(
"-h, --headers <headers>",
"Base url for the headers of target library.",
{
required: true,
},
)
.option(
"-n, --lib-name <lib-name>",
"Name of the C library and generated namespace.",
{
required: true,
},
)
.option(
"-p, --lib-prefix <lib-prefix>",
"Library prefix to strip from all symbols.",
{ default: "<lib-name>" },
)
.helpOption("--help")
.example(
"headers",
m`
Headers option is used to generate links in description of each function.
Example: "https://github.com/llvm/llvm-project/blob/release/14.x/llvm/include/"
`,
)
.arguments("[outputFolder]");

const { args, options } = await cmd.parse();

const exposedFunctions = await getFunctionsFromSharedLib(
options.symbols,
);

await generateBindings(
options.definitions,
exposedFunctions,
args[0] ?? options.libName,
options.libName,
options.headers,
options.libPrefix ?? options.libName,
);
12 changes: 6 additions & 6 deletions examples/llvm-c-14/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ exposed symbols of `/usr/lib/llvm-14/lib/libLLVM.so`.
## Generate bindings

```sh
deno run -A https://raw.githubusercontent.com/glebbash/deno-ffigen/main/mod.ts \
input/llvm-c.json \
input/llvm-c_symbols.txt \
llvm-c \
LLVM \
"https://github.com/llvm/llvm-project/blob/release/14.x/llvm/include/"
deno run -A https://deno.land/x/ffigen/cli.ts \
--definitions input/llvm-c.json \
--symbols input/llvm-c_symbols.txt \
--headers "https://github.com/llvm/llvm-project/blob/release/14.x/llvm/include/" \
--lib-name LLVM \
llvm-c
```

Using `input/llvm-c.json` and `input/llvm-c_symbols.txt` as inputs. Bindings are
Expand Down
27 changes: 2 additions & 25 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,5 @@
import { generateBindings } from "./generate-bindings.ts";
import { getFunctionsFromSharedLib } from "./get-functions-from-shared-lib.ts";

// TODO: improve cli
// TODO: clean up
// TODO: check what can be done on struct support

if (import.meta.main) {
const [
allSymbolsFile,
exposedSymbolsFile,
outputFolder,
libName,
baseSourcePath,
] = Deno.args;

const exposedFunctions = await getFunctionsFromSharedLib(
exposedSymbolsFile,
);

await generateBindings(
allSymbolsFile,
exposedFunctions,
outputFolder,
libName,
baseSourcePath,
);
}
export { generateBindings } from "./generate-bindings.ts";
export { getFunctionsFromSharedLib } from "./get-functions-from-shared-lib.ts";

0 comments on commit 80ea311

Please sign in to comment.