1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.platform.test.ravenwood.ravenizer 17 18 import com.android.hoststubgen.ArgIterator 19 import com.android.hoststubgen.ArgumentsException 20 import com.android.hoststubgen.SetOnce 21 import com.android.hoststubgen.ensureFileExists 22 import com.android.hoststubgen.log 23 import java.nio.file.Paths 24 import kotlin.io.path.exists 25 26 /** 27 * If this file exits, we also read options from it. This is "unsafe" because it could break 28 * incremental builds, if it sets any flag that affects the output file. 29 * (however, for now, there's no such options.) 30 * 31 * For example, to enable verbose logging, do `echo '-v' > ~/.raveniezr-unsafe` 32 * 33 * (but even the content of this file changes, soong won't rerun the command, so you need to 34 * remove the output first and then do a build again.) 35 */ 36 private val RAVENIZER_DOTFILE = System.getenv("HOME") + "/.raveniezr-unsafe" 37 38 class RavenizerOptions( 39 /** Input jar file*/ 40 var inJar: SetOnce<String> = SetOnce(""), 41 42 /** Output jar file */ 43 var outJar: SetOnce<String> = SetOnce(""), 44 45 /** Whether to enable test validation. */ 46 var enableValidation: SetOnce<Boolean> = SetOnce(true), 47 48 /** Whether the validation failure is fatal or not. */ 49 var fatalValidation: SetOnce<Boolean> = SetOnce(true), 50 51 /** Whether to remove mockito and dexmaker classes. */ 52 var stripMockito: SetOnce<Boolean> = SetOnce(false), 53 ) { 54 companion object { 55 parseArgsnull56 fun parseArgs(origArgs: Array<String>): RavenizerOptions { 57 val args = origArgs.toMutableList() 58 if (Paths.get(RAVENIZER_DOTFILE).exists()) { 59 log.i("Reading options from $RAVENIZER_DOTFILE") 60 args.add(0, "@$RAVENIZER_DOTFILE") 61 } 62 63 val ret = RavenizerOptions() 64 val ai = ArgIterator.withAtFiles(args.toTypedArray()) 65 66 while (true) { 67 val arg = ai.nextArgOptional() 68 if (arg == null) { 69 break 70 } 71 72 fun nextArg(): String = ai.nextArgRequired(arg) 73 74 if (log.maybeHandleCommandLineArg(arg) { nextArg() }) { 75 continue 76 } 77 try { 78 when (arg) { 79 // TODO: Write help 80 "-h", "--help" -> TODO("Help is not implemented yet") 81 82 "--in-jar" -> ret.inJar.set(nextArg()).ensureFileExists() 83 "--out-jar" -> ret.outJar.set(nextArg()) 84 85 "--enable-validation" -> ret.enableValidation.set(true) 86 "--disable-validation" -> ret.enableValidation.set(false) 87 88 "--fatal-validation" -> ret.fatalValidation.set(true) 89 "--no-fatal-validation" -> ret.fatalValidation.set(false) 90 91 "--strip-mockito" -> ret.stripMockito.set(true) 92 "--no-strip-mockito" -> ret.stripMockito.set(false) 93 94 else -> throw ArgumentsException("Unknown option: $arg") 95 } 96 } catch (e: SetOnce.SetMoreThanOnceException) { 97 throw ArgumentsException("Duplicate or conflicting argument found: $arg") 98 } 99 } 100 101 if (!ret.inJar.isSet) { 102 throw ArgumentsException("Required option missing: --in-jar") 103 } 104 if (!ret.outJar.isSet) { 105 throw ArgumentsException("Required option missing: --out-jar") 106 } 107 return ret 108 } 109 } 110 toStringnull111 override fun toString(): String { 112 return """ 113 RavenizerOptions{ 114 inJar=$inJar, 115 outJar=$outJar, 116 enableValidation=$enableValidation, 117 fatalValidation=$fatalValidation, 118 } 119 """.trimIndent() 120 } 121 } 122