/* * Copyright (C) 2017 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. */ #include "dex2oat_options.h" #include #include "cmdline_parser.h" #include "driver/compiler_options_map-inl.h" namespace art { template<> struct CmdlineType : CmdlineTypeParser { Result Parse(const std::string& option) { InstructionSet set = GetInstructionSetFromString(option.c_str()); if (set == InstructionSet::kNone) { return Result::Failure(std::string("Not a valid instruction set: '") + option + "'"); } return Result::Success(set); } static const char* Name() { return "InstructionSet"; } }; #define COMPILER_OPTIONS_MAP_TYPE Dex2oatArgumentMap #define COMPILER_OPTIONS_MAP_KEY_TYPE Dex2oatArgumentMapKey #include "driver/compiler_options_map-storage.h" // Specify storage for the Dex2oatOptions keys. #define DEX2OAT_OPTIONS_KEY(Type, Name, ...) \ const Dex2oatArgumentMap::Key Dex2oatArgumentMap::Name {__VA_ARGS__}; #include "dex2oat_options.def" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wframe-larger-than=" using M = Dex2oatArgumentMap; using Parser = CmdlineParser; using Builder = Parser::Builder; static void AddInputMappings(Builder& builder) { builder. Define("--dex-file=_") .WithType>().AppendValues() .IntoKey(M::DexFiles) .Define("--dex-location=_") .WithType>().AppendValues() .IntoKey(M::DexLocations) .Define("--zip-fd=_") .WithType() .IntoKey(M::ZipFd) .Define("--zip-location=_") .WithType() .IntoKey(M::ZipLocation) .Define("--boot-image=_") .WithType() .IntoKey(M::BootImage); } static void AddGeneratedArtifactMappings(Builder& builder) { builder. Define("--input-vdex-fd=_") .WithType() .IntoKey(M::InputVdexFd) .Define("--input-vdex=_") .WithType() .IntoKey(M::InputVdex) .Define("--output-vdex-fd=_") .WithType() .IntoKey(M::OutputVdexFd) .Define("--output-vdex=_") .WithType() .IntoKey(M::OutputVdex) .Define("--dm-fd=_") .WithType() .IntoKey(M::DmFd) .Define("--dm-file=_") .WithType() .IntoKey(M::DmFile) .Define("--oat-file=_") .WithType() .IntoKey(M::OatFile) .Define("--oat-symbols=_") .WithType() .IntoKey(M::OatSymbols) .Define("--strip") .IntoKey(M::Strip) .Define("--oat-fd=_") .WithType() .IntoKey(M::OatFd) .Define("--oat-location=_") .WithType() .IntoKey(M::OatLocation); } static void AddImageMappings(Builder& builder) { builder. Define("--image=_") .WithType() .IntoKey(M::ImageFilename) .Define("--image-fd=_") .WithType() .IntoKey(M::ImageFd) .Define("--base=_") .WithType() .IntoKey(M::Base) .Define("--app-image-file=_") .WithType() .IntoKey(M::AppImageFile) .Define("--app-image-fd=_") .WithType() .IntoKey(M::AppImageFileFd) .Define({"--multi-image", "--single-image"}) .WithValues({true, false}) .IntoKey(M::MultiImage) .Define("--dirty-image-objects=_") .WithType() .IntoKey(M::DirtyImageObjects) .Define("--updatable-bcp-packages-file=_") .WithType() .IntoKey(M::UpdatableBcpPackagesFile) .Define("--image-format=_") .WithType() .WithValueMap({{"lz4", ImageHeader::kStorageModeLZ4}, {"lz4hc", ImageHeader::kStorageModeLZ4HC}, {"uncompressed", ImageHeader::kStorageModeUncompressed}}) .IntoKey(M::ImageFormat); } static void AddSwapMappings(Builder& builder) { builder. Define("--swap-file=_") .WithType() .IntoKey(M::SwapFile) .Define("--swap-fd=_") .WithType() .IntoKey(M::SwapFileFd) .Define("--swap-dex-size-threshold=_") .WithType() .IntoKey(M::SwapDexSizeThreshold) .Define("--swap-dex-count-threshold=_") .WithType() .IntoKey(M::SwapDexCountThreshold); } static void AddCompilerMappings(Builder& builder) { builder. Define("--run-passes=_") .WithType() .IntoKey(M::Passes) .Define("--profile-file=_") .WithType() .IntoKey(M::Profile) .Define("--profile-file-fd=_") .WithType() .IntoKey(M::ProfileFd) .Define("--no-inline-from=_") .WithType() .IntoKey(M::NoInlineFrom); } static void AddTargetMappings(Builder& builder) { builder. Define("--instruction-set=_") .WithType() .IntoKey(M::TargetInstructionSet) .Define("--instruction-set-variant=_") .WithType() .IntoKey(M::TargetInstructionSetVariant) .Define("--instruction-set-features=_") .WithType() .IntoKey(M::TargetInstructionSetFeatures); } static Parser CreateArgumentParser() { std::unique_ptr parser_builder = std::make_unique(); AddInputMappings(*parser_builder); AddGeneratedArtifactMappings(*parser_builder); AddImageMappings(*parser_builder); AddSwapMappings(*parser_builder); AddCompilerMappings(*parser_builder); AddTargetMappings(*parser_builder); parser_builder-> Define({"--watch-dog", "--no-watch-dog"}) .WithValues({true, false}) .IntoKey(M::Watchdog) .Define("--watchdog-timeout=_") .WithType() .IntoKey(M::WatchdogTimeout) .Define("-j_") .WithType() .IntoKey(M::Threads) .Define("--cpu-set=_") .WithType>() .IntoKey(M::CpuSet) .Define("--android-root=_") .WithType() .IntoKey(M::AndroidRoot) .Define("--compiler-backend=_") .WithType() .WithValueMap({{"Quick", Compiler::Kind::kQuick}, {"Optimizing", Compiler::Kind::kOptimizing}}) .IntoKey(M::Backend) .Define("--host") .IntoKey(M::Host) .Define("--avoid-storing-invocation") .IntoKey(M::AvoidStoringInvocation) .Define("--very-large-app-threshold=_") .WithType() .IntoKey(M::VeryLargeAppThreshold) .Define("--force-determinism") .IntoKey(M::ForceDeterminism) .Define("--check-linkage-conditions") .IntoKey(M::CheckLinkageConditions) .Define("--crash-on-linkage-violation") .IntoKey(M::CrashOnLinkageViolation) .Define("--copy-dex-files=_") .WithType() .WithValueMap({{"true", linker::CopyOption::kOnlyIfCompressed}, {"false", linker::CopyOption::kNever}, {"always", linker::CopyOption::kAlways}}) .IntoKey(M::CopyDexFiles) .Define("--write-invocation-to=_") .WithType() .IntoKey(M::InvocationFile) .Define("--classpath-dir=_") .WithType() .IntoKey(M::ClasspathDir) .Define("--class-loader-context=_") .WithType() .IntoKey(M::ClassLoaderContext) .Define("--class-loader-context-fds=_") .WithType() .IntoKey(M::ClassLoaderContextFds) .Define("--stored-class-loader-context=_") .WithType() .IntoKey(M::StoredClassLoaderContext) .Define("--compact-dex-level=_") .WithType() .WithValueMap({{"none", CompactDexLevel::kCompactDexLevelNone}, {"fast", CompactDexLevel::kCompactDexLevelFast}}) .IntoKey(M::CompactDexLevel) .Define("--runtime-arg _") .WithType>().AppendValues() .IntoKey(M::RuntimeOptions) .Define("--compilation-reason=_") .WithType() .IntoKey(M::CompilationReason) .Define("--compile-individually") .IntoKey(M::CompileIndividually); AddCompilerOptionsArgumentParserOptions(*parser_builder); parser_builder->IgnoreUnrecognized(false); return parser_builder->Build(); } std::unique_ptr Dex2oatArgumentMap::Parse(int argc, const char** argv, std::string* error_msg) { Parser parser = CreateArgumentParser(); CmdlineResult parse_result = parser.Parse(argv, argc); if (!parse_result.IsSuccess()) { *error_msg = parse_result.GetMessage(); return nullptr; } return std::make_unique(parser.ReleaseArgumentsMap()); } #pragma GCC diagnostic pop } // namespace art