aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java112
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt10
-rw-r--r--src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java35
-rw-r--r--tools/android/android_sdk_repository_template.bzl18
4 files changed, 160 insertions, 15 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
index 179f5b51a4..2ce8b4c332 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
@@ -14,10 +14,14 @@
package com.google.devtools.build.lib.bazel.rules.android;
import com.android.repository.Revision;
+import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Maps.EntryTransformer;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.packages.Rule;
@@ -41,6 +45,8 @@ import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+import com.google.devtools.build.skyframe.ValueOrException;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
@@ -52,8 +58,9 @@ import javax.annotation.Nullable;
* Implementation of the {@code android_sdk_repository} rule.
*/
public class AndroidSdkRepositoryFunction extends RepositoryFunction {
- private static final String BUILD_TOOLS_DIR_NAME = "build-tools";
- private static final String PLATFORMS_DIR_NAME = "platforms";
+ private static final PathFragment BUILD_TOOLS_DIR = new PathFragment("build-tools");
+ private static final PathFragment PLATFORMS_DIR = new PathFragment("platforms");
+ private static final PathFragment SYSTEM_IMAGES_DIR = new PathFragment("system-images");
private static final Pattern PLATFORMS_API_LEVEL_PATTERN = Pattern.compile("android-(\\d+)");
private static final Revision MIN_BUILD_TOOLS_REVISION = new Revision(24, 0, 3);
private static final String PATH_ENV_VAR = "ANDROID_HOME";
@@ -91,7 +98,7 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction {
}
DirectoryListingValue platformsDirectoryValue =
- getDirectoryListing(fs, androidSdkPath.getChild(PLATFORMS_DIR_NAME), env);
+ getDirectoryListing(androidSdkPath, PLATFORMS_DIR, env);
if (platformsDirectoryValue == null) {
return null;
}
@@ -131,7 +138,7 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction {
// If the build_tools_version attribute is not explicitly set, we select the highest version
// installed in the SDK.
DirectoryListingValue directoryValue =
- getDirectoryListing(fs, androidSdkPath.getChild(BUILD_TOOLS_DIR_NAME), env);
+ getDirectoryListing(androidSdkPath, BUILD_TOOLS_DIR, env);
if (directoryValue == null) {
return null;
}
@@ -164,6 +171,17 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction {
throw new RepositoryFunctionException(e, Transience.PERSISTENT);
}
+ ImmutableSortedSet<PathFragment> androidDeviceSystemImageDirs =
+ getAndroidDeviceSystemImageDirs(androidSdkPath, env);
+ if (androidDeviceSystemImageDirs == null) {
+ return null;
+ }
+
+ StringBuilder systemImageDirsList = new StringBuilder();
+ for (PathFragment systemImageDir : androidDeviceSystemImageDirs) {
+ systemImageDirsList.append(String.format(" \"%s\",\n", systemImageDir));
+ }
+
String template = getStringResource("android_sdk_repository_template.txt");
String buildFile = template
@@ -171,7 +189,8 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction {
.replace("%build_tools_version%", buildToolsVersion)
.replace("%build_tools_directory%", buildToolsDirectory)
.replace("%api_levels%", Iterables.toString(apiLevels))
- .replace("%default_api_level%", defaultApiLevel);
+ .replace("%default_api_level%", defaultApiLevel)
+ .replace("%system_image_dirs%", systemImageDirsList);
// All local maven repositories that are shipped in the Android SDK.
// TODO(ajmichael): Create SkyKeys so that if the SDK changes, this function will get rerun.
@@ -218,12 +237,12 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction {
/** Gets a DirectoryListingValue for {@code dirPath} or returns null. */
private static DirectoryListingValue getDirectoryListing(
- FileSystem fs, Path dirPath, Environment env)
+ Path root, PathFragment dirPath, Environment env)
throws RepositoryFunctionException, InterruptedException {
try {
return (DirectoryListingValue)
env.getValueOrThrow(
- DirectoryListingValue.key(RootedPath.toRootedPath(fs.getRootDirectory(), dirPath)),
+ DirectoryListingValue.key(RootedPath.toRootedPath(root, dirPath)),
InconsistentFilesystemException.class);
} catch (InconsistentFilesystemException e) {
throw new RepositoryFunctionException(new IOException(e), Transience.PERSISTENT);
@@ -333,4 +352,83 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction {
e);
}
}
+
+ /**
+ * Gets PathFragments for /sdk/system-images/*&#47;*&#47;*, which are the directories in the
+ * SDK that contain system images needed for android_device.
+ */
+ private static ImmutableSortedSet<PathFragment> getAndroidDeviceSystemImageDirs(
+ Path androidSdkPath, Environment env)
+ throws RepositoryFunctionException, InterruptedException {
+ DirectoryListingValue systemImagesDirectoryValue =
+ getDirectoryListing(androidSdkPath, SYSTEM_IMAGES_DIR, env);
+ if (systemImagesDirectoryValue == null) {
+ return null;
+ }
+ ImmutableMap<PathFragment, DirectoryListingValue> apiLevelSystemImageDirs =
+ getSubdirectoryListingValues(
+ androidSdkPath, SYSTEM_IMAGES_DIR, systemImagesDirectoryValue, env);
+ if (apiLevelSystemImageDirs == null) {
+ return null;
+ }
+
+ ImmutableSortedSet.Builder<PathFragment> pathFragments = ImmutableSortedSet.naturalOrder();
+ for (PathFragment apiLevelDir : apiLevelSystemImageDirs.keySet()) {
+ ImmutableMap<PathFragment, DirectoryListingValue> apiTypeSystemImageDirs =
+ getSubdirectoryListingValues(
+ androidSdkPath, apiLevelDir, apiLevelSystemImageDirs.get(apiLevelDir), env);
+ if (apiTypeSystemImageDirs == null) {
+ return null;
+ }
+ for (PathFragment apiTypeDir : apiTypeSystemImageDirs.keySet()) {
+ for (Dirent architectureSystemImageDir :
+ apiTypeSystemImageDirs.get(apiTypeDir).getDirents()) {
+ pathFragments.add(apiTypeDir.getRelative(architectureSystemImageDir.getName()));
+ }
+ }
+ }
+ return pathFragments.build();
+ }
+
+ /** Gets DirectoryListingValues for subdirectories of the directory or returns null. */
+ private static ImmutableMap<PathFragment, DirectoryListingValue> getSubdirectoryListingValues(
+ final Path root, final PathFragment path, DirectoryListingValue directory, Environment env)
+ throws RepositoryFunctionException, InterruptedException {
+ Map<PathFragment, SkyKey> skyKeysForSubdirectoryLookups =
+ Maps.transformEntries(
+ Maps.uniqueIndex(
+ directory.getDirents(),
+ new Function<Dirent, PathFragment>() {
+ @Override
+ public PathFragment apply(Dirent input) {
+ return path.getRelative(input.getName());
+ }
+ }),
+ new EntryTransformer<PathFragment, Dirent, SkyKey>() {
+ @Override
+ public SkyKey transformEntry(PathFragment key, Dirent value) {
+ return DirectoryListingValue.key(
+ RootedPath.toRootedPath(root, root.getRelative(key)));
+ }
+ });
+
+ Map<SkyKey, ValueOrException<InconsistentFilesystemException>> values =
+ env.getValuesOrThrow(
+ skyKeysForSubdirectoryLookups.values(), InconsistentFilesystemException.class);
+
+ ImmutableMap.Builder<PathFragment, DirectoryListingValue> directoryListingValues =
+ new ImmutableMap.Builder<>();
+ for (PathFragment pathFragment : skyKeysForSubdirectoryLookups.keySet()) {
+ try {
+ SkyValue skyValue = values.get(skyKeysForSubdirectoryLookups.get(pathFragment)).get();
+ if (skyValue == null) {
+ return null;
+ }
+ directoryListingValues.put(pathFragment, (DirectoryListingValue) skyValue);
+ } catch (InconsistentFilesystemException e) {
+ throw new RepositoryFunctionException(new IOException(e), Transience.PERSISTENT);
+ }
+ }
+ return directoryListingValues.build();
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt
index 41cc7cb9d2..33a251062a 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt
@@ -1,6 +1,9 @@
package(default_visibility = ["//visibility:public"])
-load("@bazel_tools//tools/android:android_sdk_repository_template.bzl", "create_android_sdk_rules")
+load(
+ "@bazel_tools//tools/android:android_sdk_repository_template.bzl",
+ "create_android_device_rules",
+ "create_android_sdk_rules")
create_android_sdk_rules(
name = "%repository_name%",
@@ -40,5 +43,10 @@ alias(
actual = "tools/lib/emulator/snapshots.img",
)
+create_android_device_rules(
+ system_image_dirs = [
+%system_image_dirs% ],
+)
+
exports_files([
%exported_files%] + glob(["system-images/**"]))
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java
index 5d99bc6188..04799aa4bd 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java
@@ -16,8 +16,11 @@ package com.google.devtools.build.lib.bazel.rules.android;
import static com.google.common.truth.Truth.assertThat;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
@@ -47,6 +50,9 @@ public class AndroidSdkRepositoryTest extends BuildViewTestCase {
" <version>1.0.0</version>",
" <packaging>aar</packaging>",
"</project>");
+ scratch.dir("system-images/android-25/default/armeabi-v7a");
+ scratch.dir("system-images/android-24/google_apis/x86");
+ scratch.dir("system-images/android-24/google_apis/x86_64");
scratch.setWorkingDir("/bazel_tools_workspace");
if (!scratch.resolve("WORKSPACE").exists()) {
@@ -59,23 +65,28 @@ public class AndroidSdkRepositoryTest extends BuildViewTestCase {
"tools/android/android_sdk_repository_template.bzl",
"def create_android_sdk_rules(name, build_tools_version, build_tools_directory, ",
" api_levels, default_api_level):",
- " pass");
+ " pass",
+ "def create_android_device_rules(system_image_dirs):",
+ " native.filegroup(",
+ " name = 'test_android_devices_filegroup',",
+ " srcs = system_image_dirs)");
scratch.setWorkingDir("/workspace");
FileSystemUtils.appendIsoLatin1(scratch.resolve("WORKSPACE"),
"local_repository(name = 'bazel_tools', path = '/bazel_tools_workspace')",
"android_sdk_repository(",
- " name = 'mysdk',",
+ " name = 'androidsdk',",
" path = '/sdk',",
" build_tools_version = '25.0.0',",
" api_level = 25,",
")");
+ invalidatePackages();
}
@Test
public void testGeneratedAarImport() throws Exception {
- invalidatePackages();
- ConfiguredTarget aarImportTarget = getConfiguredTarget("@mysdk//com.google.android:foo-1.0.0");
+ ConfiguredTarget aarImportTarget =
+ getConfiguredTarget("@androidsdk//com.google.android:foo-1.0.0");
assertThat(aarImportTarget).isNotNull();
assertThat(aarImportTarget.getTarget().getAssociatedRule().getRuleClass())
.isEqualTo("aar_import");
@@ -83,9 +94,21 @@ public class AndroidSdkRepositoryTest extends BuildViewTestCase {
@Test
public void testExportsFiles() throws Exception {
- invalidatePackages();
ConfiguredTarget aarTarget = getConfiguredTarget(
- "@mysdk//:extras/google/m2repository/com/google/android/foo/1.0.0/foo.aar");
+ "@androidsdk//:extras/google/m2repository/com/google/android/foo/1.0.0/foo.aar");
assertThat(aarTarget).isNotNull();
}
+
+ @Test
+ public void testSystemImageDirectoriesAreFound() throws Exception {
+ ConfiguredTarget androidDevicesFilegroupTarget =
+ getConfiguredTarget("@androidsdk//:test_android_devices_filegroup");
+ ImmutableList<Artifact> systemImagesDirectories =
+ androidDevicesFilegroupTarget.getProvider(FilesToRunProvider.class).getFilesToRun();
+ assertThat(artifactsToStrings(systemImagesDirectories))
+ .containsExactly(
+ "src external/androidsdk/system-images/android-25/default/armeabi-v7a",
+ "src external/androidsdk/system-images/android-24/google_apis/x86",
+ "src external/androidsdk/system-images/android-24/google_apis/x86_64");
+ }
}
diff --git a/tools/android/android_sdk_repository_template.bzl b/tools/android/android_sdk_repository_template.bzl
index ec6de6d605..d6a29f8578 100644
--- a/tools/android/android_sdk_repository_template.bzl
+++ b/tools/android/android_sdk_repository_template.bzl
@@ -19,7 +19,7 @@ def create_android_sdk_rules(
build_tools_directory,
api_levels,
default_api_level):
- """Generate the contents of the android_sdk_repository.
+ """Generate android_sdk rules for the API levels in the Android SDK.
Args:
name: string, the name of the repository being generated.
@@ -203,3 +203,19 @@ def create_android_sdk_rules(
name = "dx_jar_import",
jars = [":dx_jar"],
)
+
+def create_android_device_rules(system_image_dirs):
+ """Generate android_device rules for the system images in the Android SDK.
+
+ Args:
+ system_image_dirs: list of strings, the directories containing system image
+ files to be used to create android_device rules.
+ """
+
+ for system_image_dir in system_image_dirs:
+ name = "_".join(system_image_dir.split("/")[1:])
+
+ native.filegroup(
+ name = "%s_files" % name,
+ srcs = native.glob(["%s/**" % system_image_dir]),
+ )