Djinni Library  2.0.0
Cross-Platform Library
Development

Build Requirements

Build Tools

Documentation Generation

Android (Java)

  • Java 11
  • Android SDK

Windows (C++/CLI)

Building & Testing

There are multiple ways on how to build & test the library during development:

First, make sure to check out all submodules: git submodule update --init.

With Conan

  • Install Dependencies with Conan: conan install --profile:build=default --profile:host=debug --install-folder=build .
  • Configure, Build and Test: conan build --build-folder=build .

With CMake

  • Install Dependencies with Conan: conan install --profile:build=default --profile:host=debug --install-folder=build .
  • Provide the toolchain generated by Conan when configuring cmake: cmake -B build --toolchain conan_toolchain.cmake
  • Build: cmake --build build
  • Test: ctest --test-dir build

With CLion

  • Install the Conan Plugin
  • Configure the build & host profiles:
    Preferences > Build, Execution, Deployment > Conan:
    Install args: --build=missing --profile:build=default --profile:host=debug
  • Configure the CMake toolchain:
    Preferences > Build, Execution, Deployment > CMake:
    CMake options: --toolchain conan_toolchain.cmake
  • Build & Configure
  • Test: Execute MyDjinniLibraryTest target.

Packaging

The build.py CLI helps you to easily build & package the library for usage in another language, without having to know what is going on under the hood.

For details on what the various parameters of the CLI do, please consult ./build.py --help.

All build outputs generated by build.py will be written to ./build/ by default. You can overwrite the build directory with the --build-directory parameter.

Before running build.py for the first time, install the Python dependencies:

pip3 install -r requirements.txt

Android AAR

When building for Android, Java 11 is required. The environment variable ANDROID_SDK_ROOT must be set to the Android SDK directory.

./build.py --android x86 armv8 --package aar

Output: build/android/package/MyDjinniLibrary.aar

The result is an Android Library (AAR) that contains both the Java-Gluecode required to call the native Library and the binaries for both x86 (for the emulator) & arm64-v8a (for the real hardware) architectures.

XCFramework for iOS/macOS

All binaries for iOS/macOS will be combined into one big XCFramework, for easy referencing in any Swift/Objective-C project. Note that for iOS two different platforms need to be targeted: The simulator and the real iPhone hardware:

./build.py --iphoneos armv8 --iphonesimulator x86_64 armv8 --macos x86_64 armv8 --package xcframework

Output: build/darwin/package/MyDjinniLibrary.xcframework

The result is a XCFramework that contains binaries for

  • real iPhones (iOS)
  • the iPhone Simulator (iOS) for both Intel & Apple silicon (ARM) architectures.
  • macOS for both Intel & Apple silicon (ARM) architectures.

.NET 6 NuGet package

./build.py --windows x86_64 x86 armv8 --package nuget

Output: build/windows/package/MyDjinniLibrary.<version>.nupkg

The result is a NuGet package that contains binaries for 3 different architectures (x86_64, x86 and arm64). The NuGet package makes it easy for you to include the library in a .NET 6 project without having to worry about what dll to include for which architecture in the build process.

Test

The library comes preconfigured for Unit-Testing with Catch2:

  • Commandline: To run just the unit-tests, you can run conan build --build-folder=build --test ..
  • CLion: Execute the MyDjinniLibraryTest target.

Debugging

Prerequisite: The sourcecode of djinni-library-template in the version that you want to debug must be available somewhere on your system.

Android (AAR)

The debug build of the library contains native debug symbols. When Android Studio is configured correctly, they can be used to debug the C++ code:

  • In Android Studio:
    • Run > Edit Configurations…
    • In the "Run/Debug Configurations" Window: Select "app" target.
    • In Tab "Debugger":
      • "Debug type": Dual (Java + Native)
      • "Symbol Directories": Add the path to the root of the djinni-library-template repository in the local filesystem

Now open the (external) C++ source file that you want to debug in Android Studio. Set the breakpoint where you want to step into the native code.

Limitation: You can only debug C++ code starting from breakpoints in the C++ code. It is not possible to step into native code from a breakpoint in Java/Kotlin code!

iOS/macOS

The debug build of the library contains native debug symbols with hardcoded paths to where the sourcefiles have been located on the system that the library was compiled on. Those have to be manually mapped to the real location of the sourcefiles on the system in lldb:

  1. Start a debugging session of your program.
  2. Open the lldb CLI in XCode.
  3. Figure out the paths that have been hardcoded into the debug symbols:
    (lldb) image lookup -va "My::DjinniLibrary::Native::hello_from_native"
    This outputs a bunch of information about the given function, including the absolute path to the CompileUnit that it comes from.
  4. With that information, you can create a mapping of the hardcoded base path to the location of the sources on your system:
    (lldb) settings set target.source-map /BuildDirectory/sources/djinni-library-template /Users/ME/djinni-library-template

