Skip to content
Draft
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
1 change: 1 addition & 0 deletions .bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8.4.0
34 changes: 34 additions & 0 deletions .github/workflows/bazel-build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: build bazel

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

jobs:
build:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
# - windows-latest
steps:
- uses: bazel-contrib/[email protected]
with:
bazelisk-cache: true
disk-cache: ${{ github.workflow }}
external-cache: true

- name: Checkout repository
uses: actions/checkout@v4

- name: Build (fastbuild)
run: bazel build //...

- name: Test (fastbuild)
run: bazel test //...
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ ztest/
# OS specific
.DS_Store


bazel-bin
bazel-djinni-generator
bazel-out
bazel-testlogs
23 changes: 23 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
load("@rules_scala//scala:scala.bzl", "scala_binary", "scala_test")

scala_binary(
name = "djinni",
srcs = glob(["src/main/scala/**/*.scala"]),
main_class = "djinni.Main",
resources = glob(["src/main/resources/**"]),
visibility = ["//visibility:public"],
deps = [
"@maven//:com_github_scopt_scopt_2_12",
"@maven//:commons_io_commons_io",
"@maven//:org_scala_lang_modules_scala_parser_combinators_2_12",
"@maven//:org_yaml_snakeyaml",
],
)

scala_test(
name = "test",
srcs = glob(["src/it/scala/djinni/**/*.scala"]),
data = glob(["src/it/resources/**"]),
deps = [":djinni"],
timeout="short",
)
67 changes: 67 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""Djinni generator - Cross-language bindings generator for C++, Java, Objective-C"""

module(
name = "djinni-generator",
version = "1.4.1",
)

# MODULE.bazel

bazel_dep(name = "rules_scala", version = "7.1.2")

# Selects the Scala version and other configuration parameters.
#
# 2.12 is the default version. Use other versions by passing them explicitly, as
# illustrated below.
#
# See the documentation of `_settings_attrs` in `scala/extensions/config.bzl`
# for other available parameters.
#
# You may define your own custom toolchain using Maven artifact dependencies
# configured by your `WORKSPACE` file, imported using an external loader like
# https://github.com/bazelbuild/rules_jvm_external. See docs/scala_toolchain.md.
scala_config = use_extension(
"@rules_scala//scala/extensions:config.bzl",
"scala_config",
)
scala_config.settings(scala_version = "2.12.20")

# See the `scala/extensions/deps.bzl` docstring for a high level description of
# the tag classes exported by this module extension.
scala_deps = use_extension(
"@rules_scala//scala/extensions:deps.bzl",
"scala_deps",
)

# Defines a default toolchain repo for the configured Scala version that loads
# Maven deps like the Scala compiler and standard libs. Enable and configure
# other builtin toolchains by instantiating their corresponding tag classes.
# See the documentation in `scala/extensions/deps.bzl` for all builtin
# toolchain configuration options.
#
# On production projects, you may consider defining a custom toolchain to use
# your project's required dependencies instead. In that case, you can omit using
# the module extension and this next line altogether. Or, you can still use the
# module extension to instantiate other optional `rules_scala` toolchains
# without it.
scala_deps.scala()
scala_deps.scalatest()

# Add Maven dependencies for djinni
bazel_dep(name = "rules_jvm_external", version = "6.4")

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"org.scala-lang.modules:scala-parser-combinators_2.12:2.1.0",
"org.yaml:snakeyaml:1.29",
"com.github.scopt:scopt_2.12:4.0.1",
"commons-io:commons-io:2.11.0",
"org.scalactic:scalactic_2.12:3.2.10",
"org.scalatest:scalatest_2.12:3.2.10",
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
use_repo(maven, "maven")
1,292 changes: 1,292 additions & 0 deletions MODULE.bazel.lock

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@ Djinni generator parses an interface definition file and generates:
- C++ implementations of types (enums, records)
- Java implementations of types
- Objective-C implementations of types
- Python implementation of types
- C++/CLI implementation of types
- C++ code to convert between C++ and Java over JNI
- C++ code to serialize/deserialize types to/from JSON
- Objective-C++ code to convert between C++ and Objective-C
- Python and C code to convert between C++ and Python over CFFI
- C++/CLI code to convert between C++ and C#


## Installation
Expand Down
15 changes: 15 additions & 0 deletions REPO.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Repository configuration for djinni-generator"""

# Repository boundary - mark directories to ignore
ignored_directories = [
"target",
"project/target",
"project/project/target",
".bloop",
".bsp",
".metals",
".vscode",
".idea",
".cache",
"test/result",
]
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import sbtassembly.AssemblyPlugin.defaultUniversalScript

