use of com.android.tools.build.bundletool.model.ModuleEntry in project bundletool by google.
the class ApexBundleValidator method validateModule.
@Override
public void validateModule(BundleModule module) {
if (module.findEntriesUnderPath(APEX_DIRECTORY).count() == 0) {
return;
}
Optional<ModuleEntry> apexManifest = module.getEntry(APEX_MANIFEST_PATH);
if (apexManifest.isPresent()) {
validateApexManifest(apexManifest.get());
} else {
apexManifest = module.getEntry(APEX_MANIFEST_JSON_PATH);
if (!apexManifest.isPresent()) {
throw InvalidBundleException.builder().withUserMessage("Missing expected file in APEX bundle: '%s' or '%s'.", APEX_MANIFEST_PATH, APEX_MANIFEST_JSON_PATH).build();
}
validateApexManifestJson(apexManifest.get());
}
ImmutableSet.Builder<String> apexImagesBuilder = ImmutableSet.builder();
ImmutableSet.Builder<String> apexBuildInfosBuilder = ImmutableSet.builder();
ImmutableSet.Builder<String> apexFileNamesBuilder = ImmutableSet.builder();
for (ModuleEntry entry : module.getEntries()) {
ZipPath path = entry.getPath();
if (path.startsWith(APEX_DIRECTORY)) {
if (path.getFileName().toString().endsWith(BundleModule.APEX_IMAGE_SUFFIX)) {
apexImagesBuilder.add(path.toString());
apexFileNamesBuilder.add(path.getFileName().toString());
} else if (path.getFileName().toString().endsWith(BundleModule.BUILD_INFO_SUFFIX)) {
apexBuildInfosBuilder.add(path.toString());
} else {
throw InvalidBundleException.builder().withUserMessage("Unexpected file in apex directory of bundle: '%s'.", entry.getPath()).build();
}
} else if (!ALLOWED_APEX_FILES_OUTSIDE_APEX_DIRECTORY.contains(path)) {
throw InvalidBundleException.builder().withUserMessage("Unexpected file in APEX bundle: '%s'.", entry.getPath()).build();
}
}
ImmutableSet<String> apexBuildInfos = apexBuildInfosBuilder.build();
ImmutableSet<String> apexImages = apexImagesBuilder.build();
ImmutableSet<ImmutableSet<AbiName>> allAbiNameSets = apexFileNamesBuilder.build().stream().map(ApexBundleValidator::abiNamesFromFile).collect(toImmutableSet());
if (allAbiNameSets.size() != apexImages.size()) {
throw InvalidBundleException.builder().withUserMessage("Every APEX image file must target a unique set of architectures, " + "but found multiple files that target the same set of architectures.").build();
}
ImmutableSet<String> expectedImages = apexBuildInfos.stream().map(f -> f.replace(BundleModule.BUILD_INFO_SUFFIX, BundleModule.APEX_IMAGE_SUFFIX)).collect(toImmutableSet());
if (!apexBuildInfos.isEmpty() && !expectedImages.equals(apexImages)) {
throw InvalidBundleException.builder().withUserMessage("If APEX build info is provided then one must be provided for each APEX image file:\n" + " Expected %s\n" + " Found %s.", expectedImages, apexImages).build();
}
if (REQUIRED_ONE_OF_ABI_SETS.stream().anyMatch(one_of -> one_of.stream().noneMatch(allAbiNameSets::contains))) {
throw InvalidBundleException.builder().withUserMessage("APEX bundle must contain one of %s.", Joiner.on(" and one of ").join(REQUIRED_ONE_OF_ABI_SETS)).build();
}
module.getApexConfig().ifPresent(targeting -> validateTargeting(apexImages, targeting));
}
use of com.android.tools.build.bundletool.model.ModuleEntry in project bundletool by google.
the class SuffixStripper method removeAssetsTargeting.
/**
* Updates the module to remove the specified targeting from the assets - both the directories in
* assets config and the associated module entries having the specified targeting will be updated.
*/
public ModuleSplit removeAssetsTargeting(ModuleSplit moduleSplit) {
if (!moduleSplit.getAssetsConfig().isPresent()) {
return moduleSplit;
}
// Update the targeted assets directory and their associated entries.
Assets assetsConfig = moduleSplit.getAssetsConfig().get();
Assets.Builder updatedAssetsConfig = assetsConfig.toBuilder().clearDirectory();
ImmutableList<ModuleEntry> updatedEntries = moduleSplit.getEntries();
for (TargetedAssetsDirectory targetedAssetsDirectory : assetsConfig.getDirectoryList()) {
TargetedAssetsDirectory updatedTargetedAssetsDirectory = removeAssetsTargetingFromDirectory(targetedAssetsDirectory);
// Remove the targeting from the entries path.
if (!updatedTargetedAssetsDirectory.equals(targetedAssetsDirectory)) {
// Update the associated entries
ZipPath directoryPath = ZipPath.create(targetedAssetsDirectory.getPath());
updatedEntries = updatedEntries.stream().map(entry -> {
if (entry.getPath().startsWith(directoryPath)) {
return removeTargetingFromEntry(entry);
}
return entry;
}).collect(toImmutableList());
}
updatedAssetsConfig.addDirectory(updatedTargetedAssetsDirectory);
}
return moduleSplit.toBuilder().setEntries(updatedEntries).setAssetsConfig(updatedAssetsConfig.build()).build();
}
use of com.android.tools.build.bundletool.model.ModuleEntry in project bundletool by google.
the class SuffixStripper method excludeAssetsTargetingOtherValue.
/**
* Updates the module to remove the specified targeting from the assets: both the assets in assets
* config and the associated entries having the specified targeting will be updated.
*/
private ModuleSplit excludeAssetsTargetingOtherValue(ModuleSplit moduleSplit, String value) {
if (!moduleSplit.getAssetsConfig().isPresent()) {
return moduleSplit;
}
// Update the targeted assets directory and their associated entries.
Assets assetsConfig = moduleSplit.getAssetsConfig().get();
Assets.Builder updatedAssetsConfig = assetsConfig.toBuilder().clearDirectory();
ImmutableList<ModuleEntry> updatedEntries = moduleSplit.getEntries();
for (TargetedAssetsDirectory targetedAssetsDirectory : assetsConfig.getDirectoryList()) {
ZipPath directoryPath = ZipPath.create(targetedAssetsDirectory.getPath());
// Check if the directory is targeted at this dimension, but for another value.
if (dimensionHandler.isDirectoryTargetingOtherValue(targetedAssetsDirectory, value)) {
// Removed the associated entries if so.
updatedEntries = updatedEntries.stream().filter(entry -> !entry.getPath().startsWith(directoryPath)).collect(toImmutableList());
} else {
// Keep the directory otherwise.
updatedAssetsConfig.addDirectory(targetedAssetsDirectory);
}
}
return moduleSplit.toBuilder().setEntries(updatedEntries).setAssetsConfig(updatedAssetsConfig.build()).build();
}
use of com.android.tools.build.bundletool.model.ModuleEntry in project bundletool by google.
the class AbiNativeLibrariesSplitter method split.
/**
* Generates {@link ModuleSplit} objects dividing the native libraries by ABI.
*/
@Override
public ImmutableCollection<ModuleSplit> split(ModuleSplit moduleSplit) {
if (!moduleSplit.getNativeConfig().isPresent()) {
return ImmutableList.of(moduleSplit);
}
ImmutableList.Builder<ModuleSplit> splits = new ImmutableList.Builder<>();
// Flatten all targeted directories.
List<TargetedNativeDirectory> allTargetedDirectories = moduleSplit.getNativeConfig().get().getDirectoryList();
// Currently we only support targeting via ABI, so grouping it by Targeting.equals() should be
// enough.
ImmutableMultimap<NativeDirectoryTargeting, TargetedNativeDirectory> targetingMap = Multimaps.index(allTargetedDirectories, TargetedNativeDirectory::getTargeting);
// We need to know the exact set of ABIs that we will generate, to set alternatives correctly.
ImmutableSet<Abi> abisToGenerate = targetingMap.keySet().stream().map(NativeDirectoryTargeting::getAbi).collect(toImmutableSet());
// Any entries not claimed by the ABI splits will be returned in a separate split using the
// original targeting.
HashSet<ModuleEntry> leftOverEntries = new HashSet<>(moduleSplit.getEntries());
for (NativeDirectoryTargeting targeting : targetingMap.keySet()) {
ImmutableList<ModuleEntry> entriesList = targetingMap.get(targeting).stream().flatMap(directory -> moduleSplit.findEntriesUnderPath(directory.getPath())).collect(toImmutableList());
ModuleSplit.Builder splitBuilder = moduleSplit.toBuilder().setApkTargeting(moduleSplit.getApkTargeting().toBuilder().setAbiTargeting(AbiTargeting.newBuilder().addValue(targeting.getAbi()).addAllAlternatives(Sets.difference(abisToGenerate, ImmutableSet.of(targeting.getAbi())))).build()).setMasterSplit(false).addMasterManifestMutator(withSplitsRequired(true)).setEntries(entriesList);
splits.add(splitBuilder.build());
leftOverEntries.removeAll(entriesList);
}
if (!leftOverEntries.isEmpty()) {
splits.add(moduleSplit.toBuilder().setEntries(ImmutableList.copyOf(leftOverEntries)).build());
}
return splits.build();
}
use of com.android.tools.build.bundletool.model.ModuleEntry in project bundletool by google.
the class SanitizerNativeLibrariesSplitter method split.
/**
* Generates {@link ModuleSplit} objects dividing the native libraries by sanitizer.
*/
@Override
public ImmutableCollection<ModuleSplit> split(ModuleSplit moduleSplit) {
if (!moduleSplit.getNativeConfig().isPresent()) {
return ImmutableList.of(moduleSplit);
}
Set<ZipPath> hwasanDirs = new HashSet<>();
for (TargetedNativeDirectory dir : moduleSplit.getNativeConfig().get().getDirectoryList()) {
if (!dir.getTargeting().hasSanitizer()) {
continue;
}
if (dir.getTargeting().getSanitizer().getAlias().equals(SanitizerAlias.HWADDRESS)) {
hwasanDirs.add(ZipPath.create(dir.getPath()));
}
}
List<ModuleEntry> hwasanEntries = moduleSplit.getEntries().stream().filter(entry -> hwasanDirs.contains(entry.getPath().subpath(0, 2))).collect(toImmutableList());
if (hwasanEntries.isEmpty()) {
return ImmutableList.of(moduleSplit);
}
List<ModuleEntry> nonHwasanEntries = moduleSplit.getEntries().stream().filter(entry -> !hwasanDirs.contains(entry.getPath().subpath(0, 2))).collect(toImmutableList());
ModuleSplit hwasanSplit = moduleSplit.toBuilder().setApkTargeting(moduleSplit.getApkTargeting().toBuilder().setSanitizerTargeting(SanitizerTargeting.newBuilder().addValue(Sanitizer.newBuilder().setAlias(SanitizerAlias.HWADDRESS))).build()).setMasterSplit(false).setEntries(hwasanEntries).build();
ModuleSplit nonHwasanSplit = moduleSplit.toBuilder().setEntries(nonHwasanEntries).build();
return ImmutableList.of(hwasanSplit, nonHwasanSplit);
}
Aggregations