< prev index next >

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

Print this page




   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 package com.sun.tools.jextract;
  24 
  25 import jdk.internal.clang.*;
  26 
  27 import java.io.ByteArrayOutputStream;
  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.lang.invoke.MethodHandles.Lookup;
  35 import java.foreign.Library;
  36 import java.foreign.Libraries;
  37 import java.nio.file.Files;
  38 import java.nio.file.Path;
  39 import java.nio.file.Paths;
  40 import java.util.ArrayList;
  41 import java.util.Arrays;
  42 import java.util.Collections;
  43 import java.util.HashMap;
  44 import java.util.List;
  45 import java.util.Map;
  46 import java.util.Optional;
  47 import java.util.Properties;
  48 import java.util.Set;
  49 import java.util.TreeSet;
  50 import java.util.function.Function;
  51 import java.util.function.Predicate;
  52 import java.util.jar.JarOutputStream;
  53 import java.util.logging.Logger;
  54 import java.util.regex.Pattern;
  55 import java.util.stream.Collectors;
  56 import java.util.zip.ZipEntry;
  57 import com.sun.tools.jextract.parser.Parser;
  58 import com.sun.tools.jextract.tree.FunctionTree;
  59 import com.sun.tools.jextract.tree.HeaderTree;
  60 import com.sun.tools.jextract.tree.Tree;
  61 
  62 import static java.nio.file.StandardOpenOption.CREATE;
  63 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
  64 import static java.nio.file.StandardOpenOption.WRITE;
  65 
  66 /**
  67  * The setup for the tool execution
  68  */
  69 public final class Context {
  70     // The folder path mapping to package name
  71     private final Map<Path, String> pkgMap;
  72     // The header file parsed
  73     private final Map<Path, HeaderFile> headerMap;
  74     // The args for parsing C
  75     private final List<String> clangArgs;
  76     // The set of source header files
  77     private final Set<Path>  sources;
  78     // The list of library names
  79     private final List<String> libraryNames;
  80     // The list of library paths
  81     private final List<String> libraryPaths;
  82     // The list of library paths for link checks
  83     private final List<String> linkCheckPaths;
  84     // Symbol patterns to be included
  85     private final List<Pattern> includeSymbols;
  86     // Symbol patterns to be excluded
  87     private final List<Pattern> excludeSymbols;
  88     // no NativeLocation info
  89     private boolean noNativeLocations;
  90     // generate static forwarder class or not?
  91     private boolean genStaticForwarder;
  92 
  93     final PrintWriter out;
  94     final PrintWriter err;

  95 
  96     private Predicate<String> symChecker;
  97     private Predicate<String> includeSymFilter;
  98     private Predicate<String> excludeSymFilter;
  99 
 100     private final Parser parser;
 101 
 102     final static String defaultPkg = "jextract.dump";
 103     final Logger logger = Logger.getLogger(getClass().getPackage().getName());
 104 
 105     public Context(PrintWriter out, PrintWriter err) {
 106         this.pkgMap = new HashMap<>();
 107         this.headerMap = new HashMap<>();
 108         this.clangArgs = new ArrayList<>();
 109         this.sources = new TreeSet<>();
 110         this.libraryNames = new ArrayList<>();
 111         this.libraryPaths = new ArrayList<>();
 112         this.linkCheckPaths = new ArrayList<>();
 113         this.includeSymbols = new ArrayList<>();
 114         this.excludeSymbols = new ArrayList<>();
 115         this.parser = new Parser(out, err, Main.INCLUDE_MACROS);
 116         this.out = out;
 117         this.err = err;
 118     }
 119 
 120     public Context() {
 121         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true));
 122     }
 123 
 124     void addClangArg(String arg) {
 125         clangArgs.add(arg);
 126     }
 127 
 128     public void addSource(Path path) {
 129         sources.add(path);
 130     }
 131 
 132     void addLibraryName(String name) {
 133         libraryNames.add(name);
 134     }
 135 
 136     void addLibraryPath(String path) {
 137         libraryPaths.add(path);
 138     }
 139 
 140     void addLinkCheckPath(String path) {
 141         linkCheckPaths.add(path);
 142     }
 143 
 144     boolean getNoNativeLocations() {
 145         return noNativeLocations;
 146     }
 147 
 148     void setNoNativeLocations() {
 149         noNativeLocations = true;
 150     }
 151 
 152     void addIncludeSymbols(String pattern) {
 153         includeSymbols.add(Pattern.compile(pattern));
 154     }
 155 
 156     void addExcludeSymbols(String pattern) {
 157         excludeSymbols.add(Pattern.compile(pattern));
 158     }
 159 
 160     void setGenStaticForwarder(boolean flag) {
 161         this.genStaticForwarder = flag;
 162     }
 163 
 164     // return the absolute path of the library of given name by searching
 165     // in the given array of paths.
 166     private static Optional<Path> findLibraryPath(Path[] paths, String libName) {
 167          return Arrays.stream(paths).
 168               map(p -> p.resolve(System.mapLibraryName(libName))).
 169               filter(Files::isRegularFile).map(Path::toAbsolutePath).findFirst();
 170     }
 171 
 172     /*
 173      * Load the specified shared libraries from the specified paths.
 174      *
 175      * @param lookup Lookup object of the caller.
 176      * @param pathStrs array of paths to load the shared libraries from.
 177      * @param names array of shared library names.
 178      */
 179     // used by jextract tool to load libraries for symbol checks.
 180     public static Library[] loadLibraries(Lookup lookup, String[] pathStrs, String[] names) {
 181         if (pathStrs == null || pathStrs.length == 0) {
 182             return Arrays.stream(names).map(
 183                 name -> Libraries.loadLibrary(lookup, name)).toArray(Library[]::new);
 184         } else {
 185             Path[] paths = Arrays.stream(pathStrs).map(Paths::get).toArray(Path[]::new);
 186             return Arrays.stream(names).map(libName -> {
 187                 Optional<Path> absPath = findLibraryPath(paths, libName);
 188                 return absPath.isPresent() ?
 189                     Libraries.load(lookup, absPath.get().toString()) :
 190                     Libraries.loadLibrary(lookup, libName);
 191             }).toArray(Library[]::new);
 192         }
 193     }
 194 
 195     private void initSymChecker() {
 196         if (!libraryNames.isEmpty() && !linkCheckPaths.isEmpty()) {
 197             try {
 198                 Library[] libs = loadLibraries(MethodHandles.lookup(),
 199                     linkCheckPaths.toArray(new String[0]),
 200                     libraryNames.toArray(new String[0]));
 201                 // check if the given symbol is found in any of the libraries or not.
 202                 // If not found, warn the user for the missing symbol.
 203                 symChecker = name -> {
 204                     if (Main.DEBUG) {
 205                         err.println("Searching symbol: " + name);
 206                     }
 207                     return (Arrays.stream(libs).filter(lib -> {
 208                             try {
 209                                 lib.lookup(name);
 210                                 if (Main.DEBUG) {
 211                                     err.println("Found symbol: " + name);
 212                                 }
 213                                 return true;
 214                             } catch (NoSuchMethodException nsme) {
 215                                 return false;
 216                             }
 217                         }).findFirst().isPresent());
 218                 };
 219             } catch (UnsatisfiedLinkError ex) {
 220                 err.println(Main.format("warn.lib.not.found"));
 221                 symChecker = null;
 222             }
 223         } else {
 224             symChecker = null;
 225         }
 226     }
 227 
 228     private boolean isSymbolFound(String name) {
 229         return symChecker == null? true : symChecker.test(name);
 230     }
 231 
 232     private void initSymFilters() {
 233         if (!includeSymbols.isEmpty()) {
 234             Pattern[] pats = includeSymbols.toArray(new Pattern[0]);
 235             includeSymFilter = name -> {
 236                 return Arrays.stream(pats).filter(pat -> pat.matcher(name).matches()).
 237                     findFirst().isPresent();
 238             };
 239         } else {
 240             includeSymFilter = null;
 241         }
 242 
 243         if (!excludeSymbols.isEmpty()) {
 244             Pattern[] pats = excludeSymbols.toArray(new Pattern[0]);
 245             excludeSymFilter = name -> {
 246                 return Arrays.stream(pats).filter(pat -> pat.matcher(name).matches()).
 247                     findFirst().isPresent();
 248             };
 249         } else {
 250             excludeSymFilter = null;
 251         }
 252     }
 253 
 254     private boolean isSymbolIncluded(String name) {
 255         return includeSymFilter == null? true : includeSymFilter.test(name);
 256     }
 257 
 258     private boolean isSymbolExcluded(String name) {
 259         return excludeSymFilter == null? false : excludeSymFilter.test(name);
 260     }
 261 
 262     /**
 263      * Setup a package name for a given folder.
 264      *
 265      * @param folder The path to the folder, use null to set catch-all.
 266      * @param pkg    The package name
 267      * @return True if the folder is setup successfully. False is a package
 268      * has been assigned for the folder.
 269      */
 270     public boolean usePackageForFolder(Path folder, String pkg) {
 271         if (folder != null) {
 272             folder = folder.toAbsolutePath();
 273             if (!Files.isDirectory(folder)) {
 274                 folder = folder.getParent();
 275             }
 276         }
 277         String existing = pkgMap.putIfAbsent(folder, pkg);
 278         final String finalFolder = (null == folder) ? "all folders not configured" : folder.toString();
 279         if (null == existing) {
 280             logger.config(() -> "Package " + pkg + " is selected for " + finalFolder);
 281             return true;
 282         } else {
 283             logger.warning(() -> "Package " + existing + " had been selected for " + finalFolder + ", request to use " + pkg + " is ignored.");
 284             return false;
 285         }
 286     }
 287 
 288     static class Entity {
 289         final String pkg;
 290         final String entity;
 291 
 292         Entity(String pkg, String entity) {
 293             this.pkg = pkg;
 294             this.entity = entity;
 295         }
 296     }
 297 
 298     /**
 299      * Determine package and interface name given a path. If the path is
 300      * a folder, then only package name is determined. The package name is
 301      * determined with the longest path matching the setup. If the path is not
 302      * setup for any package, the default package name is returned.
 303      *
 304      * @param origin The source path
 305      * @return The Entity
 306      * @see Context::usePackageForFolder(Path, String)
 307      */
 308     Entity whatis(Path origin) {
 309         // normalize to absolute path
 310         origin = origin.toAbsolutePath();
 311         String filename = null;
 312         if (!Files.isDirectory(origin)) {
 313             // ensure it's a folder name
 314             filename = origin.getFileName().toString();
 315             origin = origin.getParent();
 316         }
 317         Path path = origin;
 318 
 319         // search the map for a hit with longest path
 320         while (path != null && !pkgMap.containsKey(path)) {
 321             path = path.getParent();
 322         }
 323 
 324         int start;
 325         String pkg;
 326         if (path != null) {
 327             start = path.getNameCount();
 328             pkg = pkgMap.get(path);
 329         } else {
 330             pkg = pkgMap.get(null);
 331             if (pkg == null) {
 332                 start = 0;
 333                 pkg = defaultPkg;
 334             } else {
 335                 start = origin.getNameCount();
 336             }
 337         }
 338 
 339         if (filename == null) {
 340             // a folder, only pkg name matters
 341             return new Entity(pkg, null);
 342         }
 343 
 344         StringBuilder sb = new StringBuilder();
 345         while (start < origin.getNameCount()) {
 346             sb.append(Utils.toJavaIdentifier(origin.getName(start++).toString()));
 347             sb.append("_");
 348         }
 349 
 350         int ext = filename.lastIndexOf('.');
 351         if (ext != -1) {
 352             sb.append(filename.substring(0, ext));
 353         } else {
 354             sb.append(filename);
 355         }
 356         return new Entity(pkg, Utils.toClassName(sb.toString()));
 357     }
 358 
 359     HeaderFile getHeaderFile(Path header, HeaderFile main) {
 360         if (!Files.isRegularFile(header)) {
 361             logger.warning(() -> "Not a regular file: " + header.toString());
 362             throw new IllegalArgumentException(header.toString());
 363         }
 364 
 365         final Context.Entity e = whatis(header);
 366         HeaderFile headerFile = new HeaderFile(this, header, e.pkg, e.entity, main);
 367         headerFile.useLibraries(libraryNames, libraryPaths);
 368         return headerFile;
 369     }
 370 
 371     void processTree(Tree tree, HeaderFile main, Function<HeaderFile, AsmCodeFactory> fn) {
 372         SourceLocation loc = tree.location();
 373 
 374         HeaderFile header;
 375         boolean isBuiltIn = false;
 376 
 377         if (tree.isFromMain()) {
 378             header = main;
 379         } else {
 380             SourceLocation.Location src = loc.getFileLocation();
 381             if (src == null) {
 382                 logger.info(() -> "Tree " + tree.name() + "@" + tree.USR() + " has no FileLocation");
 383                 return;
 384             }
 385 
 386             Path p = src.path();
 387             if (p == null) {
 388                 logger.fine(() -> "Found built-in type: " + tree.name());
 389                 header = main;
 390                 isBuiltIn = true;
 391             } else {
 392                 p = p.normalize().toAbsolutePath();
 393                 header = headerMap.get(p);
 394                 if (header == null) {
 395                     final HeaderFile hf = header = getHeaderFile(p, main);
 396                     logger.config(() -> "First encounter of header file " + hf.path + ", assigned to package " + hf.pkgName);
 397                     // Only generate code for header files specified or in the same package
 398                     if (sources.contains(p) ||
 399                         (header.pkgName.equals(main.pkgName))) {
 400                         logger.config("Code gen for header " + p + " enabled in package " + header.pkgName);
 401                         header.useCodeFactory(fn.apply(header));
 402                     }
 403                     headerMap.put(p, header);
 404                 }
 405             }
 406         }
 407 
 408         header.processTree(tree, main, isBuiltIn);
 409     }
 410 
 411     public void parse() {
 412         parse(header -> genStaticForwarder?
 413             new AsmCodeFactoryExt(this, header) : new AsmCodeFactory(this, header));
 414     }
 415 
 416     private boolean symbolFilter(Tree tree) {
 417          String name = tree.name();
 418          if (!isSymbolIncluded(name) || isSymbolExcluded(name)) {
 419              return false;
 420          }
 421 
 422          // check for function symbols in libraries & warn missing symbols
 423          if (tree instanceof FunctionTree && !isSymbolFound(name)) {
 424              err.println(Main.format("warn.symbol.not.found", name));
 425              //auto-exclude symbols not found
 426              return false;
 427          }
 428 
 429          return true;
 430     }
 431 
 432     public HeaderFile headerFor(Path p) {
 433         return headerMap.get(p);
 434     }
 435 
 436     public void parse(Function<HeaderFile, AsmCodeFactory> fn) {
 437         initSymChecker();
 438         initSymFilters();
 439 
 440         List<HeaderTree> headers = parser.parse(sources, clangArgs);
 441         processHeaders(headers, fn);
 442     }
 443 
 444     private void processHeaders(List<HeaderTree> headers, Function<HeaderFile, AsmCodeFactory> fn) {
 445         headers.stream().
 446                 map(new TreeFilter(this::symbolFilter)).
 447                 map(new TypedefHandler()).
 448                 map(new EmptyNameHandler()).
 449                 forEach(header -> {
 450             HeaderFile hf = headerMap.computeIfAbsent(header.path(), p -> getHeaderFile(p, null));
 451             hf.useCodeFactory(fn.apply(hf));
 452             logger.info(() -> "Processing header file " + header.path());
 453             header.declarations().stream()
 454                     .peek(decl -> logger.finest(
 455                         () -> "Cursor: " + decl.name() + "@" + decl.USR() + "?" + decl.isDeclaration()))
 456                     .forEach(decl -> processTree(decl, hf, fn));
 457         });
 458     }
 459 
 460     private Map<String, List<AsmCodeFactory>> getPkgCfMap() {
 461         final Map<String, List<AsmCodeFactory>> mapPkgCf = new HashMap<>();
 462         // Build the pkg to CodeFactory map
 463         headerMap.values().forEach(header -> {
 464             AsmCodeFactory cf = header.getCodeFactory();
 465             String pkg = header.pkgName;
 466             logger.config(() -> "File " + header + " is in package: " + pkg);
 467             if (cf == null) {
 468                 logger.config(() -> "File " + header + " code generation is not activated!");
 469                 return;
 470             }
 471             List<AsmCodeFactory> l = mapPkgCf.computeIfAbsent(pkg, k -> new ArrayList<>());
 472             l.add(cf);
 473             logger.config(() -> "Add cf " + cf + " to pkg " + pkg + ", size is now " + l.size());
 474         });
 475         return Collections.unmodifiableMap(mapPkgCf);
 476     }
 477 
 478     public Map<String, byte[]> collectClasses(String... pkgs) {
 479         final Map<String, byte[]> rv = new HashMap<>();
 480         final Map<String, List<AsmCodeFactory>> mapPkgCf = getPkgCfMap();
 481         for (String pkg_name : pkgs) {
 482             mapPkgCf.getOrDefault(pkg_name, Collections.emptyList())
 483                     .forEach(cf -> rv.putAll(cf.collect()));
 484         }
 485         return Collections.unmodifiableMap(rv);
 486     }
 487 
 488     private static final String JEXTRACT_MANIFEST = "META-INFO" + File.separatorChar + "jextract.properties";
 489 
 490     @SuppressWarnings("deprecation")
 491     private byte[] getJextractProperties(String[] args) {
 492         Properties props = new Properties();
 493         props.setProperty("os.name", System.getProperty("os.name"));
 494         props.setProperty("os.version", System.getProperty("os.version"));
 495         props.setProperty("os.arch", System.getProperty("os.arch"));
 496         props.setProperty("jextract.args", Arrays.toString(args));
 497         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 498         props.save(baos, "jextract meta data");
 499         return baos.toByteArray();
 500     }
 501 
 502     void collectClassFiles(Path destDir, String[] args, String... pkgs) throws IOException {
 503         try {
 504             collectClasses(pkgs).entrySet().stream().forEach(e -> {
 505                 try {
 506                     String path = e.getKey().replace('.', File.separatorChar) + ".class";
 507                     logger.fine(() -> "Writing " + path);
 508                     Path fullPath = destDir.resolve(path).normalize();
 509                     Files.createDirectories(fullPath.getParent());
 510                     try (OutputStream fos = Files.newOutputStream(fullPath)) {
 511                         fos.write(e.getValue());
 512                         fos.flush();
 513                     }
 514                 } catch (IOException ioe) {
 515                     throw new UncheckedIOException(ioe);
 516                 }
 517             });
 518 
 519             Path propsPath = destDir.resolve(JEXTRACT_MANIFEST).normalize();
 520             Files.createDirectories(propsPath.getParent());
 521             try (OutputStream fos = Files.newOutputStream(propsPath)) {
 522                 fos.write(getJextractProperties(args));
 523                 fos.flush();
 524             }
 525         } catch (UncheckedIOException uioe) {
 526             throw uioe.getCause();
 527         }
 528     }
 529 
 530     private void writeJar(AsmCodeFactory cf, JarOutputStream jar) {
 531         cf.collect().entrySet().stream().forEach(e -> {
 532             try {
 533                 String path = e.getKey().replace('.', File.separatorChar) + ".class";
 534                 logger.fine(() -> "Add " + path);
 535                 jar.putNextEntry(new ZipEntry(path));
 536                 jar.write(e.getValue());
 537                 jar.closeEntry();
 538             } catch (IOException ioe) {
 539                 throw new UncheckedIOException(ioe);
 540             }
 541         });
 542     }
 543 
 544     public void collectJarFile(final JarOutputStream jos, String[] args, String... pkgs) {
 545         final Map<String, List<AsmCodeFactory>> mapPkgCf = getPkgCfMap();
 546 
 547         for (String pkg_name : pkgs) {
 548             // convert '.' to '/' to use as a path
 549             String entryName = Utils.toInternalName(pkg_name, "");
 550             // package folder
 551             if (!entryName.isEmpty()) {
 552                 try {
 553                     jos.putNextEntry(new ZipEntry(entryName));
 554                 } catch (IOException ex) {
 555                     throw new UncheckedIOException(ex);
 556                 }
 557             }
 558             logger.fine(() -> "Produce for package " + pkg_name);
 559             mapPkgCf.getOrDefault(pkg_name, Collections.emptyList())
 560                     .forEach(cf -> writeJar(cf, jos));
 561         }
 562 
 563         try {
 564             jos.putNextEntry(new ZipEntry(JEXTRACT_MANIFEST));
 565             jos.write(getJextractProperties(args));
 566             jos.closeEntry();
 567         } catch (IOException ioe) {
 568             throw new UncheckedIOException(ioe);
 569         }
 570     }
 571 
 572     void collectJarFile(final Path jar, String[] args, String... pkgs) throws IOException {
 573         logger.info(() -> "Collecting jar file " + jar);
 574         try (OutputStream os = Files.newOutputStream(jar, CREATE, TRUNCATE_EXISTING, WRITE);
 575                 JarOutputStream jo = new JarOutputStream(os)) {
 576             collectJarFile(jo, args, pkgs);
 577         } catch (UncheckedIOException uioe) {
 578             throw uioe.getCause();
 579         }
 580     }
 581 }


   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 package com.sun.tools.jextract;
  24 






  25 import java.io.PrintWriter;





  26 import java.nio.file.Files;
  27 import java.nio.file.Path;
  28 import java.util.*;













  29 import java.util.logging.Logger;
  30 import java.util.regex.Pattern;
  31 import java.util.stream.Collectors;

  32 import com.sun.tools.jextract.parser.Parser;


  33 import com.sun.tools.jextract.tree.Tree;
  34 




  35 /**
  36  * The setup for the tool execution
  37  */
  38 public final class Context {




  39     // The args for parsing C
  40     public final List<String> clangArgs;
  41     // The set of source header files
  42     public final Set<Path>  sources;
  43     // The list of library names
  44     public final List<String> libraryNames;
  45     // The list of library paths
  46     public final List<String> libraryPaths;
  47     // The list of library paths for link checks
  48     public final List<String> linkCheckPaths;
  49     // Symbol patterns to be included
  50     public final List<Pattern> includeSymbols;
  51     // Symbol patterns to be excluded
  52     public final List<Pattern> excludeSymbols;
  53     // no NativeLocation info
  54     public boolean noNativeLocations;
  55     // generate static forwarder class or not?
  56     public boolean genStaticForwarder;
  57     // target package
  58     public String targetPackage;
  59     // package mappings
  60     public final Map<Path, String> pkgMappings = new LinkedHashMap<>();
  61 
  62     public final PrintWriter out;
  63     public final PrintWriter err;

  64 



  65     final Logger logger = Logger.getLogger(getClass().getPackage().getName());
  66 
  67     public Context(PrintWriter out, PrintWriter err) {


  68         this.clangArgs = new ArrayList<>();
  69         this.sources = new TreeSet<>();
  70         this.libraryNames = new ArrayList<>();
  71         this.libraryPaths = new ArrayList<>();
  72         this.linkCheckPaths = new ArrayList<>();
  73         this.includeSymbols = new ArrayList<>();
  74         this.excludeSymbols = new ArrayList<>();

  75         this.out = out;
  76         this.err = err;
  77     }
  78 
  79     public Context() {
  80         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true));
  81     }
  82 
  83     public void addClangArg(String arg) {
  84         clangArgs.add(arg);
  85     }
  86 
  87     public void addSource(Path path) {
  88         sources.add(path);
  89     }
  90 
  91     public void addLibraryName(String name) {
  92         libraryNames.add(name);
  93     }
  94 
  95     public void addLibraryPath(String path) {
  96         libraryPaths.add(path);
  97     }
  98 
  99     public void addLinkCheckPath(String path) {
 100         linkCheckPaths.add(path);
 101     }
 102 
 103     public void setNoNativeLocations() {




 104         noNativeLocations = true;
 105     }
 106 
 107     public void addIncludeSymbols(String pattern) {
 108         includeSymbols.add(Pattern.compile(pattern));
 109     }
 110 
 111     public void addExcludeSymbols(String pattern) {
 112         excludeSymbols.add(Pattern.compile(pattern));
 113     }
 114 
 115     public void setGenStaticForwarder(boolean flag) {
 116         this.genStaticForwarder = flag;
 117     }
 118 
 119     public void setTargetPackage(String pkg) {
 120         this.targetPackage = pkg;



















































































































































































































































 121     }
 122 
 123     public void addPackageMapping(Path path, String pkg) {
 124         pkgMappings.put(path, pkg);







































































































































































 125     }
 126 }
< prev index next >