Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Expand Java GN rules to support more complex usecases #9876

Merged
merged 2 commits into from
Sep 24, 2021
Merged
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
4 changes: 4 additions & 0 deletions .github/workflows/android.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,7 @@ jobs:
run: |
./scripts/run_in_build_env.sh \
"./scripts/build/build_examples.py --no-log-timestamps --platform android build"
- name: Run Android build rule tests
run: |
./scripts/run_in_build_env.sh \
"ninja -C out/android-arm64-chip_tool build/chip/java/tests:java_build_test.tests"
3 changes: 3 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {

if (chip_build_tests) {
deps += [ "//src:tests" ]
if (current_os == "android") {
deps += [ "${chip_root}/build/chip/java/tests:java_build_test" ]
}
}

if (chip_with_lwip) {
Expand Down
30 changes: 28 additions & 2 deletions build/chip/java/javac_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"""Wrapper script to run javac command as an action with gn."""

import argparse
import json
import os
import subprocess
import sys
Expand Down Expand Up @@ -78,6 +79,19 @@ def FindCommand(command):
return None


def ReadBuildConfig(build_config):
with open(build_config, 'r') as file:
return json.load(file)


def ComputeClasspath(build_config_json):
unique_jars = build_config_json['deps_info']['deps_jars']
if sys.platform == 'win32':
return ";".join(unique_jars)
else:
return ":".join(unique_jars)


def main():
java_path = FindCommand('javac')
if not java_path:
Expand All @@ -95,13 +109,25 @@ def main():
dest='outfile',
required=True,
help='Output file containing a list of classes')
parser.add_argument(
'--build-config',
dest='build_config',
required=True,
help='Build config')
parser.add_argument(
'rest', metavar='JAVAC_ARGS', nargs='*', help='Argumets to pass to javac')

args = parser.parse_args()
if not os.path.isdir(args.classdir):
os.makedirs(args.classdir)
retcode = subprocess.check_call([java_path] + args.rest)
os.makedirs(args.classdir, exist_ok=True)

build_config_json = ReadBuildConfig(args.build_config)
classpath = ComputeClasspath(build_config_json)
java_args = [java_path]
if classpath:
java_args += ["-classpath", classpath]

retcode = subprocess.check_call(java_args + args.rest)
if retcode != EXIT_SUCCESS:
return retcode

Expand Down
174 changes: 121 additions & 53 deletions build/chip/java/rules.gni
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ 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")

# Declare a java library target
#
# sources: List of .java files included in this library.
# sources: List of .java files included in this library. Mutually exclusive with jar_path.
#
# jar_path: A path to an existing JAR. Mutually exclusive with sources.
#
# output_name: File name for the output .jar (not including extension).
# Defaults to the input .jar file name.
Expand All @@ -39,76 +42,137 @@ template("java_library") {
_jar_name += ".jar"
}

# Additional flags
_javac_flags = [
"-Werror",
"-Xlint:all",
]
if (defined(invoker.javac_flags)) {
_javac_flags += invoker.javac_flags
}

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

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

# What files will be compiled
_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/lib/$_target_dir_name/" +
get_path_info(invoker.jar_path, "name") + ".jar"
} else {
_jar_output = "$root_out_dir/lib/$_target_dir_name/$_jar_name"
}

# Generates a .java 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
# 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 ]
}
write_file(_java_sources_file, rebase_path(_java_files, root_build_dir))
_rebased_deps_configs = rebase_path(_deps_configs, 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
# 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)

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

script = javac_runner
deps = _deps

outputs = [ _build_config ]
args = [
"--classdir",
_class_dir,
"--outfile",
rebase_path(_class_list_file, root_build_dir),
"--",
"-d",
_class_dir,
"@" + rebase_path(_java_sources_file, root_build_dir),
] + _javac_flags
"--jar-path",
rebase_path(_jar_output, root_build_dir),
"--build-config",
_rebased_build_config,
"--deps-configs=$_rebased_deps_configs",
]
}

