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 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 86 public static OutputAnalyzer launchCompilerSimple(String... args) { 87 return launchJaotc(Arrays.asList(args), null); 88 } 89 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 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 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 and check its exit code 152 private static boolean checkLd(Path bin) { 153 try { 154 return 0 == ProcessTools.executeCommand(bin.toString(), "-v") 155 .getExitValue(); 156 } catch (Throwable t) { 157 // any errors mean ld doesn't work 158 return false; 159 } 160 } 161 162 public static String resolveLinker() { 163 Path linker = null; 164 // if non windows, 1st, check if PATH has ld 165 if (!Platform.isWindows()) { 166 String bin = "ld"; 167 for (String path : System.getenv("PATH").split(File.pathSeparator)) { 168 Path ld = Paths.get(path).resolve("ld"); 169 if (Files.exists(ld)) { 170 // there is ld in PATH 171 if (checkLd(ld)) { 172 System.out.println("found working linker: " + ld); 173 // ld works, jaotc is supposed to find and use it 174 return null; 175 } else { 176 System.out.println("found broken linker: " + ld); 177 // ld exists in PATH, but doesn't work, have to use devkit 178 break; 179 } 180 } 181 } 182 } 183 // there is no ld in PATH, will use ld from devkit 184 // artifacts are got from common/conf/jib-profiles.js 185 try { 186 if (Platform.isWindows()) { 187 if (Platform.isX64()) { 188 @Artifact(organization = "jpg.infra.builddeps", 189 name = "devkit-windows_x64", 190 revision = "VS2017-15.5.5+1.0", 191 extension = "tar.gz") 192 class DevkitWindowsX64 { } 193 String artifactName = "jpg.infra.builddeps." 194 + "devkit-windows_x64-" 195 + "VS2017-15.5.5+1.0"; 196 Path devkit = ArtifactResolver.resolve(DevkitWindowsX64.class) 197 .get(artifactName); 198 linker = devkit.resolve("VC") 199 .resolve("bin") 200 .resolve("x64") 201 .resolve("link.exe"); 202 } 203 } else if (Platform.isOSX()) { 204 @Artifact(organization = "jpg.infra.builddeps", 205 name = "devkit-macosx_x64", 206 revision = "Xcode6.3-MacOSX10.9+1.0", 207 extension = "tar.gz") 208 class DevkitMacosx { } 209 String artifactName = "jpg.infra.builddeps." 210 + "devkit-macosx_x64-" 211 + "Xcode6.3-MacOSX10.9+1.0"; 212 Path devkit = ArtifactResolver.resolve(DevkitMacosx.class) 213 .get(artifactName); 214 linker = devkit.resolve("Xcode.app") 215 .resolve("Contents") 216 .resolve("Developer") 217 .resolve("Toolchains") 218 .resolve("XcodeDefault.xctoolchain") 219 .resolve("usr") 220 .resolve("bin") 221 .resolve("ld"); 222 } else if (Platform.isLinux()) { 223 if (Platform.isAArch64()) { 224 @Artifact(organization = "jpg.infra.builddeps", 225 name = "devkit-linux_aarch64", 226 revision = "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0", 227 extension = "tar.gz") 228 class DevkitLinuxAArch64 { } 229 230 String artifactName = "jpg.infra.builddeps." 231 + "devkit-linux_aarch64-" 232 + "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0"; 233 Path devkit = ArtifactResolver.resolve(DevkitLinuxAArch64.class) 234 .get(artifactName); 235 linker = devkit.resolve("aarch64-linux-gnu") 236 .resolve("bin") 237 .resolve("ld"); 238 } else if (Platform.isARM()) { 239 @Artifact(organization = "jpg.infra.builddeps", 240 name = "devkit-linux_arm", 241 revision = "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0", 242 extension = "tar.gz") 243 class DevkitLinuxARM { } 244 245 String artifactName = "jpg.infra.builddeps." 246 + "devkit-linux_arm-" 247 + "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0"; 248 Path devkit = ArtifactResolver.resolve(DevkitLinuxARM.class) 249 .get(artifactName); 250 linker = devkit.resolve("arm-linux-gnueabihf") 251 .resolve("bin") 252 .resolve("ld"); 253 } else if (Platform.isX64()) { 254 @Artifact(organization = "jpg.infra.builddeps", 255 name = "devkit-linux_x64", 256 revision = "gcc7.3.0-OEL6.4+1.0", 257 extension = "tar.gz") 258 class DevkitLinuxX64 { } 259 260 String artifactName = "jpg.infra.builddeps." 261 + "devkit-linux_x64-" 262 + "gcc7.3.0-OEL6.4+1.0"; 263 Path devkit = ArtifactResolver.resolve(DevkitLinuxX64.class) 264 .get(artifactName); 265 linker = devkit.resolve("bin") 266 .resolve("ld"); 267 } 268 } 269 } catch (ArtifactResolverException e) { 270 System.err.println("artifact resolution error: " + e); 271 // let jaotc try to find linker 272 return null; 273 } 274 if (linker != null) { 275 return linker.toAbsolutePath().toString(); 276 } 277 return null; 278 } 279 }