From 135914438dd3d184ac903a153821ac546d9aae7a Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Thu, 17 Nov 2022 16:02:07 -0800 Subject: [PATCH] Add support to compile java matter controller test example in host without android (#23630) * Add suppoprt to compile java matter controller test in host * Restyled by gn Co-authored-by: Restyled.io --- build/chip/java/config.gni | 26 ++++++ build/chip/java/rules.gni | 5 +- build/config/compiler/BUILD.gn | 4 + examples/build_overrides/build.gni | 1 - examples/java-matter-controller/BUILD.gn | 3 - scripts/build/build/targets.py | 1 + scripts/build/builders/host.py | 83 +++++++++++++++++++ .../build/testdata/all_targets_linux_x64.txt | 2 +- src/controller/data_model/BUILD.gn | 13 ++- src/controller/java/BUILD.gn | 29 ++++--- src/lib/support/BUILD.gn | 9 +- src/setup_payload/java/BUILD.gn | 17 ++-- 12 files changed, 162 insertions(+), 31 deletions(-) create mode 100644 build/chip/java/config.gni diff --git a/build/chip/java/config.gni b/build/chip/java/config.gni new file mode 100644 index 00000000000000..626d7b00e2a669 --- /dev/null +++ b/build/chip/java/config.gni @@ -0,0 +1,26 @@ +# 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. + +java_path = getenv("JAVA_PATH") +declare_args() { + java_matter_controller_dependent_paths = [] + build_java_matter_controller = false + if (java_path != "") { + java_matter_controller_dependent_paths += [ + "${java_path}/include/", + "${java_path}/include/linux/", + ] + build_java_matter_controller = true + } +} diff --git a/build/chip/java/rules.gni b/build/chip/java/rules.gni index c8518303f121dd..446bad701931f1 100644 --- a/build/chip/java/rules.gni +++ b/build/chip/java/rules.gni @@ -13,14 +13,15 @@ # limitations under the License. import("//build_overrides/chip.gni") - +import("${chip_root}/build/chip/java/config.gni") import("${chip_root}/build/config/android/config.gni") javac_runner = "${chip_root}/build/chip/java/javac_runner.py" jar_runner = "${chip_root}/build/chip/java/jar_runner.py" write_build_config = "${chip_root}/build/chip/java/write_build_config.py" -assert(android_sdk_root != "", "android_sdk_root must be specified") +assert(android_sdk_root != "" || build_java_matter_controller, + "android_sdk_root or java_path must be specified") # Declare a java library target # diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 938d2d7e405835..07040089ecc0e1 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -248,6 +248,10 @@ config("strict_warnings") { ] } + if (getenv("JAVA_PATH") != "") { + cflags -= [ "-Wshadow" ] + } + cflags_cc = [ "-Wnon-virtual-dtor" ] ldflags = [] diff --git a/examples/build_overrides/build.gni b/examples/build_overrides/build.gni index b092dc3c3d7013..323b150ed3399a 100644 --- a/examples/build_overrides/build.gni +++ b/examples/build_overrides/build.gni @@ -15,5 +15,4 @@ declare_args() { # Root directory for build files. build_root = "//third_party/connectedhomeip/build" - build_java_matter_controller = false } diff --git a/examples/java-matter-controller/BUILD.gn b/examples/java-matter-controller/BUILD.gn index 71a44aaa2688cf..154f75aba19227 100644 --- a/examples/java-matter-controller/BUILD.gn +++ b/examples/java-matter-controller/BUILD.gn @@ -15,12 +15,9 @@ 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") -build_java_matter_controller = true - java_binary("java-matter-controller") { output_name = "java-matter-controller" deps = [ diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index f88e8e7a3fdce1..4c8ed88280ba43 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -100,6 +100,7 @@ def BuildHostTarget(): TargetPart('all-clusters-minimal', app=HostApp.ALL_CLUSTERS), TargetPart('chip-tool', app=HostApp.CHIP_TOOL), TargetPart('thermostat', app=HostApp.THERMOSTAT), + TargetPart('java-matter-controller', app=HostApp.JAVA_MATTER_CONTROLLER), TargetPart('minmdns', app=HostApp.MIN_MDNS), TargetPart('light', app=HostApp.LIGHT), TargetPart('lock', app=HostApp.LOCK), diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index ce735ad7ecde16..258be0a13ec39e 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -58,6 +58,7 @@ class HostApp(Enum): TV_CASTING = auto() BRIDGE = auto() DYNAMIC_BRIDGE = auto() + JAVA_MATTER_CONTROLLER = auto() def ExamplePath(self): if self == HostApp.ALL_CLUSTERS: @@ -98,6 +99,8 @@ def ExamplePath(self): return 'bridge-app/linux' elif self == HostApp.DYNAMIC_BRIDGE: return 'dynamic-bridge-app/linux' + elif self == HostApp.JAVA_MATTER_CONTROLLER: + return 'java-matter-controller' else: raise Exception('Unknown app type: %r' % self) @@ -168,6 +171,9 @@ def OutputNames(self): elif self == HostApp.DYNAMIC_BRIDGE: yield 'dynamic-chip-bridge-app' yield 'dynamic-chip-bridge-app.map' + elif self == HostApp.JAVA_MATTER_CONTROLLER: + yield 'java-matter-controller' + yield 'java-matter-controller.map' else: raise Exception('Unknown app type: %r' % self) @@ -357,6 +363,41 @@ def GnBuildArgs(self): else: raise Exception('Unknown host board type: %r' % self) + def copyToExampleApp(self, jnilibs_dir, libs_dir, libs, jars): + self._Execute( + ["mkdir", "-p", jnilibs_dir], title="Prepare Native libs " + self.identifier + ) + + for libName in libs: + self._Execute( + [ + "cp", + os.path.join( + self.output_dir, "lib", "jni", self.board.AbiName(), libName + ), + os.path.join(jnilibs_dir, libName), + ] + ) + + for jarName in jars.keys(): + self._Execute( + [ + "cp", + os.path.join(self.output_dir, "lib", jars[jarName]), + os.path.join(libs_dir, jarName), + ] + ) + + def createJavaExecutable(self, java_program): + self._Execute( + [ + "chmod", + "+x", + "%s/bin/%s" % (self.output_dir, java_program), + ], + title="Make Java program executable", + ) + def GnBuildEnv(self): if self.board == HostBoard.ARM64: self.build_env['PKG_CONFIG_PATH'] = os.path.join( @@ -370,6 +411,22 @@ def SysRootPath(self, name): def generate(self): super(HostBuilder, self).generate() + if 'JAVA_PATH' in os.environ: + self._Execute( + ["third_party/java_deps/set_up_java_deps.sh"], + title="Setting up Java deps", + ) + + exampleName = self.app.ExamplePath() + if exampleName == "java-matter-controller": + self._Execute( + [ + "cp", + os.path.join(self.root, "Manifest.txt"), + self.output_dir, + ], + title="Copying Manifest.txt to " + self.output_dir, + ) if self.app == HostApp.TESTS and self.use_coverage: self.coverage_dir = os.path.join(self.output_dir, 'coverage') @@ -385,6 +442,32 @@ def PreBuildCommand(self): '--exclude', os.path.join(self.chip_dir, 'third_party/*'), '--exclude', '/usr/include/*', '--output-file', os.path.join(self.coverage_dir, 'lcov_base.info')], title="Initial coverage baseline") + if self.app.exampleName == "java-matter-controller" and 'JAVA_PATH' in os.environ: + jnilibs_dir = os.path.join( + self.root, + "examples/", + self.app.ExampleName(), + "app/libs/jniLibs", + self.board.AbiName(), + ) + + libs_dir = os.path.join( + self.root, "examples/", self.app.ExampleName(), "app/libs" + ) + + libs = [ + "libSetupPayloadParser.so", + "libCHIPController.so", + "libc++_shared.so", + ] + + jars = { + "CHIPController.jar": "third_party/connectedhomeip/src/controller/java/CHIPController.jar", + "SetupPayloadParser.jar": "third_party/connectedhomeip/src/setup_payload/java/SetupPayloadParser.jar", + } + + self.copyToExampleApp(jnilibs_dir, libs_dir, libs, jars) + self.createJavaExecutable("java-matter-controller") def PostBuildCommand(self): if self.app == HostApp.TESTS and self.use_coverage: diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index de7b3618c23309..f893b282aad80c 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -7,7 +7,7 @@ efr32-{brd4161a,brd4187c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,brd4187a,b esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,ota-requestor,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only] genio-lighting-app linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-libfuzzer][-coverage][-dmalloc][-clang] -linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,minmdns,light,lock,shell,ota-provider,ota-requestor,python-bindings,tv-app,tv-casting-app,bridge,dynamic-bridge,tests,chip-cert,address-resolve-tool}[-nodeps][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-libfuzzer][-coverage][-dmalloc][-clang][-test][-rpc] +linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,python-bindings,tv-app,tv-casting-app,bridge,dynamic-bridge,tests,chip-cert,address-resolve-tool}[-nodeps][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-libfuzzer][-coverage][-dmalloc][-clang][-test][-rpc] linux-x64-efr32-test-runner[-clang] imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release] infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage] diff --git a/src/controller/data_model/BUILD.gn b/src/controller/data_model/BUILD.gn index 2596b11333a7fa..011669db09524a 100644 --- a/src/controller/data_model/BUILD.gn +++ b/src/controller/data_model/BUILD.gn @@ -18,6 +18,7 @@ import("//build_overrides/pigweed.gni") import("$dir_pw_build/python.gni") import("${chip_root}/build/chip/chip_codegen.gni") +import("${chip_root}/build/chip/java/config.gni") import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("data_model") { @@ -29,7 +30,7 @@ chip_data_model("data_model") { allow_circular_includes_from = [ "${chip_root}/src/controller" ] } -if (current_os == "android") { +if (current_os == "android" || build_java_matter_controller) { chip_codegen("java-jni-generate") { input = "controller-clusters.matter" generator = "java" @@ -170,15 +171,21 @@ if (current_os == "android") { source_set("java-jni-sources") { sources = get_target_outputs(":java-jni-generate") - public_configs = [ "${chip_root}/src:includes" ] + public_configs = [ "${chip_root}/src:includes" ] deps = [ ":data_model", ":java-jni-generate", "${chip_root}/src/inet", "${chip_root}/src/lib", "${chip_root}/src/platform", - "${chip_root}/src/platform/android", ] + + if (build_java_matter_controller) { + include_dirs = java_matter_controller_dependent_paths + deps += [ "${chip_root}/src/platform/Linux" ] + } else { + deps += [ "${chip_root}/src/platform/android" ] + } } } diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index 76cd24cca0e7f8..3a2d40492f62fa 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -14,13 +14,11 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") -import("${build_root}/config/android_abi.gni") +import("${chip_root}/build/chip/java/config.gni") import("${chip_root}/build/chip/java/rules.gni") -if (defined(build_java_matter_controller)) { - build_java_matter_controller = build_java_matter_controller -} else { - build_java_matter_controller = false +if (!build_java_matter_controller) { + import("${build_root}/config/android_abi.gni") } shared_library("jni") { @@ -60,12 +58,24 @@ shared_library("jni") { "${chip_root}/src/lib", "${chip_root}/src/lib/support/jsontlv", "${chip_root}/src/platform", - "${chip_root}/src/platform/android", ] public_configs = [ "${chip_root}/src:includes" ] - output_dir = "${root_out_dir}/lib/jni/${android_abi}" + if (build_java_matter_controller) { + defines = [ "JAVA_MATTER_CONTROLLER_TEST" ] + include_dirs = java_matter_controller_dependent_paths + + deps += [ "${chip_root}/src/platform/Linux" ] + + cflags = [ "-Wno-unknown-pragmas" ] + + output_dir = "${root_out_dir}/lib/jni" + } else { + deps += [ "${chip_root}/src/platform/android" ] + + output_dir = "${root_out_dir}/lib/jni/${android_abi}" + } ldflags = [ "-Wl,--gc-sections" ] } @@ -75,10 +85,7 @@ android_library("java") { deps = [ "${chip_root}/third_party/java_deps:annotation" ] - data_deps = [ - ":jni", - "${chip_root}/build/chip/java:shared_cpplib", - ] + data_deps = [ ":jni" ] sources = [ "src/chip/clusterinfo/ClusterCommandCallback.java", diff --git a/src/lib/support/BUILD.gn b/src/lib/support/BUILD.gn index 38903219b75ab1..2f86189862e683 100644 --- a/src/lib/support/BUILD.gn +++ b/src/lib/support/BUILD.gn @@ -20,6 +20,7 @@ import("//build_overrides/nlio.gni") import("//build_overrides/nlunit_test.gni") import("${chip_root}/build/chip/chip_version.gni") +import("${chip_root}/build/chip/java/config.gni") import("${chip_root}/build/chip/tests.gni") import("${chip_root}/src/lib/core/core.gni") @@ -145,8 +146,12 @@ static_library("support") { "verhoeff/Verhoeff36.cpp", ] - # added JNI helper on android - if (current_os == "android") { + if (current_os == "android" || build_java_matter_controller) { + if (build_java_matter_controller) { + include_dirs = java_matter_controller_dependent_paths + } + + # added JNI helper on android sources += [ "CHIPJNIError.h", "JniReferences.cpp", diff --git a/src/setup_payload/java/BUILD.gn b/src/setup_payload/java/BUILD.gn index df632864bb2f88..083cd6db55509f 100644 --- a/src/setup_payload/java/BUILD.gn +++ b/src/setup_payload/java/BUILD.gn @@ -14,18 +14,21 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") - -import("${build_root}/config/android_abi.gni") +import("${chip_root}/build/chip/java/config.gni") import("${chip_root}/build/chip/java/rules.gni") -if (defined(build_java_matter_controller)) { - build_java_matter_controller = build_java_matter_controller -} else { - build_java_matter_controller = false +if (!build_java_matter_controller) { + import("${build_root}/config/android_abi.gni") } shared_library("jni") { output_name = "libSetupPayloadParser" + if (build_java_matter_controller) { + include_dirs = java_matter_controller_dependent_paths + output_dir = "${root_out_dir}/lib/jni" + } else { + output_dir = "${root_out_dir}/lib/jni/${android_abi}" + } sources = [ "SetupPayloadParser-JNI.cpp" ] @@ -33,8 +36,6 @@ shared_library("jni") { "${chip_root}/src/lib", "${chip_root}/src/setup_payload", ] - - output_dir = "${root_out_dir}/lib/jni/${android_abi}" } android_library("java") {