Skip to content

Commit

Permalink
Add the initial skeleton of Matter Controller Java CLI App (#23048)
Browse files Browse the repository at this point in the history
* Add initial skeleton of Java Controller App

* Add build target for java_matter_controller

* Update comments for java_binary template
  • Loading branch information
yufengwangca authored and pull[bot] committed Oct 13, 2023
1 parent 43c5792 commit 1310186
Show file tree
Hide file tree
Showing 14 changed files with 557 additions and 33 deletions.
176 changes: 175 additions & 1 deletion build/chip/java/rules.gni
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ template("java_library") {
_data_deps = invoker.data_deps
}

# Generates a .java file containing all sources to be compiled
# Generates a .sources file containing all sources to be compiled
_java_sources_file = "$target_gen_dir/$target_name.sources"
if (defined(invoker.java_sources_file)) {
_java_sources_file = invoker.java_sources_file
Expand Down Expand Up @@ -176,6 +176,162 @@ template("java_library") {
}
}

# Declare a Java executable target
#
# Manifext.txt: contains the given class as the entrypoint about the files packaged in a Java executable target.
#
# sources: List of .java files included in this binary. Mutually exclusive with jar_path.
#
# jar_path: A path to an existing JAR. Mutually exclusive with sources.
#
# output_name: File name for the output binary under root_build_dir/bin.
#
# javac_flags: additional flags to pass to the javac compiler
#
template("java_binary") {
# Figure out the output name
_jar_name = target_name
if (defined(invoker.output_name)) {
_jar_name = invoker.output_name
} else {
_jar_name += ".jar"
}

_deps = []
if (defined(invoker.deps)) {
_deps = invoker.deps
}

# What files will be compiled
_java_files = []
if (defined(invoker.sources)) {
_java_files = invoker.sources
}

_is_prebuilt = defined(invoker.jar_path)

_jar_output = ""
_target_dir_name = get_label_info(":$target_name", "dir")
if (_is_prebuilt) {
assert(_java_files == [])
_jar_output = "$root_out_dir/bin/$_target_dir_name/" +
get_path_info(invoker.jar_path, "name") + ".jar"
} else {
_jar_output = "$root_out_dir/bin/$_target_dir_name/$_jar_name"
}

# Generate a list containing the expected build_config filepath of every dependency.
_deps_configs = []
foreach(_dep, _deps) {
_dep_gen_dir = get_label_info(_dep, "target_gen_dir")
_dep_name = get_label_info(_dep, "name")
_dep_config = "$_dep_gen_dir/$_dep_name.json"
_deps_configs += [ _dep_config ]
}
_rebased_deps_configs = rebase_path(_deps_configs, root_build_dir)

# Create the name for this target's build_config.
_library_target_name = target_name
_build_config = "$target_gen_dir/$_library_target_name.json"
_rebased_build_config = rebase_path(_build_config, root_build_dir)

# Write the build_config file for this target.
_config_target_name = target_name + "_config"
action(_config_target_name) {
script = write_build_config

deps = _deps

outputs = [ _build_config ]
args = [
"--jar-path",
rebase_path(_jar_output, root_build_dir),
"--build-config",
_rebased_build_config,
"--deps-configs=$_rebased_deps_configs",
]
}

# Building from sources - perform Java compilation and JAR creation.
if (!_is_prebuilt) {
# Additional flags
_javac_flags = [
"-Werror",
"-Xlint:all",
]
if (defined(invoker.javac_flags)) {
_javac_flags += invoker.javac_flags
}

# Data deps
_data_deps = []
if (defined(invoker.data_deps)) {
_data_deps = invoker.data_deps
}

# Generates a .sources file containing all sources to be compiled
_java_sources_file = "$target_gen_dir/$target_name.sources"
if (defined(invoker.java_sources_file)) {
_java_sources_file = invoker.java_sources_file
}
write_file(_java_sources_file, rebase_path(_java_files, root_build_dir))

# Compiles the given files into a directory and generates a 'class list'
_javac_target_name = target_name + "__javac"
_class_dir = rebase_path(target_out_dir, root_build_dir) + "/classes"
_class_list_file = "$target_gen_dir/$target_name.classlist"
action(_javac_target_name) {
sources = _java_files
deps = [ ":$_config_target_name" ]

outputs = [ _class_list_file ]

script = javac_runner

args = [
"--classdir",
_class_dir,
"--outfile",
rebase_path(_class_list_file, root_build_dir),
"--build-config",
_rebased_build_config,
"--",
"-d",
_class_dir,
"@" + rebase_path(_java_sources_file, root_build_dir),
] + _javac_flags
}

# Bundles all files within the 'class directory' into a jar file
action(target_name) {
deps = [ ":$_javac_target_name" ] + _deps

data_deps = _data_deps

outputs = [ _jar_output ]

script = jar_runner

args = [
"cfm",
rebase_path(_jar_output, root_build_dir),
"Manifest.txt",
"-C",
_class_dir,
".",
]
}
} else {
# Using pre-specified JAR instead of building from sources - simply copy the JAR to the output directory.
_original_jar_path = invoker.jar_path
copy(target_name) {
sources = [ _original_jar_path ]
outputs = [ _jar_output ]
deps = [ ":$_config_target_name" ] + _deps
}
}
}

template("android_library") {
java_library(target_name) {
forward_variables_from(invoker, "*")
Expand All @@ -194,6 +350,24 @@ template("android_library") {
}
}

template("android_binary") {
java_binary(target_name) {
forward_variables_from(invoker, "*")

if (!defined(javac_flags)) {
javac_flags = []
}

javac_flags += [
"-Xlint:-options",
"-source",
"8",
"-target",
"8",
]
}
}

template("java_prebuilt") {
java_library(target_name) {
forward_variables_from(invoker, "*")
Expand Down
20 changes: 20 additions & 0 deletions examples/java-matter-controller/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
*.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

# Shared libs & JAR libs (those libs are copied into source tree for easy Android build).
*.so
*.jar
*.map
25 changes: 25 additions & 0 deletions examples/java-matter-controller/.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) 2020-2022 Project CHIP Authors
#
# 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.

import("//build_overrides/build.gni")

# The location of the build configuration file.
buildconfig = "${build_root}/config/BUILDCONFIG.gn"

# CHIP uses angle bracket includes.
check_system_includes = true

default_args = {
import("//args.gni")
}
43 changes: 43 additions & 0 deletions examples/java-matter-controller/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright (c) 2022 Project CHIP Authors
#
# 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.

import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")

import("${build_root}/config/android_abi.gni")
import("${chip_root}/build/chip/java/rules.gni")
import("${chip_root}/build/chip/tools.gni")

android_binary("java-matter-controller") {
output_name = "java-matter-controller"

deps = [
":android",
"${chip_root}/src/controller/java",
"${chip_root}/src/setup_payload/java",
"${chip_root}/third_party/android_deps:annotation",
]

sources = [ "java/src/com/matter/controller/Main.java" ]

javac_flags = [ "-Xlint:deprecation" ]
}

java_prebuilt("android") {
jar_path = "${android_sdk_root}/platforms/android-21/android.jar"
}

group("default") {
deps = [ ":java-matter-controller" ]
}
2 changes: 2 additions & 0 deletions examples/java-matter-controller/Manifest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Main-Class: com.matter.controller.Main

67 changes: 67 additions & 0 deletions examples/java-matter-controller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Matter Controller Java App Example

This is a Matter Controller Java app that can be used to uses Matter to send
messages to a Matter server.

<hr>

- [Matter Controller Java App Example](#matter-controller-java-app-example)
- [Requirements for building](#requirements-for-building)
- [Gradle & JDK Version](#gradle--jdk-version)
- [Preparing for build](#preparing-for-build)
- [Building & Running the app](#building--running-the-app)

<hr>

<a name="requirements"></a>

## Requirements for building

You need Android SDK 21 & NDK downloaded to your machine. Set the
`$ANDROID_HOME` environment variable to where the SDK is downloaded and the
`$ANDROID_NDK_HOME` environment variable to point to where the NDK package is
downloaded.

<a name="jdk"></a>

### Gradle & JDK Version

We are using Gradle 7.1.1 for all android project which does not support Java 17
(https://docs.gradle.org/current/userguide/compatibility.html) while the default
JDK version on MacOS for Apple Silicon is 'openjdk 17.0.1' or above.

Using JDK bundled with Android Studio will help with that.

```shell
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jre/Contents/Home/
```

<hr>

<a name="preparing"></a>

## Preparing for build

Complete the following steps to prepare the Matter build:

1. Check out the Matter repository.

2. Run bootstrap (**only required first time**)

```shell
source scripts/bootstrap.sh
```

<a name="building-running"></a>

## Building & Running the app

This is the simplest option. In the command line, run the following command from
the top Matter directory:

```shell
./scripts/build/build_examples.py --target android-x86-java-matter-controller build
```

The Java executable file `java-matter-controller` will be generated at
`out/android-x86-java-matter-controller/bin/`
25 changes: 25 additions & 0 deletions examples/java-matter-controller/args.gni
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) 2020-2022 Project CHIP Authors
#
# 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.

import("//build_overrides/chip.gni")

import("${chip_root}/config/standalone/args.gni")

chip_device_project_config_include = "<CHIPProjectAppConfig.h>"
chip_project_config_include = "<CHIPProjectAppConfig.h>"
chip_system_project_config_include = "<SystemProjectConfig.h>"

chip_project_config_include_dirs =
[ "${chip_root}/examples/java-matter-controller/include" ]
chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ]
1 change: 1 addition & 0 deletions examples/java-matter-controller/build_overrides
Loading

0 comments on commit 1310186

Please sign in to comment.