1 /*
2  * Copyright (C) 2017 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 
17 package util.build;
18 
19 import com.android.tools.r8.CompilationMode;
20 import com.android.tools.r8.D8;
21 import com.android.tools.r8.D8Command;
22 import com.android.tools.r8.OutputMode;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.nio.file.Paths;
26 import java.nio.file.attribute.BasicFileAttributes;
27 
28 public class D8BuildStep extends BuildStep {
29 
30   private final boolean deleteInputFileAfterBuild;
31   private final D8Command.Builder builder;
32 
D8BuildStep(BuildFile inputFile, BuildFile outputFile, boolean deleteInputFileAfterBuild)33   D8BuildStep(BuildFile inputFile, BuildFile outputFile, boolean deleteInputFileAfterBuild) {
34     super(inputFile, outputFile);
35     this.deleteInputFileAfterBuild = deleteInputFileAfterBuild;
36     this.builder =
37         D8Command.builder()
38             .setMode(CompilationMode.DEBUG)
39             .setMinApiLevel(1000)
40             .setEnableDesugaring(false);
41   }
42 
43   @Override
build()44   boolean build() {
45 
46     if (super.build()) {
47       try {
48         builder.setOutput(Paths.get(outputFile.fileName.getAbsolutePath()), OutputMode.DexIndexed);
49         Files.find(
50                 Paths.get(inputFile.fileName.getAbsolutePath()),
51                 1000,
52                 D8BuildStep::isJarOrClassFile)
53             .forEach(
54                 p -> {
55                   try {
56                     builder.addProgramFiles(p);
57                   } catch (Throwable e) {
58                     e.printStackTrace();
59                   }
60                 });
61         D8.run(builder.build());
62       } catch (Throwable e) {
63         e.printStackTrace();
64         return false;
65       }
66       if (deleteInputFileAfterBuild) {
67         inputFile.fileName.delete();
68       }
69       return true;
70     }
71     return false;
72   }
73 
74   @Override
hashCode()75   public int hashCode() {
76     return inputFile.hashCode() ^ outputFile.hashCode();
77   }
78 
79   @Override
equals(Object obj)80   public boolean equals(Object obj) {
81     if (super.equals(obj)) {
82       D8BuildStep other = (D8BuildStep) obj;
83 
84       return inputFile.equals(other.inputFile) && outputFile.equals(other.outputFile);
85     }
86     return false;
87   }
88 
isJarOrClassFile(Path file, BasicFileAttributes attrs)89   private static boolean isJarOrClassFile(Path file, BasicFileAttributes attrs) {
90     if (!attrs.isRegularFile()) {
91       return false;
92     }
93     String name = file.getFileName().toString().toLowerCase();
94     return name.endsWith(".jar") || name.endsWith(".class");
95   }
96 }
97