Windows (NuGet)

The debug build NuGet package contains .pdb files for the C++ code. The file paths in the program database are pointing to the absolute location of the source files on the build machine.

They must be mapped to the real location of the files in Visual Studio:

  1. Select the solution in Solution Explorer, right-click and select Properties.
  2. Select Debug Source Files.
  3. Under "Directories containing source code" add the path to the sources, e.g. C:\Path\to\djinni-library-template

Documentation

The repository comes with 4 different Doxygen configurations, each is for a different target language:

  • Doxyfile-Cpp: Documents the C++ interfaces that will be exposed for all the languages. They can also be used directly in a C++ project, e.g. for targeting Linux with gtkmm.
  • Doxyfile-CppCli: Documents the C++/CLI gluecode for targeting Windows .NET 5
  • Doxyfile-Java: Documents the Java gluecode for targeting Android
  • Doxyfile-ObjC: Documents the Objective-C gluecode for targeting iOS/macOS

All Doxyfiles depend on code generated by Djinni. Make sure that the library was built at least once before running Doxygen.

doxygen Doxyfile-Cpp
doxygen Doxyfile-CppCli
doxygen Doxyfile-Java
doxygen Doxyfile-ObjC

The resulting documentation can be found under docs/generated/html.

Project Structure

.
├── CMakeLists.txt : Root `CMakeLists.txt`. Includes Library sources and unit tests.
├── Doxyfile-Cpp : Doxyfile for the C++ interface that is generated with Djinni from `my_djinni_library.djinni`.
├── Doxyfile-CppCli : Doxyfile for the generated C++/CLI interface.
├── Doxyfile-Java : Doxyfile for the generated Java interface.
├── Doxyfile-ObjC : Doxyfile for the generated Objective-C interface.
├── LICENSE : License file.
├── README.md : The document that you read right now.
├── build.py : Build script that automates building & packaging the binaries for all the supported platforms.
├── cmake
│ └── modules
│ ├── GetVersion.cmake : CMake module that reads the current project version from a temporary `VERSION` file that
│ │ is created by Conan during the install phase or from the git repository if no `VERSION` file can be found.
│ └── djinni-cmake : CMake module that introduces the `add_djinni_library` function to configure the Djinni library.
│ └── ...
├── conan
│ └── profiles : Folder containing Conan profiles for all supported target platforms (`android`, `ios`, `macos`, `windows`).
│ └── ... These profiles are used by `build.py` () to configure the CMake targets accordingly.
├── conanfile.py : Conanfile for installing dependencies & defining the library itself as Conan package.
├── docs
│ ├── doxygen-awesome-css : Submodule of the `doxygen-awesome-css` doxygen theme.
│ │ └── ...
│ ├── doxygen-custom : Doxygen customization (CSS & html)
│ │ └── ...
│ ├── generated
│ │ └── html : Folder that Doxygen will write the generated html documentation to.
│ │ └── ... Each target language is documented in a sub-folder in an entirely separate doxygen Website.
│ ├── idl.dox : Doxygen page that includes the Djinni IDL file used to generate the documented interfaces.
│ └── img : Image resources for Doxygen
│ └── ...
├── lib : Folder containing library sources.
│ ├── CMakeLists.txt : `CMakeLists.txt` that defines the library target and links it to the djinni-support-lib
│ ├── djinni-generated : The djinni generator will write the generated interfaces for each language into this folder.
│ │ └── ...
│ ├── my_djinni_library.djinni : Djinni interface definition language file that defines the libraries interface.
│ ├── platform
│ │ ├── android
│ │ │ ├── CMakeLists.txt : CMake project to generate & build Java & JNI gluecode for Android
│ │ │ └── package : Android Studio project that is used to build the Android Library (AAR).
│ │ │ └── ... `build.py` copies the directory to the build folder, populates it with the compiled C++
│ │ │ libraries and then builds the AAR with gradle.
│ │ ├── darwin
│ │ │ ├── CMakeLists.txt : CMake project to generate & build Objective-C gluecode for macOS/iOS
│ │ │ └── package : folder containing template for swift package
│ │ │ └── Package.swift
│ │ ├── linux
│ │ │ └── CMakeLists.txt
│ │ └── windows : NuGet package structure that is used by `build.py` to package the .NET 6 NuGet package.
│ │ ├── CMakeLists.txt
│ │ └── package : Nupkg template including nuspec that is populated with the project version defined in `conanfile.py`.
│ │ └── MyDjinniLibrary.nuspec
│ └── ...
├── requirements.txt : Python dependencies required to run build.py
└── test : Folder containing the library unit tests.
├── CMakeLists.txt : `CMakeLists.txt` that configures the Unit tests with Catch2.
└── ...

Read Next: Interface Definition