ThisBuild / scalaVersion := "2.12.18"
ThisBuild / scalaVersion := "2.12.20"
ThisBuild / organization := "com.github.cross-language-cpp"

ThisBuild / semanticdbEnabled := true // enable SemanticDB
ThisBuild / semanticdbVersion := scalafixSemanticdb.revision // use Scalafix compatible version
ThisBuild / semanticdbVersion := "4.13.10" // latest available version

// Keep this as a reminder, we will use that later
// ThisBuild / scalacOptions += "-Ywarn-unused"
Expand Down
56 changes: 3 additions & 53 deletions docs/cli-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ djinni \
\
--objcpp-out OBJC_OUTPUT_FOLDER \
\
--py-out PYTHON_OUTPUT_FOLDER \
--pycffi-out CFFI_OUTPUT_FOLDER \ # Required for Python support
--pycffi-package-name PyCFFIlib \
--pycffi-dynamic-lib-list mylib \
--c-wrapper-out C_WRAPPER_OUTPUT_FOLDER \ # Required for Python support
\
--idl MY_PROJECT.djinni

```
Expand Down Expand Up @@ -118,32 +112,10 @@ djinni \
| `--objc-extended-record-include-prefix <prefix>` | The prefix path for `#import` of the extended record Objective-C header (`.h`) files |
| `--objcpp-namespace <prefix>` | The namespace name to use for generated Objective-C++ classes. |

### Python

| Argument | Description |
|--------------------------------------|-------------------------------------------------------------------------|
| `--py-out <out-folder>` | The output folder for Python files (Generator disabled if unspecified). |
| `--pycffi-out <out-folder>` | The output folder for PyCFFI files (Generator disabled if unspecified). |
| `--pycffi-package-name ...` | The package name to use for the generated PyCFFI classes. |
| `--pycffi-dynamic-lib-list ...` | The names of the dynamic libraries to be linked with PyCFFI. |
| `--py-import-prefix <import-prefix>` | The import prefix used within python generated files (default: "") |

### C wrapper

| Argument | Description |
|-------------------------------------------|----------------------------------------------------------------------------------------|
| `--c-wrapper-out <out-folder>` | The output folder for C wrapper files (Generator disabled if unspecified). |
| `--c-wrapper-header-out <out-folder>` | The output folder for C wrapper header files (default: the same as `--c-wrapper-out`). |
| `--c-wrapper-include-prefix <prefix>` | The prefix for #includes of C wrapper header files from C wrapper C++ files. |
| `--c-wrapper-include-cpp-prefix <prefix>` | The prefix for #includes of C++ header files from C wrapper C++ files. |

### C++/CLI

| Argument | Description |
|----------------------------------------|----------------------------------------------------------------------------|
| `--cppcli-out <out-folder>` | The output folder for C++/CLI files (Generator disabled if unspecified). |
| `--cppcli-namespace ...` | The namespace name to use for generated C++/CLI classes. |
| `--cppcli-include-cpp-prefix <prefix>` | The prefix for `#include` of the main C++ header files from C++/CLI files. |


### Yaml Generation
Expand Down Expand Up @@ -204,31 +176,9 @@ Possible values: `FooBar`, `fooBar`, `foo_bar`, `FOO_BAR`, `m_fooBar`.
| `--ident-objc-local` | `fooBar` |
| `--ident-objc-file` | `FooBar` |

#### Python

| Argument | Default |
|-------------------------|-----------|
| `--ident-py-type` | `foo_bar` |
| `--ident-py-class-name` | `FooBar` |
| `--ident-py-type-param` | `foo_bar` |
| `--ident-py-method` | `foo_bar` |
| `--ident-py-field` | `foo_bar` |
| `--ident-py-local` | `foo_bar` |
| `--ident-py-enum` | `Foo_Bar` |
| `--ident-py-const` | `FOO_BAR` |

#### C++/CLI

| Argument | Default |
|-----------------------------|----------|
| `--ident-cppcli-type` | `FooBar` |
| `--ident-cppcli-type-param` | `FooBar` |
| `--ident-cppcli-property` | `FooBar` |
| `--ident-cppcli-method` | `FooBar` |
| `--ident-cppcli-local` | `fooBar` |
| `--ident-cppcli-enum` | `FooBar` |
| `--ident-cppcli-const` | `FooBar` |
| `--ident-cppcli-file` | `FooBar` |




Example:

