< prev index next >

src/jdk.jextract/share/classes/com/sun/tools/jextract/Context.java

Print this page




   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 package com.sun.tools.jextract;
  24 
  25 import jdk.internal.clang.*;
  26 import jdk.internal.foreign.LibrariesHelper;
  27 

  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.io.OutputStream;
  31 import java.io.PrintWriter;
  32 import java.io.UncheckedIOException;
  33 import java.lang.invoke.MethodHandles;
  34 import java.foreign.Library;
  35 import java.nio.file.Files;
  36 import java.nio.file.Path;
  37 import java.util.ArrayList;
  38 import java.util.Arrays;
  39 import java.util.Collections;
  40 import java.util.HashMap;
  41 import java.util.List;
  42 import java.util.Map;

  43 import java.util.Set;
  44 import java.util.TreeSet;
  45 import java.util.function.Function;
  46 import java.util.function.Predicate;
  47 import java.util.jar.JarOutputStream;
  48 import java.util.logging.Logger;
  49 import java.util.regex.Pattern;
  50 import java.util.stream.Collectors;
  51 import java.util.zip.ZipEntry;
  52 
  53 import static java.nio.file.StandardOpenOption.CREATE;
  54 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
  55 import static java.nio.file.StandardOpenOption.WRITE;
  56 
  57 /**
  58  * The setup for the tool execution
  59  */
  60 public final class Context {
  61     // package name to TypeDictionary
  62     private final Map<String, TypeDictionary> tdMap;
  63     // The folder path mapping to package name
  64     private final Map<Path, String> pkgMap;
  65     // The header file parsed
  66     private final Map<Path, HeaderFile> headerMap;
  67     // The args for parsing C
  68     private final List<String> clangArgs;
  69     // The set of source header files
  70     private final Set<Path>  sources;
  71     // The list of library names
  72     private final List<String> libraryNames;
  73     // The list of library paths
  74     private final List<String> libraryPaths;
  75     // The list of library paths for link checks
  76     private final List<String> linkCheckPaths;
  77     // Symbol patterns to be excluded
  78     private final List<Pattern> excludeSymbols;
  79 
  80     final PrintWriter out;
  81     final PrintWriter err;

  82 
  83     private Predicate<String> symChecker;
  84     private Predicate<String> symFilter;
  85 
  86     private final MacroParser macroParser;
  87 
  88     private final static String defaultPkg = "jextract.dump";
  89     final Logger logger = Logger.getLogger(getClass().getPackage().getName());
  90 
  91     public Context(PrintWriter out, PrintWriter err) {
  92         this.tdMap = new HashMap<>();
  93         this.pkgMap = new HashMap<>();
  94         this.headerMap = new HashMap<>();
  95         this.clangArgs = new ArrayList<>();
  96         this.sources = new TreeSet<>();
  97         this.libraryNames = new ArrayList<>();
  98         this.libraryPaths = new ArrayList<>();
  99         this.linkCheckPaths = new ArrayList<>();
 100         this.excludeSymbols = new ArrayList<>();
 101         this.macroParser = new MacroParser();
 102         this.out = out;
 103         this.err = err;

 104     }
 105 
 106     public Context() {
 107         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true));
 108     }
 109 
 110     TypeDictionary typeDictionaryFor(String pkg) {
 111         return tdMap.computeIfAbsent(pkg, p->new TypeDictionary(this, p));
 112     }
 113 
 114     void addClangArg(String arg) {
 115         clangArgs.add(arg);
 116     }
 117 
 118     public void addSource(Path path) {
 119         sources.add(path);
 120     }
 121 
 122     void addLibraryName(String name) {
 123         libraryNames.add(name);
 124     }
 125 
 126     void addLibraryPath(String path) {
 127         libraryPaths.add(path);


 419                 logger.config(() -> "File " + header + " code generation is not activated!");
 420                 return;
 421             }
 422             List<AsmCodeFactory> l = mapPkgCf.computeIfAbsent(pkg, k -> new ArrayList<>());
 423             l.add(cf);
 424             logger.config(() -> "Add cf " + cf + " to pkg " + pkg + ", size is now " + l.size());
 425         });
 426         return Collections.unmodifiableMap(mapPkgCf);
 427     }
 428 
 429     public Map<String, byte[]> collectClasses(String... pkgs) {
 430         final Map<String, byte[]> rv = new HashMap<>();
 431         final Map<String, List<AsmCodeFactory>> mapPkgCf = getPkgCfMap();
 432         for (String pkg_name : pkgs) {
 433             mapPkgCf.getOrDefault(pkg_name, Collections.emptyList())
 434                     .forEach(cf -> rv.putAll(cf.collect()));
 435         }
 436         return Collections.unmodifiableMap(rv);
 437     }
 438 














 439     void collectClassFiles(Path destDir, String... pkgs) throws IOException {
 440         try {
 441             collectClasses(pkgs).entrySet().stream().forEach(e -> {
 442                 try {
 443                     String path = e.getKey().replace('.', File.separatorChar) + ".class";
 444                     logger.fine(() -> "Writing " + path);
 445                     Path fullPath = destDir.resolve(path).normalize();
 446                     Files.createDirectories(fullPath.getParent());
 447                     try (OutputStream fos = Files.newOutputStream(fullPath)) {
 448                         fos.write(e.getValue());
 449                         fos.flush();
 450                     }
 451                 } catch (IOException ioe) {
 452                     throw new UncheckedIOException(ioe);
 453                 }
 454             });







 455         } catch (UncheckedIOException uioe) {
 456             throw uioe.getCause();
 457         }
 458     }
 459 
 460     private void writeJar(AsmCodeFactory cf, JarOutputStream jar) {
 461         cf.collect().entrySet().stream().forEach(e -> {
 462             try {
 463                 String path = e.getKey().replace('.', File.separatorChar) + ".class";
 464                 logger.fine(() -> "Add " + path);
 465                 jar.putNextEntry(new ZipEntry(path));
 466                 jar.write(e.getValue());
 467                 jar.closeEntry();
 468             } catch (IOException ioe) {
 469                 throw new UncheckedIOException(ioe);
 470             }
 471         });
 472     }
 473 
 474     public void collectJarFile(final JarOutputStream jos, String... pkgs) {


 479             String entryName = Utils.toInternalName(pkg_name, "");
 480             // package folder
 481             if (!entryName.isEmpty()) {
 482                 try {
 483                     jos.putNextEntry(new ZipEntry(entryName));
 484                 } catch (IOException ex) {
 485                     throw new UncheckedIOException(ex);
 486                 }
 487             }
 488             logger.fine(() -> "Produce for package " + pkg_name);
 489             mapPkgCf.getOrDefault(pkg_name, Collections.emptyList())
 490                     .forEach(cf -> writeJar(cf, jos));
 491         }
 492     }
 493 
 494     void collectJarFile(final Path jar, String... pkgs) throws IOException {
 495         logger.info(() -> "Collecting jar file " + jar);
 496         try (OutputStream os = Files.newOutputStream(jar, CREATE, TRUNCATE_EXISTING, WRITE);
 497                 JarOutputStream jo = new JarOutputStream(os)) {
 498             collectJarFile(jo, pkgs);



 499         } catch (UncheckedIOException uioe) {
 500             throw uioe.getCause();
 501         }
 502     }
 503 
 504     /**
 505      * Perform a local lookup, any undefined type will cause a JType
 506      * be defined within origin scope.
 507      *
 508      * @param type   The libclang type
 509      * @param origin The path of the file where type is encountered
 510      * @return The JType
 511      */
 512     JType getJType(final Type type, Path origin) {
 513         Path p = origin.normalize().toAbsolutePath();
 514 
 515         HeaderFile hf = headerMap.get(p);
 516         // We should not encounter a type if the header file reference to it is not yet processed
 517         assert(null != hf);
 518         if (hf == null) {




   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 package com.sun.tools.jextract;
  24 
  25 import jdk.internal.clang.*;
  26 import jdk.internal.foreign.LibrariesHelper;
  27 
  28 import java.io.ByteArrayOutputStream;
  29 import java.io.File;
  30 import java.io.IOException;
  31 import java.io.OutputStream;
  32 import java.io.PrintWriter;
  33 import java.io.UncheckedIOException;
  34 import java.lang.invoke.MethodHandles;
  35 import java.foreign.Library;
  36 import java.nio.file.Files;
  37 import java.nio.file.Path;
  38 import java.util.ArrayList;
  39 import java.util.Arrays;
  40 import java.util.Collections;
  41 import java.util.HashMap;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.Properties;
  45 import java.util.Set;
  46 import java.util.TreeSet;
  47 import java.util.function.Function;
  48 import java.util.function.Predicate;
  49 import java.util.jar.JarOutputStream;
  50 import java.util.logging.Logger;
  51 import java.util.regex.Pattern;
  52 import java.util.stream.Collectors;
  53 import java.util.zip.ZipEntry;
  54 
  55 import static java.nio.file.StandardOpenOption.CREATE;
  56 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
  57 import static java.nio.file.StandardOpenOption.WRITE;
  58 
  59 /**
  60  * The setup for the tool execution
  61  */
  62 public final class Context {
  63     // package name to TypeDictionary
  64     private final Map<String, TypeDictionary> tdMap;
  65     // The folder path mapping to package name
  66     private final Map<Path, String> pkgMap;
  67     // The header file parsed
  68     private final Map<Path, HeaderFile> headerMap;
  69     // The args for parsing C
  70     private final List<String> clangArgs;
  71     // The set of source header files
  72     private final Set<Path>  sources;
  73     // The list of library names
  74     private final List<String> libraryNames;
  75     // The list of library paths
  76     private final List<String> libraryPaths;
  77     // The list of library paths for link checks
  78     private final List<String> linkCheckPaths;
  79     // Symbol patterns to be excluded
  80     private final List<Pattern> excludeSymbols;
  81 
  82     final PrintWriter out;
  83     final PrintWriter err;
  84     final String[] args;
  85 
  86     private Predicate<String> symChecker;
  87     private Predicate<String> symFilter;
  88 
  89     private final MacroParser macroParser;
  90 
  91     private final static String defaultPkg = "jextract.dump";
  92     final Logger logger = Logger.getLogger(getClass().getPackage().getName());
  93 
  94     public Context(PrintWriter out, PrintWriter err, String[] args) {
  95         this.tdMap = new HashMap<>();
  96         this.pkgMap = new HashMap<>();
  97         this.headerMap = new HashMap<>();
  98         this.clangArgs = new ArrayList<>();
  99         this.sources = new TreeSet<>();
 100         this.libraryNames = new ArrayList<>();
 101         this.libraryPaths = new ArrayList<>();
 102         this.linkCheckPaths = new ArrayList<>();
 103         this.excludeSymbols = new ArrayList<>();
 104         this.macroParser = new MacroParser();
 105         this.out = out;
 106         this.err = err;
 107         this.args = args;
 108     }
 109 
 110     public Context(String[] args) {
 111         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true), args);
 112     }
 113 
 114     TypeDictionary typeDictionaryFor(String pkg) {
 115         return tdMap.computeIfAbsent(pkg, p->new TypeDictionary(this, p));
 116     }
 117 
 118     void addClangArg(String arg) {
 119         clangArgs.add(arg);
 120     }
 121 
 122     public void addSource(Path path) {
 123         sources.add(path);
 124     }
 125 
 126     void addLibraryName(String name) {
 127         libraryNames.add(name);
 128     }
 129 
 130     void addLibraryPath(String path) {
 131         libraryPaths.add(path);


 423                 logger.config(() -> "File " + header + " code generation is not activated!");
 424                 return;
 425             }
 426             List<AsmCodeFactory> l = mapPkgCf.computeIfAbsent(pkg, k -> new ArrayList<>());
 427             l.add(cf);
 428             logger.config(() -> "Add cf " + cf + " to pkg " + pkg + ", size is now " + l.size());
 429         });
 430         return Collections.unmodifiableMap(mapPkgCf);
 431     }
 432 
 433     public Map<String, byte[]> collectClasses(String... pkgs) {
 434         final Map<String, byte[]> rv = new HashMap<>();
 435         final Map<String, List<AsmCodeFactory>> mapPkgCf = getPkgCfMap();
 436         for (String pkg_name : pkgs) {
 437             mapPkgCf.getOrDefault(pkg_name, Collections.emptyList())
 438                     .forEach(cf -> rv.putAll(cf.collect()));
 439         }
 440         return Collections.unmodifiableMap(rv);
 441     }
 442 
 443     private static final String JEXTRACT_MANIFEST = "META-INFO" + File.separatorChar + "jextract.properties";
 444 
 445     @SuppressWarnings("deprecation")
 446     private byte[] getJextractProperties() {
 447         Properties props = new Properties();
 448         props.setProperty("os.name", System.getProperty("os.name"));
 449         props.setProperty("os.version", System.getProperty("os.version"));
 450         props.setProperty("os.arch", System.getProperty("os.arch"));
 451         props.setProperty("jextract.args", Arrays.toString(args));
 452         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 453         props.save(baos, "jextract meta data");
 454         return baos.toByteArray();
 455     }
 456 
 457     void collectClassFiles(Path destDir, String... pkgs) throws IOException {
 458         try {
 459             collectClasses(pkgs).entrySet().stream().forEach(e -> {
 460                 try {
 461                     String path = e.getKey().replace('.', File.separatorChar) + ".class";
 462                     logger.fine(() -> "Writing " + path);
 463                     Path fullPath = destDir.resolve(path).normalize();
 464                     Files.createDirectories(fullPath.getParent());
 465                     try (OutputStream fos = Files.newOutputStream(fullPath)) {
 466                         fos.write(e.getValue());
 467                         fos.flush();
 468                     }
 469                 } catch (IOException ioe) {
 470                     throw new UncheckedIOException(ioe);
 471                 }
 472             });
 473 
 474             Path propsPath = destDir.resolve(JEXTRACT_MANIFEST).normalize();
 475             Files.createDirectories(propsPath.getParent());
 476             try (OutputStream fos = Files.newOutputStream(propsPath)) {
 477                 fos.write(getJextractProperties());
 478                 fos.flush();
 479             }
 480         } catch (UncheckedIOException uioe) {
 481             throw uioe.getCause();
 482         }
 483     }
 484 
 485     private void writeJar(AsmCodeFactory cf, JarOutputStream jar) {
 486         cf.collect().entrySet().stream().forEach(e -> {
 487             try {
 488                 String path = e.getKey().replace('.', File.separatorChar) + ".class";
 489                 logger.fine(() -> "Add " + path);
 490                 jar.putNextEntry(new ZipEntry(path));
 491                 jar.write(e.getValue());
 492                 jar.closeEntry();
 493             } catch (IOException ioe) {
 494                 throw new UncheckedIOException(ioe);
 495             }
 496         });
 497     }
 498 
 499     public void collectJarFile(final JarOutputStream jos, String... pkgs) {


 504             String entryName = Utils.toInternalName(pkg_name, "");
 505             // package folder
 506             if (!entryName.isEmpty()) {
 507                 try {
 508                     jos.putNextEntry(new ZipEntry(entryName));
 509                 } catch (IOException ex) {
 510                     throw new UncheckedIOException(ex);
 511                 }
 512             }
 513             logger.fine(() -> "Produce for package " + pkg_name);
 514             mapPkgCf.getOrDefault(pkg_name, Collections.emptyList())
 515                     .forEach(cf -> writeJar(cf, jos));
 516         }
 517     }
 518 
 519     void collectJarFile(final Path jar, String... pkgs) throws IOException {
 520         logger.info(() -> "Collecting jar file " + jar);
 521         try (OutputStream os = Files.newOutputStream(jar, CREATE, TRUNCATE_EXISTING, WRITE);
 522                 JarOutputStream jo = new JarOutputStream(os)) {
 523             collectJarFile(jo, pkgs);
 524             jo.putNextEntry(new ZipEntry(JEXTRACT_MANIFEST));
 525             jo.write(getJextractProperties());
 526             jo.closeEntry();
 527         } catch (UncheckedIOException uioe) {
 528             throw uioe.getCause();
 529         }
 530     }
 531 
 532     /**
 533      * Perform a local lookup, any undefined type will cause a JType
 534      * be defined within origin scope.
 535      *
 536      * @param type   The libclang type
 537      * @param origin The path of the file where type is encountered
 538      * @return The JType
 539      */
 540     JType getJType(final Type type, Path origin) {
 541         Path p = origin.normalize().toAbsolutePath();
 542 
 543         HeaderFile hf = headerMap.get(p);
 544         // We should not encounter a type if the header file reference to it is not yet processed
 545         assert(null != hf);
 546         if (hf == null) {


< prev index next >