# Bundles all files within the 'class directory' into a jar file
_jar_output = "$root_out_dir/lib/$_jar_name"
action(target_name) {
deps = [ ":$_javac_target_name" ] + _deps
# 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
# Data deps
_data_deps = []
if (defined(invoker.data_deps)) {
_data_deps = invoker.data_deps
}

outputs = [ _jar_output ]
# Generates a .java 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
}

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

args = [
"cf",
rebase_path(_jar_output, root_build_dir),
"-C",
_class_dir,
".",
]
data_deps = _data_deps

outputs = [ _jar_output ]

script = jar_runner

args = [
"cf",
rebase_path(_jar_output, root_build_dir),
"-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
}
}
}

Expand All @@ -121,8 +185,6 @@ template("android_library") {
}

javac_flags += [
"-classpath",
"${android_sdk_root}/platforms/android-${android_sdk_version}/android.jar",
"-Xlint:-options",
"-source",
"8",
Expand All @@ -131,3 +193,9 @@ template("android_library") {
]
}
}

template("java_prebuilt") {
java_library(target_name) {
forward_variables_from(invoker, "*")
}
}
63 changes: 63 additions & 0 deletions build/chip/java/tests/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright (c) 2021 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("//build_overrides/pigweed.gni")
import("$dir_pw_build/python.gni")
import("${chip_root}/build/chip/java/rules.gni")

pw_python_script("java_build_test") {
inputs = [
"expected_output/child_library_2_expected.json",
"expected_output/grandchild_library_expected.json",
"expected_output/child_library_expected.json",
"expected_output/java_library_expected.json",
"expected_output/child_prebuilt_expected.json",
"expected_output/java_prebuilt_expected.json",
]
other_deps = [ ":java_library" ]
tests = [ "test.py" ]
}

java_library("java_library") {
sources = [ "IncludedInSources.java" ]
deps = [
":child_library",
":child_library_2",
":java_prebuilt",
]
}

java_library("child_library") {
sources = [ "IncludedInChildSources.java" ]
}

java_library("child_library_2") {
sources = [ "IncludedInChildSources2.java" ]

deps = [ ":grandchild_library" ]
}

java_library("grandchild_library") {
sources = [ "IncludedInGrandchildSources.java" ]
}

java_prebuilt("java_prebuilt") {
jar_path = "/tmp/chip_java_build_test/prebuilt_jar.jar"
deps = [ ":child_prebuilt" ]
}

java_prebuilt("child_prebuilt") {
jar_path = "/tmp/chip_java_build_test/child_jar.jar"
}
3 changes: 3 additions & 0 deletions build/chip/java/tests/IncludedInChildJar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package build.chip.java.tests;

public class IncludedInChildJar {}
3 changes: 3 additions & 0 deletions build/chip/java/tests/IncludedInChildSources.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package build.chip.java.tests;

public class IncludedInChildSources {}
5 changes: 5 additions & 0 deletions build/chip/java/tests/IncludedInChildSources2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package build.chip.java.tests;

public class IncludedInChildSources2 {
IncludedInGrandchildSources includedInGrandchildSources;
}
3 changes: 3 additions & 0 deletions build/chip/java/tests/IncludedInGrandchildSources.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package build.chip.java.tests;

public class IncludedInGrandchildSources {}
5 changes: 5 additions & 0 deletions build/chip/java/tests/IncludedInJar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package build.chip.java.tests;

public class IncludedInJar {
IncludedInChildJar includedInChildJar;
}
9 changes: 9 additions & 0 deletions build/chip/java/tests/IncludedInSources.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package build.chip.java.tests;

public class IncludedInSources {
IncludedInChildSources includedInChildSources;
IncludedInChildSources2 includedInChildSources2;
IncludedInGrandchildSources includedInGrandchildSources;

IncludedInJar includedInJar;
}
Loading