diff --git a/README.md b/README.md index 9c9b8fd..e3295cc 100644 --- a/README.md +++ b/README.md @@ -4,165 +4,7 @@ This tool generates Scala Native bindings from C headers. It's built upon clang and Libtooling and thus respects the conventions of clang-tools. -## Usage - -Calling the tool is pretty easy, you need to specify the file(s) and the name of the created bindings. - -```sh -scala-native-bindgen --name uv /usr/include/uv.h -- -``` - -Running the previous command wild also yield warnings along with the translation. To keep only the bindings please redirect the output to a file like this: - -```sh -scala-native-bindgen --name uv /usr/include/uv.h -- > uv.scala -``` - -Run `scala-native-bindgen --help` to see all available options. - -## Obtaining bindgen - -There are 2 ways to obtain bindgen: - * [use docker container](#docker-container) - * [build binary from sources](#building) - -### Docker container - -This option requires [Docker]. - -Download docker image with the binary: - -```sh -docker pull scalabindgen/scala-native-bindgen -``` - -Mount directories with required header files and run bindgen: - -```sh -docker run -v "$(pwd)":/src -v /usr/include:/usr/include \ - --rm scalabindgen/scala-native-bindgen \ - relative/path/to/my_header.h --name my_header -- -``` - -The docker image does not contain standard headers so it is important to -mount all system include directories that are used by the header file -passed to `scala-native-bindgen`. See the [docker-bindgen.sh] script for -how to wrap the dockerized program. The `$CWD` of the container is -`/src` which should be mounted from `$(pwd)` in case relative paths are -used. - -Note, the `scalabindgen/scala-native-bindgen:latest` image is updated on -each merge to the `master` branch. - - [Docker]: https://www.docker.com/ - [docker-bindgen.sh]: scripts/docker-bindgen.sh - -## Building - -Building `scala-native-bindgen` requires the following tools and libraries: - - - [CMake] version 3.9 or higher - - [LLVM] and [Clang] version 5.0 or 6.0. - -```sh -# On apt-based systems -apt install cmake clang-$LLVM_VERSION libclang-$LLVM_VERSION-dev llvm-$LLVM_VERSION-dev - -# With `brew` -brew install cmake llvm@6 -``` - -To run the tests you also need the required Scala Native libraries. -See the [Scala Native setup guide] for instructions on installing the dependencies. - -```sh -mkdir -p bindgen/target -cd bindgen/target -cmake .. -make -./scala-native-bindgen --name ctype /usr/include/ctype.h -- -``` - -To build a statically linked executable pass `-DSTATIC_LINKING=ON` when invoking `cmake`: - -```sh -cmake -DSTATIC_LINKING=ON .. -``` - -Additional compiler and linker flags may be passed as environment variable sor their CMake -equivalent, e.g. to compile with debug symbols the following are the same: - -```sh -cmake -DCMAKE_CXX_FLAGS=-g .. -CXXFLAGS=-g cmake .. -``` - -### Building with `docker-compose` - -Alternatively, you can use [docker-compose] to build and test the program: - -```sh -# Build the docker image with LLVM version 6.0. -docker-compose build ubuntu-18.04-llvm-6.0 -# Build the bindgen tool and run the tests. -docker-compose run --rm ubuntu-18.04-llvm-6.0 ./script/test.sh -# Run the bindgen tool inside the container. -docker-compose run --rm ubuntu-18.04-llvm-6.0 \ - bindgen/target/scala-native-bindgen --name union tests/samples/Union.h -- -``` - - [CMake]: https://cmake.org/ - [LLVM]: https://llvm.org/ - [Clang]: https://clang.llvm.org/ - [Scala Native setup guide]: http://www.scala-native.org/en/latest/user/setup.html - [docker-compose]: https://docs.docker.com/compose/ - -## Testing - -The tests assume that the above instructions for building `scala-native-bindgen` from source -has been followed. - -```sh -cd tests -sbt test -``` - -## Limitations - -There are multiple unsupported cases that should be considered when generating bindings: - - 1. Currently bindgen does not support passing structs by value. - For example, it will not be possible to call these two functions from Scala Native code: - ```c - struct MyStruct { - int a; - }; - - struct MyStruct returnStruct(); - - void handleStruct(struct MyStruct mystr); - ``` - To support such cases one should generate bindings for C wrapper functions that use pointers to structs instead of actual structs. - 2. `#define`s for literals and variables are supported. For other types of `#define`s, - write wrapper functions that return defined values. - ```c - // Supported - #define ESC 0x1b /* Defines for numerical and string literals. */ - extern const int pi_const; - #define PI pi_const /* Defines aliasing extern variables. */ - - // Not supported (non-exhaustive list) - #define COLS (getenv("COLS") ? atoi(getenv("COLS")) : 80) - #define MAX(a, b) (a > b ? a : b) - ``` - - 3. There is no way to reuse already generated bindings. - Bindgen outputs bindings also for headers that were included in a given header. See [#2]. - 4. Type qualifiers `const`, `volatile` and `restrict` are not supported. - 5. Extern variables are read-only. See [scala-native/scala-native#202]. - - [#2]: https://github.com/kornilova-l/scala-native-bindgen/issues/2 - [scala-native/scala-native#202]: https://github.com/scala-native/scala-native/issues/202 +[Documentation](https://kornilova-l.github.io/scala-native-bindgen/) ## License diff --git a/build.sbt b/build.sbt index 2576997..0ccfbee 100644 --- a/build.sbt +++ b/build.sbt @@ -88,3 +88,14 @@ lazy val samples = project ) lazy val tools = project in file("tools") + +lazy val docs = project + .in(file("docs")) + .enablePlugins(GhpagesPlugin, ParadoxSitePlugin) + .settings( + paradoxTheme := Some(builtinParadoxTheme("generic")), + paradoxProperties in Paradox ++= Map( + "github.base_url" -> "https://github.com/kornilova-l/scala-native-bindgen/tree/master/" + ), + git.remoteRepo := "git@github.com:kornilova-l/scala-native-bindgen.git" + ) diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index 2f7efbe..0000000 --- a/docs/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-minimal \ No newline at end of file diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 11a7039..0000000 --- a/docs/index.md +++ /dev/null @@ -1,6 +0,0 @@ -# Scala Native Bindgen - -This tool generates Scala Native bindings from C headers. -It's built upon clang and [LibTooling] and thus respects the conventions of clang-tools. - - [LibTooling]: https://clang.llvm.org/docs/LibTooling.html diff --git a/docs/obtaining-bindgen.md b/docs/obtaining-bindgen.md deleted file mode 100644 index 4ce78f3..0000000 --- a/docs/obtaining-bindgen.md +++ /dev/null @@ -1,107 +0,0 @@ -# Obtaining bindgen - -There are 2 ways to obtain bindgen: - * [Use docker container](#docker-container) - * [Build binary with CMake](#building-with-cmake) - * [Build binary with docker-compose](#building-with-docker-compose) - -## Docker container - -This option requires [Docker]. - -Download docker image with the binary: - -```sh -docker pull scalabindgen/scala-native-bindgen -``` - -Mount directories with required header files and run bindgen: - -```sh -docker run -v "$(pwd)":/src -v /usr/include:/usr/include \ - --rm scalabindgen/scala-native-bindgen \ - relative/path/to/my_header.h --name my_header -- -``` - -The docker image does not contain standard headers so it is important to -mount all system include directories that are used by the header file -passed to `scala-native-bindgen`. See the [docker-bindgen.sh] script for -how to wrap the dockerized program. The `$CWD` of the container is -`/src` which should be mounted from `$(pwd)` in case relative paths are -used. - -Note, the `scalabindgen/scala-native-bindgen:latest` image is updated on -each merge to the `master` branch. - - [Docker]: https://www.docker.com/ - [docker-bindgen.sh]: scripts/docker-bindgen.sh - -## Building with `CMake` - -Building `scala-native-bindgen` requires the following tools and libraries: - - - [CMake] version 3.9 or higher - - [LLVM] and [Clang] version 5.0 or 6.0. - -```sh -# On apt-based systems -apt install cmake clang-$LLVM_VERSION libclang-$LLVM_VERSION-dev llvm-$LLVM_VERSION-dev - -# With `brew` -brew install cmake llvm@6 -``` - -To run the tests you also need the required Scala Native libraries. -See the [Scala Native setup guide] for instructions on installing the dependencies. - -```sh -mkdir -p bindgen/target -cd bindgen/target -cmake .. -make -./scala-native-bindgen --name ctype /usr/include/ctype.h -- -``` - -To build a statically linked executable pass `-DSTATIC_LINKING=ON` when invoking `cmake`: - -```sh -cmake -DSTATIC_LINKING=ON .. -``` - -Additional compiler and linker flags may be passed as environment variable sor their CMake -equivalent, e.g. to compile with debug symbols the following are the same: - -```sh -cmake -DCMAKE_CXX_FLAGS=-g .. -CXXFLAGS=-g cmake .. -``` - -## Building with `docker-compose` - -Alternatively, you can use [docker-compose] to build and test the program: - -```sh -# Build the docker image with LLVM version 6.0. -docker-compose build ubuntu-18.04-llvm-6.0 -# Build the bindgen tool and run the tests. -docker-compose run --rm ubuntu-18.04-llvm-6.0 ./script/test.sh -# Run the bindgen tool inside the container. -docker-compose run --rm ubuntu-18.04-llvm-6.0 \ - bindgen/target/scala-native-bindgen --name union tests/samples/Union.h -- -``` - - [CMake]: https://cmake.org/ - [LLVM]: https://llvm.org/ - [Clang]: https://clang.llvm.org/ - [Scala Native setup guide]: http://www.scala-native.org/en/latest/user/setup.html - [docker-compose]: https://docs.docker.com/compose/ - -## Testing - -The tests assume that the above instructions for building `scala-native-bindgen` from source -has been followed. - -```sh -cd tests -sbt test -``` \ No newline at end of file diff --git a/docs/src/paradox/command-line-usage/index.md b/docs/src/paradox/command-line-usage/index.md new file mode 100644 index 0000000..52ddcd9 --- /dev/null +++ b/docs/src/paradox/command-line-usage/index.md @@ -0,0 +1,25 @@ +# Command Line Usage + +Calling the tool is pretty easy, you need to specify the file(s) and the name of the created bindings. + +```sh +scala-native-bindgen --name uv /usr/include/uv.h -- +``` + +Running the previous command wild also yield warnings along with the translation. To keep only the bindings please redirect the output to a file like this: + +```sh +scala-native-bindgen --name uv /usr/include/uv.h -- > uv.scala +``` + +## Bindgen Options + +| Option | Description | +|----------------------|---------------------------------------------------------------------------------| +| `--link` | Library to link with, e.g. `--link` uv for libuv. | +| `--no-link` | Library does not require linking. | +| `--name` | Scala object name that contains bindings. Default value set to library name. | +| `--package` | Package name of generated Scala file. | +| `--exclude-prefix` | Functions and unused typedefs will be removed if their names have given prefix. | +| `--extra-arg` | Additional argument to append to the compiler command line. | +| `--extra-arg-before` | Additional argument to prepend to the compiler command line. | diff --git a/docs/src/paradox/index.md b/docs/src/paradox/index.md new file mode 100644 index 0000000..609e22b --- /dev/null +++ b/docs/src/paradox/index.md @@ -0,0 +1,20 @@ +# Scala Native Bindgen + +@@@ index + +* [Obtaining Bindgen](obtaining-bindgen/index.md) +* [Command Line Usage](command-line-usage/index.md) +* [Limitations](limitations/index.md) +* [Using Generated Bindings](using-generated-bindings/README.md) + +@@@ + +This tool generates Scala Native bindings from C headers. +It's built upon clang and [LibTooling] and thus respects the conventions of clang-tools. + +## License + +This project is distributed under the Scala license. +@github[See LICENSE.txt for details](/LICENSE.txt) + + [LibTooling]: https://clang.llvm.org/docs/LibTooling.html diff --git a/docs/src/paradox/limitations/index.md b/docs/src/paradox/limitations/index.md new file mode 100644 index 0000000..e97d9c5 --- /dev/null +++ b/docs/src/paradox/limitations/index.md @@ -0,0 +1,35 @@ +## Limitations + +There are multiple unsupported cases that should be considered when generating bindings: + + 1. Currently bindgen does not support passing structs by value. + For example, it will not be possible to call these two functions from Scala Native code: + + ```c + struct MyStruct { + int a; + }; + + struct MyStruct returnStruct(); + + void handleStruct(struct MyStruct mystr); + ``` + To support such cases one should generate bindings for C wrapper functions that use pointers to structs instead of actual structs. + 2. `#define`s for literals and variables are supported. For other types of `#define`s, + write wrapper functions that return defined values. + + ```c + // Supported + #define ESC 0x1b /* Defines for numerical and string literals. */ + extern const int pi_const; + #define PI pi_const /* Defines aliasing extern variables. */ + + // Not supported (non-exhaustive list) + #define COLS (getenv("COLS") ? atoi(getenv("COLS")) : 80) + #define MAX(a, b) (a > b ? a : b) + ``` + + 3. There is no way to reuse already generated bindings. + Bindgen outputs bindings also for headers that were included in a given header. See @github[#2](#2). + 4. Type qualifiers `const`, `volatile` and `restrict` are not supported. + 5. Extern variables are read-only. See @github[scala-native/scala-native#202](scala-native/scala-native#202). diff --git a/docs/src/paradox/obtaining-bindgen/cmake.md b/docs/src/paradox/obtaining-bindgen/cmake.md new file mode 100644 index 0000000..27384b3 --- /dev/null +++ b/docs/src/paradox/obtaining-bindgen/cmake.md @@ -0,0 +1,54 @@ +# Building with `CMake` + +Building `scala-native-bindgen` requires the following tools and libraries: + + - [CMake] version 3.9 or higher + - [LLVM] and [Clang] version 5.0 or 6.0. + +```sh +# On apt-based systems +apt install cmake clang-$LLVM_VERSION libclang-$LLVM_VERSION-dev llvm-$LLVM_VERSION-dev + +# With `brew` +brew install cmake llvm@6 +``` + +To run the tests you also need the required Scala Native libraries. +See the [Scala Native setup guide] for instructions on installing the dependencies. + +```sh +mkdir -p bindgen/target +cd bindgen/target +cmake .. +make +./scala-native-bindgen --name ctype /usr/include/ctype.h -- +``` + +To build a statically linked executable pass `-DSTATIC_LINKING=ON` when invoking `cmake`: + +```sh +cmake -DSTATIC_LINKING=ON .. +``` + +Additional compiler and linker flags may be passed as environment variable sor their CMake +equivalent, e.g. to compile with debug symbols the following are the same: + +```sh +cmake -DCMAKE_CXX_FLAGS=-g .. +CXXFLAGS=-g cmake .. +``` + +## Testing + +The tests assume that the above instructions for building `scala-native-bindgen` from source +has been followed. + +```sh +cd tests +sbt test +``` + + [CMake]: https://cmake.org/ + [LLVM]: https://llvm.org/ + [Clang]: https://clang.llvm.org/ + [Scala Native setup guide]: http://www.scala-native.org/en/latest/user/setup.html diff --git a/docs/src/paradox/obtaining-bindgen/docker-compose.md b/docs/src/paradox/obtaining-bindgen/docker-compose.md new file mode 100644 index 0000000..4412acc --- /dev/null +++ b/docs/src/paradox/obtaining-bindgen/docker-compose.md @@ -0,0 +1,14 @@ +# Building with `docker-compose` + +You can use [docker-compose] to build and test the program: + +```sh +# Build the docker image with LLVM version 6.0. +docker-compose build ubuntu-18.04-llvm-6.0 +# Build the bindgen tool and run the tests. +docker-compose run --rm ubuntu-18.04-llvm-6.0 ./script/test.sh +# Run the bindgen tool inside the container. +docker-compose run --rm ubuntu-18.04-llvm-6.0 \ + bindgen/target/scala-native-bindgen --name union tests/samples/Union.h -- +``` + [docker-compose]: https://docs.docker.com/compose/ diff --git a/docs/src/paradox/obtaining-bindgen/docker-container.md b/docs/src/paradox/obtaining-bindgen/docker-container.md new file mode 100644 index 0000000..9f9ed8f --- /dev/null +++ b/docs/src/paradox/obtaining-bindgen/docker-container.md @@ -0,0 +1,32 @@ +# Using Docker Container + +This option requires [Docker]. + +Download docker image with the binary: + +```sh +docker pull scalabindgen/scala-native-bindgen +``` + +Mount directories with required header files and run bindgen: + +```sh +docker run -v "$(pwd)":/src -v /usr/include:/usr/include \ + --rm scalabindgen/scala-native-bindgen \ + relative/path/to/my_header.h --name my_header -- +``` + +The docker image does not contain standard headers so it is important to +mount all system include directories that are used by the header file +passed to `scala-native-bindgen`. + +See the [docker-bindgen.sh] script for how to wrap the dockerized program. +The `$CWD` of the container is `/src` which should be mounted from `$(pwd)` +in case relative paths are used. + +Note, the `scalabindgen/scala-native-bindgen:latest` image is updated on +each merge to the `master` branch. + + [Docker]: https://www.docker.com/ + [docker-bindgen.sh]: https://github.com/kornilova-l/scala-native-bindgen/blob/master/scripts/docker-bindgen.sh + \ No newline at end of file diff --git a/docs/src/paradox/obtaining-bindgen/index.md b/docs/src/paradox/obtaining-bindgen/index.md new file mode 100644 index 0000000..9686f48 --- /dev/null +++ b/docs/src/paradox/obtaining-bindgen/index.md @@ -0,0 +1,17 @@ +# Obtaining Bindgen + +@@@ index + +* [Use Docker Container](docker-container.md) +* [Build Binary with CMake](cmake.md) +* [Build Binary with docker-compose](docker-compose.md) + +@@@ + +There are 3 ways to obtain bindgen: + + * @ref:[Use docker container](docker-container.md) + + * @ref:[Build binary with CMake](cmake.md) + + * @ref:[Build binary with docker-compose](docker-compose.md) diff --git a/docs/src/paradox/using-generated-bindings/README.md b/docs/src/paradox/using-generated-bindings/README.md new file mode 100644 index 0000000..073831c --- /dev/null +++ b/docs/src/paradox/using-generated-bindings/README.md @@ -0,0 +1,112 @@ +# Using Generated Bindings + +Consider following header file: + +```c +struct point { + float x; + float y; +}; + +struct vector { + struct point a; + struct point b; +}; + +struct vector *add(struct vector *v1, struct vector *v2); +``` + +Bindgen will generate type aliases for the structs, binding for function `add` +and helper functions that make usage of structs easier. +```scala +import scala.scalanative._ +import scala.scalanative.native._ + +@native.link("mylib") +@native.extern +object mylib { + type struct_point = native.CStruct2[native.CFloat, native.CFloat] + type struct_vector = native.CStruct2[struct_point, struct_point] + def add(v1: native.Ptr[struct_vector], v2: native.Ptr[struct_vector]): native.Ptr[struct_vector] = native.extern +} + +import mylib._ + +object mylibHelpers { + + implicit class struct_point_ops(val p: native.Ptr[struct_point]) extends AnyVal { + def x: native.CFloat = !p._1 + def x_=(value: native.CFloat): Unit = !p._1 = value + def y: native.CFloat = !p._2 + def y_=(value: native.CFloat): Unit = !p._2 = value + } + + def struct_point()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point] + + implicit class struct_vector_ops(val p: native.Ptr[struct_vector]) extends AnyVal { + def a: native.Ptr[struct_point] = p._1 + def a_=(value: native.Ptr[struct_point]): Unit = !p._1 = !value + def b: native.Ptr[struct_point] = p._2 + def b_=(value: native.Ptr[struct_point]): Unit = !p._2 = !value + } + + def struct_vector()(implicit z: native.Zone): native.Ptr[struct_vector] = native.alloc[struct_vector] +} +``` +Let's write code that creates two vectors, adds them and prints resulting +vector. + +First we need to create points for vectors. We will use `native.Zone` to +allocate struct (more information on memory management can be found +here: [Scala Native memory management]). + +Helper object `mylibHelpers` contains function for struct allocation. +To import it use `import mylibHelpers._` + +Let's create points for first vector: +```scala +import mylibHelpers._ +import scala.scalanative.native.Zone + +object Hello extends App { + Zone { implicit zone => + val vec1p1 = struct_point() + val vec1p2 = struct_point() + } +} +``` + +Now we want to set fields of created points. Scala Native provides access +to fields by using `_N` methods where `N` is index of a field +(see [Scala Native memory layout types]). + +Bindgen generates implicit helper classes that wrap calls to `_N` in functions +with meaningful names. We already imported helper class, so we can use the +functions: +```scala +vec1p1.x = 0 +vec1p1.y = 1 + +vec1p2.x = 6 +vec1p2.y = 3 +``` + +Lets create first vector. Note that `struct_vector` contains +fields of type `struct_point` but setters accept variables of type +`native.Ptr[struct_point]`. It helps to avoid Scala Native limitation that +does not allow passing structs and arrays by value +(see @github[scala-native/scala-native#555](scala-native/scala-native#555)). +```scala +val vec1 = struct_vector() +vec1.a = vec1p1 +vec1.b = vec1p2 +``` +Repeat these steps to create second vector. Once both vectors are created we can +call `add` function and print the result: +```scala +val vec3 = mylib.add(vec1, vec2) +println(s"(${vec3.a.x}, ${vec3.a.y}), (${vec3.b.x}, ${vec3.b.y})") +``` + + [Scala Native memory management]: http://www.scala-native.org/en/latest/user/interop.html#memory-management + [Scala Native memory layout types]: http://www.scala-native.org/en/latest/user/interop.html#memory-layout-types diff --git a/project/plugins.sbt b/project/plugins.sbt index afc9d5a..e7f571a 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1,3 @@ addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.3.7") +addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.2") +addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.2")