blob: d8975dc9902d7d84983357cd7c23daab59f3e798 [file] [log] [blame]
Jake Wharton2d7aab82019-09-13 10:24:26 -04001// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4package dx;
5
6import com.google.common.base.Optional;
7import java.io.File;
8import java.io.IOException;
9import java.io.UncheckedIOException;
10import java.util.ArrayList;
11import java.util.List;
12import java.util.Set;
13import javax.inject.Inject;
14import org.gradle.api.DefaultTask;
15import org.gradle.api.file.FileCollection;
16import org.gradle.api.tasks.Input;
17import org.gradle.api.tasks.InputFile;
18import org.gradle.api.tasks.InputFiles;
19import org.gradle.api.tasks.OutputDirectory;
20import org.gradle.api.tasks.TaskAction;
21import org.gradle.workers.IsolationMode;
22import org.gradle.workers.WorkerExecutor;
23import utils.Utils;
24
25public class DxTask extends DefaultTask {
26
27 private final WorkerExecutor workerExecutor;
28
29 private FileCollection source;
30 private File destination;
31 private Optional<File> dxExecutable = Optional.absent(); // Worker API cannot handle null.
32 private boolean debug;
33
34 @Inject
35 public DxTask(WorkerExecutor workerExecutor) {
36 this.workerExecutor = workerExecutor;
37 }
38
39 @InputFiles
40 public FileCollection getSource() {
41 return source;
42 }
43
44 public void setSource(FileCollection source) {
45 this.source = source;
46 }
47
48 @OutputDirectory
49 public File getDestination() {
50 return destination;
51 }
52
53 public void setDestination(File destination) {
54 this.destination = destination;
55 }
56
57 @InputFile
58 @org.gradle.api.tasks.Optional
59 public File getDxExecutable() {
60 return dxExecutable.orNull();
61 }
62
63 public void setDxExecutable(File dxExecutable) {
64 this.dxExecutable = Optional.fromNullable(dxExecutable);
65 }
66
67 @Input
68 public boolean isDebug() {
69 return debug;
70 }
71
72 public void setDebug(boolean debug) {
73 this.debug = debug;
74 }
75
76 @TaskAction
77 void exec() {
78 workerExecutor.submit(RunDx.class, config -> {
79 config.setIsolationMode(IsolationMode.NONE);
80 config.params(source.getFiles(), destination, dxExecutable, debug);
81 });
82 }
83
84 public static class RunDx implements Runnable {
85 private final Set<File> sources;
86 private final File destination;
87 private final Optional<File> dxExecutable;
88 private final boolean debug;
89
90 @Inject
91 public RunDx(Set<File> sources, File destination, Optional<File> dxExecutable, boolean debug) {
92 this.sources = sources;
93 this.destination = destination;
94 this.dxExecutable = dxExecutable;
95 this.debug = debug;
96 }
97
98 @Override
99 public void run() {
100 try {
101 List<String> command = new ArrayList<>();
102 command.add(dxExecutable.or(Utils::dxExecutable).getCanonicalPath());
103 command.add("--dex");
104 command.add("--output");
105 command.add(destination.getCanonicalPath());
106 if (debug) {
107 command.add("--debug");
108 }
109 for (File source : sources) {
110 command.add(source.getCanonicalPath());
111 }
112
113 Process dx = new ProcessBuilder(command).inheritIO().start();
114 int exitCode = dx.waitFor();
115 if (exitCode != 0) {
116 throw new RuntimeException("dx failed with code " + exitCode);
117 }
118 } catch (IOException e) {
119 throw new UncheckedIOException(e);
120 } catch (InterruptedException e) {
121 throw new RuntimeException(e);
122 }
123 }
124 }
125}