--- old/src/jdk.jextract/share/classes/com/sun/tools/jextract/JModWriter.java 2019-04-25 08:51:29.000000000 +0530 +++ new/src/jdk.jextract/share/classes/com/sun/tools/jextract/JModWriter.java 2019-04-25 08:51:28.000000000 +0530 @@ -29,19 +29,16 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashSet; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.logging.Level; import java.util.spi.ToolProvider; import java.util.logging.Logger; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.ModuleVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; // Utility class to generate a .jmod file public final class JModWriter { - private final Options options; - private final Log log; + private final Context ctx; private final Writer writer; private static ToolProvider findTool(String name) { @@ -53,20 +50,20 @@ return tp.get(); } + private static final ToolProvider JAVAC = findTool("javac"); private static final ToolProvider JMOD = findTool("jmod"); public JModWriter(Context ctx, Writer writer) { - this.options = ctx.options; - this.log = ctx.log; + this.ctx = ctx; this.writer = writer; } public void writeJModFile(Path jmodFile, String[] args) throws IOException { - if (options.targetPackage == null || options.targetPackage.isEmpty()) { + if (ctx.options.targetPackage == null || ctx.options.targetPackage.isEmpty()) { throw new IllegalArgumentException("no --target-package specified"); } - log.print(Level.INFO, () -> "Collecting jmod file " + jmodFile); + ctx.log.print(Level.INFO, () -> "Collecting jmod file " + jmodFile); String modName = jmodFile.getFileName().toString(); modName = modName.substring(0, modName.length() - 5 /* ".jmod".length() */); @@ -75,14 +72,14 @@ Path jmodRootDir = Files.createTempDirectory("jextract.jmod"); jmodRootDir.toFile().deleteOnExit(); - log.print(Level.INFO, () -> "Writing .class files"); + ctx.log.print(Level.INFO, () -> "Writing .class files"); // write .class files Path modClassesDir = jmodRootDir.resolve(modName); writer.writeClassFiles(modClassesDir, args); - log.print(Level.INFO, () -> "Generating module-info.class"); + ctx.log.print(Level.INFO, () -> "Generating module-info.class"); // generate module-info.class - generateModuleInfoClass(modClassesDir, modName); + generateModuleInfoClass(jmodRootDir, modClassesDir, modName); // copy libraries Path libsDir = jmodRootDir.resolve("libs"); @@ -92,40 +89,50 @@ generateJMod(modClassesDir, libsDir, jmodFile); } - private void generateModuleInfoClass(Path modClassesDir, String modName) throws IOException { + private void generateModuleInfoClass(Path jmodRootDir, Path modClassesDir, String modName) throws IOException { // collect package names final Set packages = new HashSet<>(); for (String cls : writer.results().keySet()) { - int idx = cls.lastIndexOf("/"); + int idx = cls.lastIndexOf("."); packages.add(cls.substring(0, idx)); } - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - cw.visit(Opcodes.V9, Opcodes.ACC_MODULE, "module-info", null, null, null); - - ModuleVisitor mv = cw.visitModule(modName, Opcodes.ACC_MANDATED, null); - mv.visitRequire("java.base", Opcodes.ACC_MANDATED, null); + // module-info.java source code string + StringBuilder modInfoCode = new StringBuilder(); + modInfoCode.append("module "); + modInfoCode.append(modName); + modInfoCode.append(" {\n"); for (String pkg : packages) { - mv.visitExport(pkg, Opcodes.ACC_MANDATED); - } - mv.visitEnd(); - - cw.visitEnd(); + modInfoCode.append(" exports "); + modInfoCode.append(pkg); + modInfoCode.append(";\n"); + } + modInfoCode.append("}"); + + // write module-info.java source in module directory + Files.write(modClassesDir.resolve("module-info.java"), List.of(modInfoCode.toString())); + + // compile module-info.java + int exitCode = JAVAC.run(ctx.log.getOut(), ctx.log.getErr(), + "--module-source-path", jmodRootDir.toString(), + "-d", jmodRootDir.toString(), + modClassesDir.resolve("module-info.java").toString()); - // write module-info.class source in module directory - Files.write(modClassesDir.resolve("module-info.class"), cw.toByteArray()); + if (exitCode != 0) { + throw new RuntimeException("module-info.class generation failed: " + exitCode); + } } private void copyNativeLibraries(Path libsDir) throws IOException { Files.createDirectory(libsDir); - if (!options.libraryNames.isEmpty()) { - if (options.libraryPaths.isEmpty()) { - log.printWarning("warn.no.library.paths.specified"); + if (!ctx.options.libraryNames.isEmpty()) { + if (ctx.options.libraryPaths.isEmpty()) { + ctx.log.printWarning("warn.no.library.paths.specified"); return; } - log.print(Level.INFO, () -> "Copying native libraries"); - Path[] paths = options.libraryPaths.stream().map(Paths::get).toArray(Path[]::new); - options.libraryNames.forEach(libName -> { + ctx.log.print(Level.INFO, () -> "Copying native libraries"); + Path[] paths = ctx.options.libraryPaths.stream().map(Paths::get).toArray(Path[]::new); + ctx.options.libraryNames.forEach(libName -> { Optional absPath = Utils.findLibraryPath(paths, libName); if (absPath.isPresent()) { Path libPath = absPath.get(); @@ -135,7 +142,7 @@ throw new UncheckedIOException(ioExp); } } else { - log.printWarning("warn.library.not.copied", libName); + ctx.log.printWarning("warn.library.not.copied", libName); } }); } @@ -143,8 +150,8 @@ private void generateJMod(Path classesDir, Path libsDir, Path jmodFile) throws IOException { - log.print(Level.INFO, () -> "Generating jmod file: " + jmodFile); - int exitCode = JMOD.run(log.getOut(), log.getErr(), "create", + ctx.log.print(Level.INFO, () -> "Generating jmod file: " + jmodFile); + int exitCode = JMOD.run(ctx.log.getOut(), ctx.log.getErr(), "create", "--class-path", classesDir.toString(), "--libs", libsDir.toString(), jmodFile.toString());