blob: 6fd791924e2eb620136b7ccc7fa865f9df3dda71 [file] [log] [blame]
// 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.android;
import com.android.builder.core.VariantType;
import com.google.devtools.build.android.AndroidResourceProcessor.AaptConfigOptions;
import com.google.devtools.build.android.Converters.PathConverter;
import com.google.devtools.build.android.Converters.VariantTypeConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.ShellQuotedParamsFilePreProcessor;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* Action that processes resources for Databinding v2.
*/
public class AndroidDataBindingProcessingAction {
/** Flag specifications for this action. */
public static final class Options extends OptionsBase {
@Option(
name = "resource_root",
defaultValue = "null",
converter = PathConverter.class,
allowMultiple = true,
category = "input",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.UNKNOWN},
help = "Input resource root. A corresponding output resource root must be passed to "
+ "--output_resource_root. Multiple roots will be paired in the order they're passed.")
public List<Path> resourceRoots;
@Option(
name = "output_resource_directory",
defaultValue = "null",
converter = PathConverter.class,
category = "input",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.UNKNOWN},
help =
"The output resource directory. Input source roots will be appended to this to "
+ "create the output resource roots.")
public Path outputResourceDirectory;
@Option(
name = "packageType",
defaultValue = "DEFAULT",
converter = VariantTypeConverter.class,
category = "config",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.UNKNOWN},
help =
"Variant configuration type for packaging the resources."
+ " Acceptable values DEFAULT, LIBRARY, ANDROID_TEST, UNIT_TEST")
public VariantType packageType;
@Option(
name = "dataBindingInfoOut",
defaultValue = "null",
converter = PathConverter.class,
category = "output",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.UNKNOWN},
help = "Path to where data binding's layout info output should be written.")
public Path dataBindingInfoOut;
@Option(
name = "appId",
defaultValue = "null",
category = "config",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.UNKNOWN},
help = "The java package for the app.")
public String appId;
}
public static void main(String[] args) throws IOException {
OptionsParser optionsParser =
OptionsParser.builder()
.allowResidue(true)
.optionsClasses(
Options.class, AaptConfigOptions.class, ResourceProcessorCommonOptions.class)
.argsPreProcessor(new ShellQuotedParamsFilePreProcessor(FileSystems.getDefault()))
.build();
optionsParser.parseAndExitUponError(args);
Options options = optionsParser.getOptions(Options.class);
AaptConfigOptions aaptConfigOptions = optionsParser.getOptions(AaptConfigOptions.class);
if (options.dataBindingInfoOut == null) {
throw new IllegalArgumentException("--dataBindingInfoOut is required");
}
if (options.appId == null) {
throw new IllegalArgumentException("--appId is required");
}
if (options.outputResourceDirectory == null) {
throw new IllegalArgumentException("--output_resource_directory is required");
}
List<Path> resourceRoots = options.resourceRoots == null
? Collections.emptyList()
: options.resourceRoots;
try (ScopedTemporaryDirectory dataBindingInfoOutDir =
new ScopedTemporaryDirectory("android_data_binding_layout_info_tmp")) {
// 1. Process databinding resources for each source root.
for (Path resourceRoot : resourceRoots) {
AndroidResourceProcessor.processDataBindings(
options.outputResourceDirectory,
resourceRoot,
dataBindingInfoOutDir.getPath(),
options.appId,
/* shouldZipDataBindingInfo= */ false,
aaptConfigOptions.useDataBindingAndroidX);
}
// 2. Zip all the layout info files into one zip file.
try (ZipOutputStream layoutInfoZip =
new ZipOutputStream(Files.newOutputStream(options.dataBindingInfoOut));
Stream<Path> layoutInfos = Files.list(dataBindingInfoOutDir.getPath())) {
Iterator<Path> it = layoutInfos.iterator();
while (it.hasNext()) {
Path layoutInfo = it.next();
ZipEntry zipEntry = new ZipEntry(layoutInfo.getFileName().toString());
layoutInfoZip.putNextEntry(zipEntry);
Files.copy(layoutInfo, layoutInfoZip);
layoutInfoZip.closeEntry();
}
}
}
}
}