/* * Copyright (C) 2012 The Android Open Source Project * * 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.android.jack; import com.google.common.base.Joiner; import com.android.jack.backend.dex.DexFileWriter; import com.android.jack.backend.dex.MultiDexLegacy; import com.android.jack.backend.dex.rop.CodeItemBuilder; import com.android.jack.config.id.Arzon; import com.android.jack.config.id.JavaVersionPropertyId; import com.android.jack.config.id.Private; import com.android.jack.incremental.InputFilter; import com.android.jack.ir.ast.JMethod; import com.android.jack.library.ClasspathEntryCodec; import com.android.jack.library.InputJackLibrary; import com.android.jack.library.InputJackLibraryCodec; import com.android.jack.library.InputLibrary; import com.android.jack.meta.MetaImporter; import com.android.jack.reporting.Reportable.ProblemLevel; import com.android.jack.reporting.Reporter; import com.android.jack.resource.ResourceImporter; import com.android.jack.shrob.obfuscation.MappingPrinter; import com.android.jack.shrob.obfuscation.NameProviderFactory; import com.android.jack.shrob.obfuscation.Renamer; import com.android.jack.shrob.obfuscation.SourceFileRenamer; import com.android.jack.shrob.obfuscation.annotation.AnnotationRemover; import com.android.jack.shrob.obfuscation.annotation.ParameterAnnotationRemover; import com.android.jack.shrob.seed.SeedPrinter; import com.android.jack.shrob.spec.Flags; import com.android.jack.transformations.renamepackage.PackageRenamer; import com.android.jack.util.ClassNameCodec; import com.android.jack.util.filter.Filter; import com.android.sched.util.RunnableHooks; import com.android.sched.util.codec.CaseInsensitiveDirectFSCodec; import com.android.sched.util.codec.DirectDirOutputVFSCodec; import com.android.sched.util.codec.DirectoryCodec; import com.android.sched.util.codec.InputFileOrDirectoryCodec; import com.android.sched.util.codec.InputStreamOrDirectoryCodec; import com.android.sched.util.codec.ListCodec; import com.android.sched.util.codec.PairCodec; import com.android.sched.util.codec.PairCodec.Pair; import com.android.sched.util.codec.PairListToMapCodecConverter; import com.android.sched.util.codec.StringValueCodec; import com.android.sched.util.codec.VariableName; import com.android.sched.util.codec.ZipFSCodec; import com.android.sched.util.codec.ZipOutputVFSCodec; import com.android.sched.util.config.Config; import com.android.sched.util.config.ConfigurationException; import com.android.sched.util.config.GatherConfigBuilder; import com.android.sched.util.config.HasKeyId; import com.android.sched.util.config.PropertyIdException; import com.android.sched.util.config.id.BooleanPropertyId; import com.android.sched.util.config.id.EnumPropertyId; import com.android.sched.util.config.id.ImplementationPropertyId; import com.android.sched.util.config.id.ListPropertyId; import com.android.sched.util.config.id.ObjectId; import com.android.sched.util.config.id.PropertyId; import com.android.sched.util.config.id.ReflectFactoryPropertyId; import com.android.sched.util.file.Directory; import com.android.sched.util.file.FileOrDirectory; import com.android.sched.util.file.FileOrDirectory.ChangePermission; import com.android.sched.util.file.FileOrDirectory.Existence; import com.android.sched.util.file.FileOrDirectory.Permission; import com.android.sched.util.file.FileUtils; import com.android.sched.util.file.Files; import com.android.sched.util.file.NoSuchFileException; import com.android.sched.util.file.NotDirectoryException; import com.android.sched.util.file.OutputStreamFile; import com.android.sched.util.file.WrongPermissionException; import com.android.sched.util.location.FileLocation; import com.android.sched.util.location.NoLocation; import com.android.sched.util.location.StringLocation; import com.android.sched.util.log.LoggerFactory; import com.android.sched.util.log.TracerFactory; import com.android.sched.util.log.tracer.StatsTracerFtl; import com.android.sched.vfs.CachedDirectFS; import com.android.sched.vfs.Container; import com.android.sched.vfs.OutputVFS; import com.android.sched.vfs.VFS; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; import org.kohsuke.args4j.spi.ExplicitBooleanOptionHandler; import org.kohsuke.args4j.spi.MapOptionHandler; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; /** * Jack command line options Bean */ @HasKeyId public class Options { @Nonnull public static final BooleanPropertyId INCREMENTAL_MODE = BooleanPropertyId .create("jack.incremental", "Enable incremental mode") .addDefaultValue(Boolean.FALSE); @Nonnull public static final ReflectFactoryPropertyId INPUT_FILTER = ReflectFactoryPropertyId .create("jack.input.filter", "Inputs filter", InputFilter.class) .addDefaultValue("no-filter").addArgType(Options.class); @Nonnull public static final JavaVersionPropertyId JAVA_SOURCE_VERSION = JavaVersionPropertyId .create("jack.java.source.version", "Java source version").addDefaultValue("1.7") .withCategory(Arzon.get()); @Nonnull public static final BooleanPropertyId GENERATE_JACK_LIBRARY = BooleanPropertyId.create( "jack.library", "Generate jack library").addDefaultValue(Boolean.FALSE); @Nonnull public static final BooleanPropertyId GENERATE_DEX_FILE = BooleanPropertyId .create("jack.dex", "Generate dex file").addDefaultValue(Boolean.FALSE); @Nonnull public static final BooleanPropertyId GENERATE_DEX_IN_LIBRARY = BooleanPropertyId .create("jack.library.dex", "Generate dex files in library").addDefaultValue(Boolean.TRUE) .requiredIf(GENERATE_JACK_LIBRARY.getValue().isTrue()); @Nonnull public static final BooleanPropertyId GENERATE_JAYCE_IN_LIBRARY = BooleanPropertyId .create("jack.library.jayce", "Generate Jayce files in library") .addDefaultValue(Boolean.FALSE).withCategory(Private.get()) .requiredIf(GENERATE_JACK_LIBRARY.getValue().isTrue()); @Nonnull public static final BooleanPropertyId GENERATE_DEPENDENCIES_IN_LIBRARY = BooleanPropertyId .create("jack.library.dependencies", "Generate Dependency files in library") .addDefaultValue(Boolean.FALSE).withCategory(Private.get()) .requiredIf(GENERATE_JACK_LIBRARY.getValue().isTrue()); @Nonnull public static final BooleanPropertyId GENERATE_LIBRARY_FROM_INCREMENTAL_FOLDER = BooleanPropertyId.create( "jack.library.from-incremental-folder", "Generate a jack library from the incremental folder").addDefaultValue(Boolean.FALSE) .withCategory(Private.get()); @Nonnull public static final EnumPropertyId DEX_OUTPUT_CONTAINER_TYPE = EnumPropertyId .create("jack.dex.output.container", "Output container type", Container.class, Container.values()).ignoreCase().requiredIf(GENERATE_DEX_FILE.getValue().isTrue()); @Nonnull public static final EnumPropertyId LIBRARY_OUTPUT_CONTAINER_TYPE = EnumPropertyId .create("jack.library.output.container", "Library output container type", Container.class, Container.values()).ignoreCase().requiredIf(GENERATE_JACK_LIBRARY.getValue().isTrue()); @Nonnull public static final PropertyId LIBRARY_OUTPUT_ZIP = PropertyId.create( "jack.library.output.zip", "Output zip archive for library", new ZipFSCodec(Existence.MAY_EXIST)).requiredIf(GENERATE_JACK_LIBRARY.getValue().isTrue() .and(LIBRARY_OUTPUT_CONTAINER_TYPE.is(Container.ZIP)) .or(GENERATE_LIBRARY_FROM_INCREMENTAL_FOLDER.getValue().isTrue())); @Nonnull public static final PropertyId LIBRARY_OUTPUT_DIR = PropertyId.create( "jack.library.output.dir", "Output folder for library", new CaseInsensitiveDirectFSCodec(Existence.MUST_EXIST)).requiredIf(GENERATE_JACK_LIBRARY .getValue().isTrue().and(LIBRARY_OUTPUT_CONTAINER_TYPE.is(Container.DIR))); @Nonnull public static final PropertyId DEX_OUTPUT_DIR = PropertyId.create( "jack.dex.output.dir", "Output folder for dex", new DirectDirOutputVFSCodec(Existence.MUST_EXIST)).requiredIf( DEX_OUTPUT_CONTAINER_TYPE.is(Container.DIR)); @Nonnull public static final PropertyId DEX_OUTPUT_ZIP = PropertyId.create( "jack.dex.output.zip", "Output zip archive for dex", new ZipOutputVFSCodec(Existence.MAY_EXIST)).requiredIf( DEX_OUTPUT_CONTAINER_TYPE.is(Container.ZIP)); @Nonnull public static final ListPropertyId IMPORTED_LIBRARIES = new ListPropertyId("jack.library.import", "Libraries to import", new InputJackLibraryCodec()).minElements(0).addDefaultValue( Collections.emptyList()); @Nonnull public static final PropertyId> CLASSPATH = PropertyId.create( "jack.classpath", "Classpath", new ListCodec(new ClasspathEntryCodec()).setSeparator(File.pathSeparator) .setMin(0)).addDefaultValue(Collections.emptyList()); @Nonnull public static final BooleanPropertyId ENABLE_COMPILED_FILES_STATISTICS = BooleanPropertyId.create( "jack.statistic.source", "Enable compiled files statistics").addDefaultValue( Boolean.FALSE); @Nonnull public static final BooleanPropertyId ANNOTATION_PROCESSOR_ENABLED = BooleanPropertyId.create( "jack.annotation-processor", "Enable annotation processors") .addDefaultValue(true); @Option(name = "--version", usage = "display version") private boolean version; @Option(name = "--help", usage = "display help") private boolean help; @Option(name = "--help-properties", usage = "display properties list") private boolean helpProperties; @Option(name = "-D", metaVar = "=", usage = "set value for the given property (repeatable)", handler = MapOptionHandler.class) @Nonnull private final Map properties = new HashMap(); @Option(name = "-A", metaVar = "