// Copyright 2014 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.rules.java; import com.google.common.collect.ImmutableMap.Builder; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; import com.google.devtools.build.lib.util.OsUtils; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; /** * This class represents a Java virtual machine with a host system and a path. If the JVM comes from * the client, it can optionally also contain a label pointing to a target that contains all the * necessary files. */ @SkylarkModule( name = "jvm", category = SkylarkModuleCategory.CONFIGURATION_FRAGMENT, doc = "A configuration fragment representing the Java virtual machine." ) @Immutable public final class Jvm extends BuildConfiguration.Fragment { private final PathFragment javaHome; private final Label jvmLabel; private final PathFragment java; private static final String BIN_JAVA = "bin/java" + OsUtils.executableExtension(); /** * Creates a Jvm instance. Either the {@code javaHome} parameter is absolute, * and/or the {@code jvmLabel} parameter must be non-null. Only the * {@code jvmLabel} is optional. */ public Jvm(PathFragment javaHome, Label jvmLabel) { Preconditions.checkArgument(javaHome.isAbsolute() || jvmLabel != null); this.javaHome = javaHome; this.jvmLabel = jvmLabel; this.java = getJavaHome().getRelative(BIN_JAVA); } /** * Returns a path fragment that determines the path to the installation * directory. It is either absolute or relative to the execution root. */ public PathFragment getJavaHome() { return javaHome; } /** * Returns the path to the java binary. */ @SkylarkCallable(name = "java_executable", structField = true, doc = "The java executable, i.e. bin/java relative to the Java home.") public PathFragment getJavaExecutable() { return java; } /** * Returns a label. Adding this label to the dependencies of an action that * depends on this JVM is sufficient to ensure that all the required files are * present. Can be <code>null</code>, in which case nothing needs to be added * to the dependencies of an action. We rely on convention to make sure that * this case works, since we can't know which JVMs are installed on the build host. */ public Label getJvmLabel() { return jvmLabel; } /** * If possible, resolves java relative to the jvmLabel's repository. Otherwise, returns the * same thing as getJavaExecutable(). */ public PathFragment getRunfilesJavaExecutable() { if (javaHome.isAbsolute() || jvmLabel.getPackageIdentifier().getRepository().isMain()) { return getJavaExecutable(); } return jvmLabel.getPackageIdentifier().getRepository().getRunfilesPath().getRelative(BIN_JAVA); } @Override public void addGlobalMakeVariables(Builder<String, String> globalMakeEnvBuilder) { globalMakeEnvBuilder.put("JAVABASE", getJavaHome().getPathString()); globalMakeEnvBuilder.put("JAVA", getJavaExecutable().getPathString()); } }