Expand Down
6 changes: 1 addition & 5 deletions docs/developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ sbt "run
--cpp-out out/cpp
--java-out out/java/src
--jni-out out/java/jni
--objc-out out/objc
--py-out out/python
--pycffi-out out/cffi
--c-wrapper-out out/cwrapper
--cppcli-out out/cppcli"
--objc-out out/objc"
```

```bash
Expand Down
84 changes: 0 additions & 84 deletions docs/generated-code-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,93 +78,9 @@ Add all generated files to your build target, and link against the [djinni-suppo
Note that `+Private` files can only be used with ObjC++ source (other headers are pure ObjC) and are not required by Objective-C users of your interface.


## Python / C++ Project (Experimental)

Python support in Djinni is experimental, but ready to try out. It can generate code for bridging
C++ with Python 3.

For more information, you can check out the talk from CppCon 2015.
[Slides](https://bit.ly/djinnitalk2) and [video](https://bit.ly/djinnivideo2) are available online.

### Includes & Build Target

When bridging to Python, Djinni generates 4 types of output:

* `python` Generated Python classes and proxies for interacting with C++ via [CFFI](https://cffi.readthedocs.org/).
* `cffi` Python code run at build time to create a Python extension out of the C++ code.
* `cwrapper` A C interface implemented in C++ to allowing Python to interact with C++ classes.
* `cpp` The same C++ classes generated for all other Djinni languages.

Generated files for Python / C++ are as follows:

| Type | C++ header | C++ source | Python files | CFFI | C Wrapper |
|------------|----------------------------|------------------------------|---------------------|---------------------|----------------------|
| Enum/Flags | my\_enum.hpp | | my_enum.py | | dh__my_enum.cpp |
| | my\_enum+json.hpp :two: | | | | dh__my_enum.h |
| | | | | | dh__my_enum.hpp |
| Record | my\_record[\_base].hpp | my\_record[\_base].cpp :one: | my_record[_base].py | | dh__my_record.cpp |
| | my\_record[\_base]+json.hpp| | | | dh__my_record.h |
| | :two:| | | | dh__my_record.hpp |
| Interface | my\_interface.hpp | my\_interface.cpp :one: | my_interface.py | pycffi_lib_build.py | cw__my_interface.cpp |
| | | | | | cw__my_interface.h |
| | | | | | cw__my_interface.hpp |

- :one: Generated only for types that contain constants.
- :two: Generated only if cpp json serialization is enabled.

Additional C Wrapper files are generated for data structures; their names are encoded as:

dh__{list,set,map}_{encoded_type(s)}.cpp
dh__{list,set,map}_{encoded_type(s)}.h
dh__{list,set,map}_{encoded_type(s)}.hpp

See the in the table below a few examples:

| Type | C Wrapper |
|-------------------------|----------------------------------------|
| `list<i32>` | dh__list_int32_t.{cpp,h,hpp} |
| `set<string>` | dh__set_string.{cpp,h,hpp} |
| `map<i32, set<string>>` | dh__map_int32_t_set_string.{cpp,h,hpp} |

Add all generated C and C++ source files to your build target, and link it against the
[djinni-support-lib](https://github.com/cross-language-cpp/djinni-support-lib).

Compile the Python extension module (CFFI) by executing `pycffi_lib_build.py` while providing all C
Wrapper header files (`.h`) as arguments. The resulting shared library will enable Python to access
your C++ library through the CFFI bridge.

### Known limitations of the generator

* External types defined in YAML are not yet supported.
* Use of non-nullable pointers is not yet supported.


## C++/CLI / C++ Project

C++/CLI is a technology by Microsoft that provides interoperability of C++ with Microsoft .NET languages such as C#.
It is only supported on Windows.

Djinni generates a shallow C++/CLI wrapper around the C++ interfaces. Once compiled to a shared library, the resulting `dll`
just needs to be added to your C# project as reference, and you can call your Djinni interfaces from C# like any other .NET library.

### Includes & Build target

The following code will be generated for each defined type:

| Type | C++ header | C++ source | C++/CLI header/sources |
|------------|--------------------------|----------------------------|-------------------------------------|
| Enum/Flags | my\_enum.hpp | | MyEnum.hpp, MyEnum.cpp |
| | my\_enum+json.hpp :two: | | |
| Record | my\_record.hpp | my\_record.cpp | MyRecord.hpp, MyRecord.cpp |
| | my\_record+json.hpp :two:| | |
| Interface | my\_interface.hpp | my\_interface.cpp :one: | MyInterface.hpp, MyInterface.cpp |

- :one: Generated only for types that contain constants.
- :two: Generated only if cpp json serialization is enabled.

Add all generated files to your build target, and link against the [djinni-support-lib](https://github.com/cross-language-cpp/djinni-support-lib).

C++/CLI sources have to be compiled with MSVC and the [`/clr` (Common Language Runtime Compilation)](https://docs.microsoft.com/en-us/cpp/build/reference/clr-common-language-runtime-compilation?view=msvc-160) option.

## C++ JSON Serialization support

Expand Down
Loading