1 /*
2  * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package compiler.aot;
25 
26 import jdk.test.lib.Platform;
27 import jdk.test.lib.artifacts.Artifact;
28 import jdk.test.lib.artifacts.ArtifactResolver;
29 import jdk.test.lib.artifacts.ArtifactResolverException;
30 import jdk.test.lib.process.OutputAnalyzer;
31 import java.io.File;
32 import java.io.IOException;
33 import java.lang.annotation.Annotation;
34 import java.nio.file.Files;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.nio.file.StandardOpenOption;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
41 import jdk.test.lib.JDKToolLauncher;
42 import jdk.test.lib.Utils;
43 import jdk.test.lib.process.ProcessTools;
44 
45 /**
46  * A simple class calling AOT compiler over requested items
47  */
48 public class AotCompiler {
49 
50     private final static String METHODS_LIST_FILENAME = "methodsList.txt";
51 
main(String args[])52     public static void main(String args[]) {
53         String className = null;
54         List<String> compileList = new ArrayList<>();
55         String libName = null;
56         List<String> extraopts = new ArrayList<>();
57         for (int i = 0; i < args.length; i++) {
58             switch (args[i]) {
59                 case "-class":
60                     className = args[++i];
61                     break;
62                 case "-compile":
63                     compileList.add("compileOnly " + args[++i]);
64                     break;
65                 case "-libname":
66                     libName = args[++i];
67                     break;
68                 case "-extraopt":
69                     extraopts.add(args[++i]);
70                     break;
71                 default:
72                     throw new Error("Unknown option: " + args[i]);
73             }
74         }
75         extraopts.add("-classpath");
76         extraopts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
77         if (className != null && libName != null) {
78             OutputAnalyzer oa = launchCompiler(libName, className, extraopts, compileList);
79             oa.shouldHaveExitValue(0);
80         } else {
81             printUsage();
82             throw new Error("Mandatory arguments aren't passed");
83         }
84     }
85 
launchCompilerSimple(String... args)86     public static OutputAnalyzer launchCompilerSimple(String... args) {
87         return launchJaotc(Arrays.asList(args), null);
88     }
89 
launchCompiler(String libName, String item, List<String> extraopts, List<String> compList)90     public static OutputAnalyzer launchCompiler(String libName, String item, List<String> extraopts,
91             List<String> compList) {
92         Path file = null;
93         if (compList != null && !compList.isEmpty()) {
94             file = Paths.get(METHODS_LIST_FILENAME);
95             try {
96                 Files.write(file, compList, StandardOpenOption.CREATE);
97             } catch (IOException e) {
98                 throw new Error("Couldn't write " + METHODS_LIST_FILENAME + " " + e, e);
99             }
100         }
101         List<String> args = new ArrayList<>();
102         args.add("--compile-with-assertions");
103         args.add("--info");
104         args.add("--output");
105         args.add(libName);
106         if (file != null) {
107             args.add("--compile-commands");
108             args.add(file.toString());
109         }
110         args.add("--class-name");
111         args.add(item);
112         String linker = resolveLinker();
113         if (linker != null) {
114             args.add("--linker-path");
115             args.add(linker);
116         }
117         // Execute with asserts
118         args.add("-J-ea");
119         args.add("-J-esa");
120         // we don't want to run jaotc w/ Xcomp even if it's in extraopts
121         args.add("-J-Xmixed");
122         return launchJaotc(args, extraopts);
123     }
124 
launchJaotc(List<String> args, List<String> extraVmOpts)125     private static OutputAnalyzer launchJaotc(List<String> args, List<String> extraVmOpts) {
126         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jaotc");
127         for (String vmOpt : Utils.getTestJavaOpts()) {
128             launcher.addVMArg(vmOpt);
129         }
130         if (extraVmOpts != null) {
131             for (String vmOpt : extraVmOpts) {
132                 launcher.addVMArg(vmOpt);
133             }
134         }
135         for (String arg : args) {
136             launcher.addToolArg(arg);
137         }
138         try {
139             return ProcessTools.executeCommand(new ProcessBuilder(launcher.getCommand()).redirectErrorStream(true));
140         } catch (Throwable e) {
141             throw new Error("Can't start test process: " + e, e);
142         }
143     }
144 
printUsage()145     public static void printUsage() {
146         System.err.println("Usage: " + AotCompiler.class.getName()
147                 + " -class <class> -libname <.so name>"
148                 + " [-compile <compileItems>]* [-extraopt <java option>]*");
149     }
150 
151     // runs ld -v (or ld -V on solaris) and check its exit code
checkLd(Path bin)152     private static boolean checkLd(Path bin) {
153         try {
154             return 0 == ProcessTools.executeCommand(bin.toString(),
155                                                     Platform.isSolaris() ? "-V" : "-v")
156                                     .getExitValue();
157         } catch (Throwable t) {
158             // any errors mean ld doesn't work
159             return false;
160         }
161     }
162 
resolveLinker()163     public static String resolveLinker() {
164         Path linker = null;
165         // if non windows, 1st, check if PATH has ld
166         if (!Platform.isWindows()) {
167             String bin = "ld";
168             for (String path : System.getenv("PATH").split(File.pathSeparator)) {
169                 Path ld = Paths.get(path).resolve("ld");
170                 if (Files.exists(ld)) {
171                     // there is ld in PATH
172                     if (checkLd(ld)) {
173                         System.out.println("found working linker: " + ld);
174                         // ld works, jaotc is supposed to find and use it
175                         return null;
176                     } else {
177                         System.out.println("found broken linker: " + ld);
178                         // ld exists in PATH, but doesn't work, have to use devkit
179                         break;
180                     }
181                 }
182             }
183         }
184         // there is no ld in PATH, will use ld from devkit
185         // artifacts are got from common/conf/jib-profiles.js
186         try {
187             if (Platform.isWindows()) {
188                 if (Platform.isX64()) {
189                     @Artifact(organization = "jpg.infra.builddeps",
190                             name = "devkit-windows_x64",
191                             revision = "VS2017-15.5.5+1.0",
192                             extension = "tar.gz")
193                     class DevkitWindowsX64 { }
194                     String artifactName = "jpg.infra.builddeps."
195                             + "devkit-windows_x64-"
196                             + "VS2017-15.5.5+1.0";
197                     Path devkit = ArtifactResolver.resolve(DevkitWindowsX64.class)
198                                                   .get(artifactName);
199                     linker = devkit.resolve("VC")
200                                    .resolve("bin")
201                                    .resolve("x64")
202                                    .resolve("link.exe");
203                 }
204             } else if (Platform.isOSX()) {
205                 @Artifact(organization =  "jpg.infra.builddeps",
206                         name = "devkit-macosx_x64",
207                         revision = "Xcode6.3-MacOSX10.9+1.0",
208                         extension = "tar.gz")
209                 class DevkitMacosx { }
210                 String artifactName = "jpg.infra.builddeps."
211                         + "devkit-macosx_x64-"
212                         + "Xcode6.3-MacOSX10.9+1.0";
213                 Path devkit = ArtifactResolver.resolve(DevkitMacosx.class)
214                                               .get(artifactName);
215                 linker = devkit.resolve("Xcode.app")
216                                .resolve("Contents")
217                                .resolve("Developer")
218                                .resolve("Toolchains")
219                                .resolve("XcodeDefault.xctoolchain")
220                                .resolve("usr")
221                                .resolve("bin")
222                                .resolve("ld");
223             } else if (Platform.isSolaris()) {
224                 if (Platform.isSparc()) {
225                     @Artifact(organization =  "jpg.infra.builddeps",
226                             name = "devkit-solaris_sparcv9",
227                             revision = "SS12u4-Solaris11u1+1.1",
228                             extension = "tar.gz")
229                     class DevkitSolarisSparc { }
230 
231                     String artifactName = "jpg.infra.builddeps."
232                             + "devkit-solaris_sparcv9-"
233                             + "SS12u4-Solaris11u1+1.1";
234                     Path devkit = ArtifactResolver.resolve(DevkitSolarisSparc.class)
235                                                   .get(artifactName);
236                     linker = devkit.resolve("SS12u4-Solaris11u1")
237                                    .resolve("gnu")
238                                    .resolve("bin")
239                                    .resolve("ld");
240                 } else if (Platform.isX64()) {
241                     @Artifact(organization =  "jpg.infra.builddeps",
242                             name = "devkit-solaris_x64",
243                             revision = "SS12u4-Solaris11u1+1.0",
244                             extension = "tar.gz")
245                     class DevkitSolarisX64 { }
246 
247                     String artifactName = "jpg.infra.builddeps."
248                             + "devkit-solaris_x64-"
249                             + "SS12u4-Solaris11u1+1.0";
250                     Path devkit = ArtifactResolver.resolve(DevkitSolarisX64.class)
251                                                   .get(artifactName);
252                     linker = devkit.resolve("SS12u4-Solaris11u1")
253                                    .resolve("bin")
254                                    .resolve("amd64")
255                                    .resolve("ld");
256                 }
257             } else if (Platform.isLinux()) {
258                 if (Platform.isAArch64()) {
259                     @Artifact(organization = "jpg.infra.builddeps",
260                             name = "devkit-linux_aarch64",
261                             revision = "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0",
262                             extension = "tar.gz")
263                     class DevkitLinuxAArch64 { }
264 
265                     String artifactName = "jpg.infra.builddeps."
266                             + "devkit-linux_aarch64-"
267                             + "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0";
268                     Path devkit = ArtifactResolver.resolve(DevkitLinuxAArch64.class)
269                                                   .get(artifactName);
270                     linker = devkit.resolve("aarch64-linux-gnu")
271                                    .resolve("bin")
272                                    .resolve("ld");
273                 } else if (Platform.isARM()) {
274                     @Artifact(organization = "jpg.infra.builddeps",
275                             name = "devkit-linux_arm",
276                             revision = "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0",
277                             extension = "tar.gz")
278                     class DevkitLinuxARM { }
279 
280                     String artifactName = "jpg.infra.builddeps."
281                             + "devkit-linux_arm-"
282                             + "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0";
283                     Path devkit = ArtifactResolver.resolve(DevkitLinuxARM.class)
284                                                   .get(artifactName);
285                     linker = devkit.resolve("arm-linux-gnueabihf")
286                                    .resolve("bin")
287                                    .resolve("ld");
288                 } else if (Platform.isX64()) {
289                     @Artifact(organization = "jpg.infra.builddeps",
290                             name = "devkit-linux_x64",
291                             revision = "gcc7.3.0-OEL6.4+1.0",
292                             extension = "tar.gz")
293                     class DevkitLinuxX64 { }
294 
295                     String artifactName = "jpg.infra.builddeps."
296                             + "devkit-linux_x64-"
297                             + "gcc7.3.0-OEL6.4+1.0";
298                     Path devkit = ArtifactResolver.resolve(DevkitLinuxX64.class)
299                                                   .get(artifactName);
300                     linker = devkit.resolve("bin")
301                                    .resolve("ld");
302                 }
303             }
304         } catch (ArtifactResolverException e) {
305             System.err.println("artifact resolution error: " + e);
306             // let jaotc try to find linker
307             return null;
308         }
309         if (linker != null) {
310             return linker.toAbsolutePath().toString();
311         }
312         return null;
313     }
314 }
315