Skip to content

Commit

Permalink
Adds simple example
Browse files Browse the repository at this point in the history
Signed-off-by: Yauheni Khnykin <[email protected]>
  • Loading branch information
Hsilgos committed Nov 5, 2023
1 parent 9447c95 commit ece6456
Show file tree
Hide file tree
Showing 45 changed files with 1,967 additions and 46 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/functional-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ jobs:
export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools
./scripts/build-android-namerules --publish
working-directory: functional-tests
- name: Build examples
run: |
export ANDROID_HOME=${HOME}/android-sdk-linux
pushd examples/calculator/android
./gradlew build
popd
swift:
name: Swift on Linux
Expand Down Expand Up @@ -221,6 +227,11 @@ jobs:
run: |
./scripts/build-swift-namerules --publish
working-directory: functional-tests
- name: Build examples
run: |
mkdir build_example_calculator
cmake -B build_example_calculator examples/calculator -GXcode -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_SYSTEM_NAME=iOS
cmake --build build_example_calculator
dart:
name: Dart
Expand Down
49 changes: 3 additions & 46 deletions docs/lime_idl.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,54 +25,11 @@ LimeIDL syntax

### Example

This example only shows how syntax looks like, it's not ready to use out of the box.
For working examples check lime files in [functional tests](https://github.com/heremaps/gluecodium/tree/master/functional-tests/functional/input/lime).
Also [cmake tests](https://github.com/heremaps/gluecodium/tree/master/cmake/tests/unit) demonstrate how
to integrate Gluecodium to CMake-based project and how to use it for more complex scenarios when you need
multiple modules which interact with each other.
Start with [examples](../examples/README.md).

```
package com.example
import com.example.utils.GenericResult
class SomeImportantProcessor {
constructor create(options: Options?) throws SomethingWrongException
fun process(mode: Mode, input: String): GenericResult
property processingTime: ProcessorHelperTypes.Timestamp { get }
@Internal
static property secretDelegate: ProcessorDelegate?
enum Mode {
SLOW,
FAST,
CHEAP
}
@Immutable
struct Options {
flagOption: Boolean
uintOption: UShort
additionalOptions: List<String> = {}
}
For more advanced lime examples check [functional tests](https://github.com/heremaps/gluecodium/tree/master/functional-tests/functional/input/lime).

exception SomethingWrongException(String)
}
interface ProcessorDelegate: com.example.utils.GenericDelegate {
fun onProcessorEvent(message: String)
}
struct ProcessorHelperTypes {
typealias Timestamp = Date
const DefaultOptions: SomeImportantProcessor.Options = {flagOption = true, uintOption = 42, {}}
}
```
Also [cmake tests](https://github.com/heremaps/gluecodium/tree/master/cmake/tests/unit) demonstrate how to use CMake scripts for more complex scenarios when you need multiple modules which interact with each other.

### General remarks on syntax

Expand Down
31 changes: 31 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Overview

[README.md](../README.md) in the root provides basic information about Gluecodium.
It's simplier to keep C++ code in shared library when binding is necessary for Java and for Swift.
In examples simpliest configuration is used. For more advanced check `cmake/tests/unit` tests.

## CMake Gluecodium wraper.

This is set of cmake functions which provide the following functionality:
- Download Gluecodium from artifactory.
- Add step to generate code.
- Set options to configure generated code.
- Help to configure a target to include generated C++/Swift/Java/Flutter sources, add include directories, etc.

While examples work with shipped CMake Gluecodium wraper in real application it's handy to clone only subtree `cmake/modules`.

## Example `calculator`.

What this example demonstrates:
- How to configure the project to generate C++, Java and Swift source code.
- How to use the generated code in Android and iOS applications.
- How to describe basic primitives like `class`, `interface`, `struct` and how to interact with them
- How to make platform-only comment and links.

What this example DOESN'T demonstrate:
- How to make complex build setup with several modules.
- How to describe custom types.
- How to make Flutter plugin.
- How to use advanced Gluecodium features: tags, advanced manupulations with comments, properties, etc.

For detailed desription check [calculator/README.md](calculator/README.md)
77 changes: 77 additions & 0 deletions examples/calculator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Copyright (C) 2016-2023 HERE Europe B.V.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# License-Filename: LICENSE

cmake_minimum_required(VERSION 3.12)

project(gluecodium.calculator)

option(ENABLE_APP "Enables iOS app which demostrates how to use the generated code" ON)

set(CMAKE_CXX_STANDARD 17)

if(CMAKE_GENERATOR STREQUAL "Xcode")
enable_language(Swift)
endif()

# Path to Gluecodium CMake wrapper
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../cmake/modules")

include(gluecodium/Gluecodium)

# Android requires C++ code to be built as shared library.
# For iOS it's recommended (but not required) to do Framework because it's consistent
# to Android setup and simplifies CMake scripts and it allows to use framework with
# Xcode projects which are not originated from CMake (for example cocoapods or
# generated by Xcode itself).
add_library(mylibrary SHARED "${CMAKE_CURRENT_LIST_DIR}/cpp/CalculatorImpl.cpp")

# C++ (cpp) generator usually always necessary, android and swift depend on current platform.
set (_generators cpp)
if (ANDROID)
list (APPEND _generators android)
elseif (CMAKE_GENERATOR STREQUAL "Xcode")
list (APPEND _generators swift)
endif()

# Add step to generate sources. Lime files are specified below.
gluecodium_generate(mylibrary GENERATORS ${_generators})

# Gluecodium has plenty options which can be configured with target properties
# prfixed with `GLUECODIUM_`. To learn all the properties configure the project
# with `-DGLUECODIUM_PRINT_KNOWN_PROPERTIES=ON` parameter.
set_target_properties(mylibrary PROPERTIES
# Not required, but highly desired Java annotations.
GLUECODIUM_JAVA_NONNULL_ANNOTATION "androidx.annotation.NonNull"
GLUECODIUM_JAVA_NULLABLE_ANNOTATION "androidx.annotation.Nullable"

# Set prefix for java package.
GLUECODIUM_JAVA_PACKAGE "com")

# This is the most convenient way to add lime files from which Gluecodium generates code.
set_property(TARGET mylibrary APPEND PROPERTY GLUECODIUM_LIME_SOURCES
"${CMAKE_CURRENT_LIST_DIR}/lime/Calculator.lime")

if (CMAKE_GENERATOR STREQUAL "Xcode")
# Make CMake to build framework.
set_target_properties(mylibrary PROPERTIES
FRAMEWORK TRUE
XCODE_ATTRIBUTE_DEFINES_MODULE YES)

if(ENABLE_APP AND IOS)
add_subdirectory("ios")
endif()
endif()
150 changes: 150 additions & 0 deletions examples/calculator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Calculator

This simple application demonstrates how to use basic entities like `struct`, `class`, `interface`, `exception`, `lambda`, `optional values`, `documentation`, `platform-only documentation` and interact between Java, Swift and C++. Flutter is out of this example.

# Requirements

* For Apple: Xcode, CMake the newer the better.
* For Android: CMake, Android SDK, optionally Android Studio

# How to build

## Android

Option 1. Command line

Build and install the app from command line:

```
cd android
./gradlew installDebug
```
Then find "Gluecodium calculator" on our simulator or device and run.

Option 2. IDE

Run Android Studio not older than Giraffe, open directory `android`, press "Run".

## Apple
First of all Xcode solution must be configured with CMake

Generated code and implementation for interfaces are built as framework. For iOS there is also test application which uses this framework.

Create directory and `cd` there. There are many options to configure solution for Xcode:
```
# iOS, simulator, M1
cmake path/to/example -GXcode -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_SYSTEM_NAME=iOS
# iOS, simulator, Intel
cmake path/to/example -GXcode -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_SYSTEM_NAME=iOS
# iOS, simulator, both M1 and Intel (i.e. lipoed)
cmake path/to/example -GXcode -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_SYSTEM_NAME=iOS
# iOS, device
cmake path/to/example -GXcode -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_SYSTEM_NAME=iOS
# MacOS. Only framework will be built, without test application.
cmake path/to/example -GXcode
```
Optionally parameter `-DENABLE_APP=OFF` can be passed to skip building the test application. In this case only framework is built which can be used in another existing Xcode project.

To build framework from console:
```
# Build debug
cmake --build . --target mylibrary
# Build release
cmake --build . --target mylibrary --config Release
```

Test application is easier to build from Xcode. Open Xcode, opern generated project, click "Run" button.

# Highlights

## CMake

File [CMakeLists.txt](CMakeLists.txt) describes library and adds compilation step to generate code with Gluecodium.

Path to gluecodium cmake files must be specified before including gluecodium cmake files. In examples it's hardcoded, but can be specified outside:
```
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../cmake/modules")
```

Gluecodium options can be configured with target properties preficed with `GLUECODIUM_`. To learn all the properties configure the project with `-DGLUECODIUM_PRINT_KNOWN_PROPERTIES=ON` parameter.

The most convenient way to add lime files is to append them to `GLUECODIUM_LIME_SOURCES` property:
```
set_property(TARGET target APPEND PROPERTY GLUECODIUM_LIME_SOURCES
"path/to/file1.lime"
"path/to/file2.lime")
```

## Lime file

File [lime/Calculator.lime](lime/Calculator.lime) describes entities to be generated by Gluecoium. Syntax should look like very simplified Kotlin or Swift. Text which begins with `#` is local comment and not processed by Gluecodium somehow special. Text which begins with `//` is official documentation and Gluecodium uses it to generate Javadoc/Jazzy/Doxygen compatible documentation for related generated code. Check the lime file for more detailed description for used entites.

For simplification everything is described in single file, but it's possible to use as many lime files. In case when type from different package is referenced then either fully qualified name or `import` should be used.

Only simple subset of features are used, for more please refer to Gluecodium documentation.

## Android sources

Major part of android sources are generated automatically by Android Studio when simple project for this example was created. The most significant changes are the following:

Gradle build script [android/app/build.gradle](android/app/build.gradle). It specifies path to folder to generate code using CMake variable `GLUECODIUM_BASE_OUTPUT_DIR_DEFAULT`:
```
externalNativeBuild {
cmake {
// Put generated sources outside of default build directory because Android Gradle Plugin
// makes build directory for C++ using some unpredictable random-like path.
// Generated Java sources should be added to `sourceSet` below, so it's better to specify
// and know where code is generated.
arguments "-DGLUECODIUM_BASE_OUTPUT_DIR_DEFAULT=${project.buildDir}/generated/gluecodium"
}
}
```

Below directories with generated sources are added to Java source set. Note that this is based on the directory which is specified with `GLUECODIUM_BASE_OUTPUT_DIR_DEFAULT` and C++ target name:
```
sourceSets {
main {
// Add generated Java code.
java.srcDirs += ["${project.buildDir}/generated/gluecodium/mylibrary/android-cpp/common/android",
"${project.buildDir}/generated/gluecodium/mylibrary/android-cpp/main/android"]
}
}
```

Relative path to [CMakeLists.txt](CMakeLists.txt) is specified:
```
externalNativeBuild {
cmake {
// Path to root `CMakeLists.txt`
path file('../../CMakeLists.txt')
version '3.22.1+'
}
}
```

And finally it's necessary to compile Java code only after C++ is compiled (and Java sources are generated):
```
tasks.configureEach { task ->
// Java compilation depends on .java created by Gluecodium,
// so depend Java compilation task on build C++ task.
if (task.name == 'javaPreCompileDebug') {
task.dependsOn 'externalNativeBuildDebug'
}
if (task.name == 'javaPreCompileRelease') {
task.dependsOn 'externalNativeBuildRelease'
}
}
```

Usage of generated code is in [android/app/src/main/java/com/gluecodium/calculator/MainActivity.java](android/app/src/main/java/com/gluecodium/calculator/MainActivity.java)

## iOS

Optional CMake file [ios/CMakeLists.txt](ios/CMakeLists.txt) describes simple iOS application. It's optional because the framework which is built in the root file [CMakeLists.txt](CMakeLists.txt) can be used in Xcode project which is created by Xcode itself or by for example `cocoapods`. There is nothing specific for Gluecodium.

Usage of generated code is in [ios/ContentView.swift](ios/ContentView.swift).
15 changes: 15 additions & 0 deletions examples/calculator/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
1 change: 1 addition & 0 deletions examples/calculator/android/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
Loading

0 comments on commit ece6456

Please sign in to comment.