void ProcessOptions()

in dex2oat/dex2oat.cc [679:903]


  void ProcessOptions(ParserOptions* parser_options) {
    boot_image_ = !image_filenames_.empty();
    app_image_ = app_image_fd_ != -1 || !app_image_file_name_.empty();

    if (IsAppImage() && IsBootImage()) {
      Usage("Can't have both --image and (--app-image-fd or --app-image-file)");
    }

    if (IsBootImage()) {
      // We need the boot image to always be debuggable.
      // TODO: Remove this once we better deal with full frame deoptimization.
      compiler_options_->debuggable_ = true;
    }

    if (oat_filenames_.empty() && oat_fd_ == -1) {
      Usage("Output must be supplied with either --oat-file or --oat-fd");
    }

    if (!oat_filenames_.empty() && oat_fd_ != -1) {
      Usage("--oat-file should not be used with --oat-fd");
    }

    if (!parser_options->oat_symbols.empty() && oat_fd_ != -1) {
      Usage("--oat-symbols should not be used with --oat-fd");
    }

    if (!parser_options->oat_symbols.empty() && is_host_) {
      Usage("--oat-symbols should not be used with --host");
    }

    if (oat_fd_ != -1 && !image_filenames_.empty()) {
      Usage("--oat-fd should not be used with --image");
    }

    if (!parser_options->oat_symbols.empty() &&
        parser_options->oat_symbols.size() != oat_filenames_.size()) {
      Usage("--oat-file arguments do not match --oat-symbols arguments");
    }

    if (!image_filenames_.empty() && image_filenames_.size() != oat_filenames_.size()) {
      Usage("--oat-file arguments do not match --image arguments");
    }

    if (android_root_.empty()) {
      const char* android_root_env_var = getenv("ANDROID_ROOT");
      if (android_root_env_var == nullptr) {
        Usage("--android-root unspecified and ANDROID_ROOT not set");
      }
      android_root_ += android_root_env_var;
    }

    if (!boot_image_ && parser_options->boot_image_filename.empty()) {
      parser_options->boot_image_filename += android_root_;
      parser_options->boot_image_filename += "/framework/boot.art";
    }
    if (!parser_options->boot_image_filename.empty()) {
      boot_image_filename_ = parser_options->boot_image_filename;
    }

    if (image_classes_filename_ != nullptr && !IsBootImage()) {
      Usage("--image-classes should only be used with --image");
    }

    if (image_classes_filename_ != nullptr && !boot_image_filename_.empty()) {
      Usage("--image-classes should not be used with --boot-image");
    }

    if (image_classes_zip_filename_ != nullptr && image_classes_filename_ == nullptr) {
      Usage("--image-classes-zip should be used with --image-classes");
    }

    if (compiled_classes_filename_ != nullptr && !IsBootImage()) {
      Usage("--compiled-classes should only be used with --image");
    }

    if (compiled_classes_filename_ != nullptr && !boot_image_filename_.empty()) {
      Usage("--compiled-classes should not be used with --boot-image");
    }

    if (compiled_classes_zip_filename_ != nullptr && compiled_classes_filename_ == nullptr) {
      Usage("--compiled-classes-zip should be used with --compiled-classes");
    }

    if (dex_filenames_.empty() && zip_fd_ == -1) {
      Usage("Input must be supplied with either --dex-file or --zip-fd");
    }

    if (!dex_filenames_.empty() && zip_fd_ != -1) {
      Usage("--dex-file should not be used with --zip-fd");
    }

    if (!dex_filenames_.empty() && !zip_location_.empty()) {
      Usage("--dex-file should not be used with --zip-location");
    }

    if (dex_locations_.empty()) {
      for (const char* dex_file_name : dex_filenames_) {
        dex_locations_.push_back(dex_file_name);
      }
    } else if (dex_locations_.size() != dex_filenames_.size()) {
      Usage("--dex-location arguments do not match --dex-file arguments");
    }

    if (!dex_filenames_.empty() && !oat_filenames_.empty()) {
      if (oat_filenames_.size() != 1 && oat_filenames_.size() != dex_filenames_.size()) {
        Usage("--oat-file arguments must be singular or match --dex-file arguments");
      }
    }

    if (zip_fd_ != -1 && zip_location_.empty()) {
      Usage("--zip-location should be supplied with --zip-fd");
    }

    if (boot_image_filename_.empty()) {
      if (image_base_ == 0) {
        Usage("Non-zero --base not specified");
      }
    }

    const bool have_profile_file = !profile_file_.empty();
    const bool have_profile_fd = profile_file_fd_ != kInvalidFd;
    if (have_profile_file && have_profile_fd) {
      Usage("Profile file should not be specified with both --profile-file-fd and --profile-file");
    }

    if (!parser_options->oat_symbols.empty()) {
      oat_unstripped_ = std::move(parser_options->oat_symbols);
    }

    // If no instruction set feature was given, use the default one for the target
    // instruction set.
    if (instruction_set_features_.get() == nullptr) {
      instruction_set_features_.reset(
          InstructionSetFeatures::FromVariant(
              instruction_set_, "default", &parser_options->error_msg));
      if (instruction_set_features_.get() == nullptr) {
        Usage("Problem initializing default instruction set features variant: %s",
              parser_options->error_msg.c_str());
      }
    }

    if (instruction_set_ == kRuntimeISA) {
      std::unique_ptr<const InstructionSetFeatures> runtime_features(
          InstructionSetFeatures::FromCppDefines());
      if (!instruction_set_features_->Equals(runtime_features.get())) {
        LOG(WARNING) << "Mismatch between dex2oat instruction set features ("
            << *instruction_set_features_ << ") and those of dex2oat executable ("
            << *runtime_features <<") for the command line:\n"
            << CommandLine();
      }
    }

    // It they are not set, use default values for inlining settings.
    // TODO: We should rethink the compiler filter. We mostly save
    // time here, which is orthogonal to space.
    if (compiler_options_->inline_depth_limit_ == CompilerOptions::kUnsetInlineDepthLimit) {
      compiler_options_->inline_depth_limit_ =
          (compiler_options_->compiler_filter_ == CompilerFilter::kSpace)
          // Implementation of the space filter: limit inlining depth.
          ? CompilerOptions::kSpaceFilterInlineDepthLimit
          : CompilerOptions::kDefaultInlineDepthLimit;
    }
    if (compiler_options_->inline_max_code_units_ == CompilerOptions::kUnsetInlineMaxCodeUnits) {
      compiler_options_->inline_max_code_units_ =
          (compiler_options_->compiler_filter_ == CompilerFilter::kSpace)
          // Implementation of the space filter: limit inlining max code units.
          ? CompilerOptions::kSpaceFilterInlineMaxCodeUnits
          : CompilerOptions::kDefaultInlineMaxCodeUnits;
    }

    // Checks are all explicit until we know the architecture.
    // Set the compilation target's implicit checks options.
    switch (instruction_set_) {
      case kArm:
      case kThumb2:
      case kArm64:
      case kX86:
      case kX86_64:
      case kMips:
      case kMips64:
        compiler_options_->implicit_null_checks_ = true;
        compiler_options_->implicit_so_checks_ = true;
        break;

      default:
        // Defaults are correct.
        break;
    }

    compiler_options_->verbose_methods_ = verbose_methods_.empty() ? nullptr : &verbose_methods_;

    if (!IsBootImage() && multi_image_) {
      Usage("--multi-image can only be used when creating boot images");
    }
    if (IsBootImage() && multi_image_ && image_filenames_.size() > 1) {
      Usage("--multi-image cannot be used with multiple image names");
    }

    // For now, if we're on the host and compile the boot image, *always* use multiple image files.
    if (!kIsTargetBuild && IsBootImage()) {
      if (image_filenames_.size() == 1) {
        multi_image_ = true;
      }
    }

    // Done with usage checks, enable watchdog if requested
    if (parser_options->watch_dog_enabled) {
      watchdog_.reset(new WatchDog(true));
    }

    // Fill some values into the key-value store for the oat header.
    key_value_store_.reset(new SafeMap<std::string, std::string>());

    // Automatically force determinism for the boot image in a host build if the default GC is CMS
    // or MS and read barriers are not enabled, as the former switches the GC to a non-concurrent
    // one by passing the option `-Xgc:nonconcurrent` (see below).
    if (!kIsTargetBuild && IsBootImage()) {
      if (SupportsDeterministicCompilation()) {
        force_determinism_ = true;
      } else {
        LOG(WARNING) << "Deterministic compilation is disabled.";
      }
    }
    compiler_options_->force_determinism_ = force_determinism_;
  }