Skip to content

Commit

Permalink
Add IsRunfilesLibraryInfo provider and add support to java_library
Browse files Browse the repository at this point in the history
`java_library` targets that directly depend on
`@bazel_tools//tools/java/runfiles` have compile-time access to the
constant
`com.google.devtools.build.runfiles.RunfilesHelper.CURRENT_REPO_NAME`,
which contains the canonical repository name of the repository that
contains the target.

The constant is inlined during compilation, ensuring that no new class
is added to the classpath. If a `java_library` does not directly depend
on the runfiles library, no additional action will be generated.
  • Loading branch information
fmeum committed Jun 11, 2022
1 parent f0e63c4 commit fdbc854
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/main/java/com/google/devtools/build/lib/analysis/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ java_library(
":file_provider",
":incompatible_platform_provider",
":inconsistent_aspect_order_exception",
":is_runfiles_library_info",
":label_and_location",
":label_expander",
":licenses_provider",
Expand Down Expand Up @@ -820,6 +821,16 @@ java_library(
],
)

java_library(
name = "is_runfiles_library_info",
srcs = ["IsRunfilesLibraryInfo.java"],
deps = [
"//src/main/java/com/google/devtools/build/lib/concurrent",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi",
],
)

java_library(
name = "label_and_location",
srcs = ["LabelAndLocation.java"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2022 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.

package com.google.devtools.build.lib.analysis;

import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
import com.google.devtools.build.lib.starlarkbuildapi.IsRunfilesLibraryInfoApi;

/**
* Provider that signals to direct dependents that this target is a runfiles library and that they
* should ensure that their compiled code has access to its canonical repository name, e.g.
* via a generated constant.
*/
@Immutable
public final class IsRunfilesLibraryInfo extends NativeInfo implements IsRunfilesLibraryInfoApi {

public static final IsRunfilesLibraryInfoProvider PROVIDER = new IsRunfilesLibraryInfoProvider();

@Override
public IsRunfilesLibraryInfoProvider getProvider() {
return PROVIDER;
}

public static class IsRunfilesLibraryInfoProvider extends BuiltinProvider<IsRunfilesLibraryInfo>
implements IsRunfilesLibraryInfoApi.RunEnvironmentInfoApiProvider {

private IsRunfilesLibraryInfoProvider() {
super("IsRunfilesLibraryInfo", IsRunfilesLibraryInfo.class);
}

@Override
public IsRunfilesLibraryInfoApi constructor() {
return new IsRunfilesLibraryInfo();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.ActionsProvider;
import com.google.devtools.build.lib.analysis.DefaultInfo;
import com.google.devtools.build.lib.analysis.IsRunfilesLibraryInfo;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RunEnvironmentInfo;
import com.google.devtools.build.lib.packages.StarlarkLibrary;
Expand Down Expand Up @@ -46,5 +47,6 @@ public static void addPredeclared(ImmutableMap.Builder<String, Object> predeclar
predeclared.put("Actions", ActionsProvider.INSTANCE);
predeclared.put("DefaultInfo", DefaultInfo.PROVIDER);
predeclared.put("RunEnvironmentInfo", RunEnvironmentInfo.PROVIDER);
predeclared.put("IsRunfilesLibraryInfo", IsRunfilesLibraryInfo.PROVIDER);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2022 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.

package com.google.devtools.build.lib.starlarkbuildapi;

import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.docgen.annot.StarlarkConstructor;
import com.google.devtools.build.lib.starlarkbuildapi.core.ProviderApi;
import com.google.devtools.build.lib.starlarkbuildapi.core.StructApi;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.annot.StarlarkMethod;

/**
* Provider that signals to direct dependents that this target is a runfiles library and that they
* should ensure that their compiled code has access to its canonical repository name, e.g.
* via a generated constant.
*/
@StarlarkBuiltin(
name = "IsRunfilesLibraryInfo",
category = DocCategory.PROVIDER,
doc = "Provider that signals to direct dependents that this target is a runfiles library and "
+ "that they should ensure that their compiled code has access to its canonical repository "
+ "name, e.g. via a generated constant.")
public interface IsRunfilesLibraryInfoApi extends StructApi {

@StarlarkBuiltin(name = "Provider", category = DocCategory.PROVIDER, documented = false, doc = "")
interface RunEnvironmentInfoApiProvider extends ProviderApi {

@StarlarkMethod(
name = "IsRunfilesLibraryInfo",
doc = "",
documented = false,
selfCall = true)
@StarlarkConstructor
IsRunfilesLibraryInfoApi constructor();
}
}
12 changes: 11 additions & 1 deletion src/main/starlark/builtins_bzl/common/java/java_common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ load(":common/java/android_lint.bzl", "android_lint_action")
load(":common/java/compile_action.bzl", "COMPILE_ACTION", "COMPILE_ACTION_IMPLICIT_ATTRS", "compile_action")
load(":common/java/java_semantics.bzl", "semantics")
load(":common/java/proguard_validation.bzl", "VALIDATE_PROGUARD_SPECS_IMPLICIT_ATTRS", "validate_proguard_specs")
load(":common/java/runfiles_helper.bzl", "RUNFILES_HELPER_ACTION", "RUNFILES_HELPER_ACTION_IMPLICIT_ATTRS", "depends_on_runfiles_library", "runfiles_helper_action")

java_common = _builtins.toplevel.java_common
coverage_common = _builtins.toplevel.coverage_common
Expand Down Expand Up @@ -124,13 +125,20 @@ def basic_java_library(
resources = list(resources)
resources.extend(properties)

if coverage_config:
collected_deps = _collect_deps(deps + [coverage_config.runner])
else:
collected_deps = _collect_deps(deps)
if depends_on_runfiles_library(deps):
collected_deps.append(runfiles_helper_action(ctx))

java_info, compilation_info = compile_action(
ctx,
ctx.outputs.classjar,
ctx.outputs.sourcejar,
source_files,
source_jars,
_collect_deps(deps + [coverage_config.runner]) if coverage_config else _collect_deps(deps),
collected_deps,
_collect_deps(runtime_deps),
plugins_javaplugininfo,
_collect_deps(exports),
Expand Down Expand Up @@ -258,6 +266,7 @@ def construct_defaultinfo(ctx, files_to_build, files, neverlink, *extra_attrs):

BASIC_JAVA_LIBRARY_IMPLICIT_ATTRS = merge_attrs(
COMPILE_ACTION_IMPLICIT_ATTRS,
RUNFILES_HELPER_ACTION_IMPLICIT_ATTRS,
{
"_java_plugins": attr.label(
default = semantics.JAVA_PLUGINS_FLAG_ALIAS_LABEL,
Expand All @@ -275,4 +284,5 @@ BASIC_JAVA_LIBRARY_WITH_PROGUARD_IMPLICIT_ATTRS = merge_attrs(
JAVA_COMMON_DEP = create_composite_dep(
basic_java_library,
COMPILE_ACTION,
RUNFILES_HELPER_ACTION,
)
69 changes: 69 additions & 0 deletions src/main/starlark/builtins_bzl/common/java/runfiles_helper.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2021 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.

load(":common/rule_util.bzl", "create_dep")
load(":common/java/java_semantics.bzl", "semantics")

java_common = _builtins.toplevel.java_common

IsRunfilesLibraryInfo = _builtins.toplevel.IsRunfilesLibraryInfo

_RUNFILES_HELPER_TEMPLATE = """package com.google.devtools.build.runfiles;
public final class RunfilesHelper {
public static final String CURRENT_REPO_NAME = "%s";
private RunfilesHelper() {}
}
"""

def depends_on_runfiles_library(deps):
for dep in deps:
if IsRunfilesLibraryInfo in dep:
return True
return False

def runfiles_helper_action(ctx):
basename = "_runfiles_helper/%s_runfiles_helper" % ctx.attr.name

java_file = ctx.actions.declare_file(basename + ".java")
current_repo_name = ctx.label.workspace_name or ctx.workspace_name
ctx.actions.write(java_file, _RUNFILES_HELPER_TEMPLATE % current_repo_name)

jar_file = ctx.actions.declare_file(basename + ".jar")
return java_common.compile(
ctx,
java_toolchain = ctx.attr._java_toolchain[java_common.JavaToolchainInfo],
# The JLS (§13.1) guarantees that constants are inlined. Since the generated code only
# contains constants, we can remove it from the runtime classpath.
neverlink = True,
output = jar_file,
source_files = [java_file],
)

RUNFILES_HELPER_ACTION = create_dep(
runfiles_helper_action,
attrs = {
"_java_toolchain": attr.label(
default = semantics.JAVA_TOOLCHAIN_LABEL,
providers = [java_common.JavaToolchainInfo],
),
},
)

RUNFILES_HELPER_ACTION_IMPLICIT_ATTRS = {
"_java_toolchain": attr.label(
default = semantics.JAVA_TOOLCHAIN_LABEL,
providers = [java_common.JavaToolchainInfo],
),
}
1 change: 1 addition & 0 deletions tools/java/runfiles/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ filegroup(
name = "embedded_tools",
srcs = [
"BUILD.tools",
"java_runfiles_library.bzl",
":java-srcs",
],
visibility = ["//tools/java:__pkg__"],
Expand Down
10 changes: 8 additions & 2 deletions tools/java/runfiles/BUILD.tools
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
java_library(
load(":java_runfiles_library.bzl", "java_runfiles_library")

java_runfiles_library(
name = "runfiles",
visibility = ["//visibility:public"],
)

java_library(
name = "runfiles_impl",
srcs = [
"Runfiles.java",
"Util.java",
],
visibility = ["//visibility:public"],
)
13 changes: 13 additions & 0 deletions tools/java/runfiles/java_runfiles_library.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
def _java_runfiles_library_impl(ctx):
return [
ctx.attr._runfiles_library[DefaultInfo],
ctx.attr._runfiles_library[JavaInfo],
IsRunfilesLibraryInfo(),
]

java_runfiles_library = rule(
implementation = _java_runfiles_library_impl,
attrs = {
"_runfiles_library": attr.label(default = ":runfiles_impl"),
},
)

0 comments on commit fdbc854

Please sign in to comment.