// 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. package com.google.devtools.build.lib.rules.android; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; import com.google.devtools.build.lib.rules.java.JavaUtil; import com.google.devtools.build.lib.vfs.PathFragment; import javax.annotation.Nullable; /** Wraps an Android Manifest and provides utilities for working with it */ @Immutable public class AndroidManifest { private static final SafeImplicitOutputsFunction MERGED_MANIFEST = ImplicitOutputsFunction.fromTemplates("{name}_manifest/AndroidManifest.xml"); private static final SafeImplicitOutputsFunction MERGE_LOG = ImplicitOutputsFunction.fromTemplates("{name}_manifest/manifest_merger_log.txt"); private final RuleContext ruleContext; /** * The current manifest. May be null if this rule has no manifest and we have not yet generated * one through merging or stamping. */ @Nullable private final Artifact manifest; private final String pkg; private final boolean isDummy; public static AndroidManifest empty(RuleContext ruleContext) { return of(ruleContext, null, null); } /** * @param ruleContext the current context * @param manifest this target's manifest. Can be null if this target has no manifest, in which * case a dummy manifest will be generated. * @param customPackage this target's custom package. If null, the default package, derived from * BUILD file location, will be used. * @return an AndroidManifest object wrapping the manifest and package */ public static AndroidManifest of( RuleContext ruleContext, @Nullable Artifact manifest, @Nullable String customPackage) { return new AndroidManifest( ruleContext, manifest, customPackage == null ? getDefaultPackage(ruleContext) : customPackage, manifest == null); } AndroidManifest( RuleContext ruleContext, @Nullable Artifact manifest, String pkg, boolean isDummy) { this.ruleContext = ruleContext; this.manifest = manifest; this.pkg = pkg; this.isDummy = isDummy; } /** * Merges the current manifest with manifests from the specified deps and stamps the result. * *
Manifests will not be merged if the dependencies do not provide {@link AndroidManifestInfo} * or the provided manifests are generated dummies. * *
The resulting manifest will always be stamped if needed, even if no merging is done.
*/
public StampedAndroidManifest stampAndMergeWith(ImmutableList Bazel requires that all Java code (including Android code) be in a path prefixed with "java"
* or "javatests" followed by the Java package; this method validates and takes advantage of that
* requirement.
*
* @param ruleContext the current context
* @param jarPathFragment The path to a JAR file contained in the current BUILD file's directory.
* @return the Java package, as a String
*/
static String getJavaPackageFromPath(RuleContext ruleContext, PathFragment jarPathFragment) {
// TODO(bazel-team): JavaUtil.getJavaPackageName does not check to see if the path is valid.
// So we need to check for the JavaRoot.
if (JavaUtil.getJavaRoot(jarPathFragment) == null) {
ruleContext.ruleError(
"The location of your BUILD file determines the Java package used for "
+ "Android resource processing. A directory named \"java\" or \"javatests\" will "
+ "be used as your Java source root and the path of your BUILD file relative to "
+ "the Java source root will be used as the package for Android resource "
+ "processing. The Java source root could not be determined for \""
+ ruleContext.getPackageDirectory()
+ "\". Move your BUILD file under a java or javatests directory, or set the "
+ "'custom_package' attribute.");
}
return JavaUtil.getJavaPackageName(jarPathFragment);
}
}