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 (or ld -V on solaris) and check its exit code 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 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 }