| # Copyright 2018 The Bazel Authors. All rights reserved. |
| # |
| # 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. |
| """Methods to create and process R.java.""" |
| |
| load("//rules:visibility.bzl", "PROJECT_VISIBILITY") |
| load("@rules_java//java/common:java_common.bzl", "java_common") |
| load(":utils.bzl", "utils") |
| |
| visibility(PROJECT_VISIBILITY) |
| |
| def _make_r_java(ctx, resource_src_jar, main_r_java, out_r_java): |
| """Remove final qualifieres from R.java.""" |
| |
| # R classes used during library compilation have only library level |
| # information about app resources, therefore we strip those files but still |
| # need to repackage the final version of the R classes for all packages. |
| # In theory we could implement this as a provider in blaze and use whatever |
| # they create, however their implementation might be suboptimal. |
| cmd = """ |
| if [[ $1 == *.java ]]; then |
| r_java=$1 |
| else |
| r_java_dir=$(mktemp -d) |
| r_java="${r_java_dir}/R.java" |
| unzip -j -q $1 $2 -d "${r_java_dir}" &> /dev/null |
| fi |
| # R jar might be empty, so check for R java file explicitly |
| if [[ -f ${r_java} ]]; then |
| sed -i -e 's/final class/class/g' ${r_java} |
| cat ${r_java} | grep -v "^package .*;$" > $3 |
| else |
| touch $3 |
| fi |
| """ |
| ctx.actions.run_shell( |
| command = cmd, |
| arguments = [ |
| resource_src_jar.path, |
| main_r_java, |
| out_r_java.path, |
| ], |
| inputs = [resource_src_jar], |
| outputs = [out_r_java], |
| mnemonic = "MakeRJava", |
| progress_message = "MI R.java " + out_r_java.path, |
| ) |
| |
| def _make_r_jar(ctx, r_java, packages, out_r_jar): |
| """Makes an R.jar containing all the Rs for the app.""" |
| |
| # TODO(djwhang): Create an intermediary action that creates the remaining |
| # R.java files and then use the default compiler to compile and Jar. |
| r_packages = utils.isolated_declare_file( |
| ctx, |
| "r_packages.txt", |
| sibling = out_r_jar, |
| ) |
| ctx.actions.write( |
| output = r_packages, |
| content = "\n".join(packages.to_list()), |
| ) |
| |
| rjar_args = ctx.actions.args() |
| rjar_args.add("rjar") |
| rjar_args.add("--jdk", utils.host_jvm_path(ctx)) |
| rjar_args.add("--jartool", utils.first(ctx.attr._jar_tool[DefaultInfo].files.to_list()).path) |
| rjar_args.add("--rjava", r_java.path) |
| rjar_args.add("--pkgs", r_packages.path) |
| rjar_args.add("--rjar", out_r_jar.path) |
| rjar_args.add("--target_label", str(ctx.label)) |
| rjar_args.add_joined("--jvm_opts", ctx.attr._java_toolchain[java_common.JavaToolchainInfo].jvm_opt, join_with = " ") |
| |
| # Call action binary. |
| ctx.actions.run( |
| executable = ctx.executable._android_kit, |
| arguments = [rjar_args], |
| tools = ctx.attr._jar_tool[DefaultInfo].files, |
| inputs = depset([r_packages, r_java], transitive = [ctx.attr._java_jdk[DefaultInfo].files]), |
| outputs = [out_r_jar], |
| mnemonic = "RJar", |
| progress_message = "MI RJar " + out_r_jar.path, |
| ) |
| |
| def make_r(ctx, r_java_zip, main_package, packages, sibling): |
| """Creates all the Rs for the app then compiles, Jar and Dex it. |
| |
| Args: |
| ctx: The context. |
| r_java_zip: A zip file containing the main R.java file. |
| main_package: A string representing the package of the main target. |
| packages: The list of packages in the app that need Rs. |
| sibling: The file used as the relative location for any new files created. |
| |
| Returns: |
| The R.java as a Dex file. |
| """ |
| main_r_java = main_package.replace(".", "/") + "/R.java" |
| r_java = utils.isolated_declare_file(ctx, "dex_shards/R.java", sibling = sibling) |
| _make_r_java(ctx, r_java_zip, main_r_java, r_java) |
| |
| r_jar = utils.isolated_declare_file(ctx, "R.jar", sibling = r_java) |
| _make_r_jar(ctx, r_java, packages, r_jar) |
| |
| # To ensure R.zip is at the beginning of all the dex_shards,which ranges |
| # between 01-16, the R.zip is named as 00.zip |
| r_dex = utils.isolated_declare_file(ctx, "00.zip", sibling = r_java) |
| utils.merge_dex_shards(ctx, [r_jar], r_dex) |
| return r_dex |