• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.tools.r8wrappers;
17 
18 import com.android.tools.r8.ArchiveProgramResourceProvider;
19 import com.android.tools.r8.CompilationFailedException;
20 import com.android.tools.r8.D8;
21 import com.android.tools.r8.D8Command;
22 import com.android.tools.r8.ParseFlagInfo;
23 import com.android.tools.r8.ParseFlagPrinter;
24 import com.android.tools.r8.Version;
25 import com.android.tools.r8.origin.Origin;
26 import com.android.tools.r8wrappers.utils.WrapperDiagnosticsHandler;
27 import com.android.tools.r8wrappers.utils.WrapperFlag;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.List;
34 
35 public class D8Wrapper {
36 
37   private static final String WRAPPER_STRING = "d8-aosp-wrapper";
38 
39   private static final Origin CLI_ORIGIN =
40       new Origin(Origin.root()) {
41         @Override
42         public String part() {
43           return WRAPPER_STRING;
44         }
45       };
46 
47   private static final String NO_DEX_FLAG = "--no-dex-input-jar";
48   private static final String INFO_FLAG = "--info";
getAdditionalFlagsInfo()49   private static List<ParseFlagInfo> getAdditionalFlagsInfo() {
50     return Arrays.asList(
51         new WrapperFlag(NO_DEX_FLAG, "Input archive with potential all dex code ignored."),
52         new WrapperFlag(INFO_FLAG, "Print the info-level log messages from the compiler."));
53   }
54 
getUsageMessage()55   private static String getUsageMessage() {
56     StringBuilder builder =
57         appendLines(
58             new StringBuilder(),
59             "Usage: d8 [options] [@<argfile>] <input-files>",
60             " where <input-files> are any combination of dex, class, zip, jar or apk files",
61             " and each <argfile> is a file containing additional arguments (one per line)",
62             " and options are:");
63     new ParseFlagPrinter()
64         .addFlags(D8Command.getParseFlagsInformation())
65         .addFlags(getAdditionalFlagsInfo())
66         .setIndent(2)
67         .appendLinesToBuilder(builder);
68     return builder.toString();
69   }
70 
appendLines(StringBuilder builder, String... lines)71   private static StringBuilder appendLines(StringBuilder builder, String... lines) {
72     for (String line : lines) {
73       builder.append(line).append(System.lineSeparator());
74     }
75     return builder;
76   }
77 
main(String[] args)78   public static void main(String[] args) throws CompilationFailedException {
79     D8Wrapper wrapper = new D8Wrapper();
80     String[] remainingArgs = wrapper.parseWrapperArguments(args);
81     D8Command.Builder builder = D8Command.parse(
82         remainingArgs, CLI_ORIGIN, wrapper.diagnosticsHandler);
83     if (builder.isPrintHelp()) {
84       System.out.println(getUsageMessage());
85       return;
86     }
87     if (builder.isPrintVersion()) {
88       System.out.println("D8(" + WRAPPER_STRING + ") " + Version.getVersionString());
89       return;
90     }
91     wrapper.applyWrapperArguments(builder);
92     R8Wrapper.applyCommonCompilerArguments(builder);
93     D8.run(builder.build());
94   }
95 
96   private WrapperDiagnosticsHandler diagnosticsHandler = new WrapperDiagnosticsHandler();
97   private boolean printInfoDiagnostics = false;
98   private List<Path> noDexArchives = new ArrayList<>();
99 
parseWrapperArguments(String[] args)100   private String[] parseWrapperArguments(String[] args) {
101     List<String> remainingArgs = new ArrayList<>();
102     for (int i = 0; i < args.length; i++) {
103       String arg = args[i];
104       switch (arg) {
105         case INFO_FLAG:
106           {
107             printInfoDiagnostics = true;
108             break;
109           }
110         case NO_DEX_FLAG:
111           {
112             if (++i >= args.length) {
113               throw new RuntimeException("Missing argument to " + NO_DEX_FLAG);
114             }
115             Path path = Paths.get(args[i]);
116             if (!Files.isRegularFile(path)) {
117               throw new RuntimeException("Unexpected argument to " + NO_DEX_FLAG + ". Expected an archive");
118             }
119             noDexArchives.add(path);
120             break;
121           }
122         default:
123           {
124             remainingArgs.add(arg);
125             break;
126           }
127       }
128     }
129     return remainingArgs.toArray(new String[0]);
130   }
131 
applyWrapperArguments(D8Command.Builder builder)132   private void applyWrapperArguments(D8Command.Builder builder) {
133     diagnosticsHandler.setWarnOnUnsupportedMainDexList(true);
134     diagnosticsHandler.setPrintInfoDiagnostics(printInfoDiagnostics);
135     for (Path path : noDexArchives) {
136       builder.addProgramResourceProvider(
137           ArchiveProgramResourceProvider.fromArchive(
138               path,
139               ArchiveProgramResourceProvider::includeClassFileEntries));
140     }
141   }
142 }
143