Ejemplo n.º 1
0
 /**
  * Tries to find automatically include paths for {@code jni.h} and {@code jni_md.h}, as well as
  * the link and library paths for the {@code jvm} library.
  *
  * @param properties the Properties containing the paths to update
  * @param header to request support for exporting callbacks via generated header file
  */
 static void includeJavaPaths(ClassProperties properties, boolean header) {
   if (properties.getProperty("platform", "").startsWith("android")) {
     // Android includes its own jni.h file and doesn't have a jvm library
     return;
   }
   String platform = Loader.getPlatform();
   final String jvmlink =
       properties.getProperty("platform.link.prefix", "")
           + "jvm"
           + properties.getProperty("platform.link.suffix", "");
   final String jvmlib =
       properties.getProperty("platform.library.prefix", "")
           + "jvm"
           + properties.getProperty("platform.library.suffix", "");
   final String[] jnipath = new String[2];
   final String[] jvmpath = new String[2];
   FilenameFilter filter =
       new FilenameFilter() {
         @Override
         public boolean accept(File dir, String name) {
           if (new File(dir, "jni.h").exists()) {
             jnipath[0] = dir.getAbsolutePath();
           }
           if (new File(dir, "jni_md.h").exists()) {
             jnipath[1] = dir.getAbsolutePath();
           }
           if (new File(dir, jvmlink).exists()) {
             jvmpath[0] = dir.getAbsolutePath();
           }
           if (new File(dir, jvmlib).exists()) {
             jvmpath[1] = dir.getAbsolutePath();
           }
           return new File(dir, name).isDirectory();
         }
       };
   File javaHome = new File(System.getProperty("java.home")).getParentFile();
   try {
     javaHome = javaHome.getCanonicalFile();
   } catch (IOException e) {
   }
   ArrayList<File> dirs = new ArrayList<File>(Arrays.asList(javaHome.listFiles(filter)));
   while (!dirs.isEmpty()) {
     File d = dirs.remove(dirs.size() - 1);
     String dpath = d.getPath();
     for (File f : d.listFiles(filter)) {
       try {
         f = f.getCanonicalFile();
       } catch (IOException e) {
       }
       if (!dpath.startsWith(f.getPath())) {
         dirs.add(f);
       }
     }
   }
   if (jnipath[0] != null && jnipath[0].equals(jnipath[1])) {
     jnipath[1] = null;
   } else if (jnipath[0] == null) {
     String macpath = "/System/Library/Frameworks/JavaVM.framework/Headers/";
     if (new File(macpath).isDirectory()) {
       jnipath[0] = macpath;
     }
   }
   if (jvmpath[0] != null && jvmpath[0].equals(jvmpath[1])) {
     jvmpath[1] = null;
   }
   properties.addAll("platform.includepath", jnipath);
   if (platform.equals(properties.getProperty("platform", platform))) {
     if (header) {
       // We only need libjvm for callbacks exported with the header file
       properties.get("platform.link").add(0, "jvm");
       properties.addAll("platform.linkpath", jvmpath);
     }
     if (platform.startsWith("macosx")) {
       properties.addAll("platform.framework", "JavaVM");
     }
   }
 }
Ejemplo n.º 2
0
  /**
   * Launches and waits for the native compiler to produce a native shared library.
   *
   * @param sourceFilename the C++ source filename
   * @param outputFilename the output filename of the shared library
   * @param properties the Properties detailing the compiler options to use
   * @return the result of {@link Process#waitFor()}
   * @throws IOException
   * @throws InterruptedException
   */
  int compile(String sourceFilename, String outputFilename, ClassProperties properties)
      throws IOException, InterruptedException {
    ArrayList<String> command = new ArrayList<String>();

    includeJavaPaths(properties, header);

    String platform = Loader.getPlatform();
    String compilerPath = properties.getProperty("platform.compiler");
    command.add(compilerPath);

    {
      String p = properties.getProperty("platform.sysroot.prefix", "");
      for (String s : properties.get("platform.sysroot")) {
        if (new File(s).isDirectory()) {
          if (p.endsWith(" ")) {
            command.add(p.trim());
            command.add(s);
          } else {
            command.add(p + s);
          }
        }
      }
    }

    {
      String p = properties.getProperty("platform.includepath.prefix", "");
      for (String s : properties.get("platform.includepath")) {
        if (new File(s).isDirectory()) {
          if (p.endsWith(" ")) {
            command.add(p.trim());
            command.add(s);
          } else {
            command.add(p + s);
          }
        }
      }
    }

    command.add(sourceFilename);

    Collection<String> allOptions = properties.get("platform.compiler.*");
    if (allOptions.isEmpty()) {
      allOptions.add("default");
    }
    for (String s : allOptions) {
      if (s == null || s.length() == 0) {
        continue;
      }
      String p = "platform.compiler." + s;
      String options = properties.getProperty(p);
      if (options != null && options.length() > 0) {
        command.addAll(Arrays.asList(options.split(" ")));
      } else if (!"default".equals(s)) {
        logger.warn("Could not get the property named \"" + p + "\"");
      }
    }

    command.addAll(compilerOptions);

    String output = properties.getProperty("platform.compiler.output");
    if (output != null && output.length() > 0) {
      command.addAll(Arrays.asList(output.split(" ")));
    }

    if (output == null || output.length() == 0 || output.endsWith(" ")) {
      command.add(outputFilename);
    } else {
      command.add(command.remove(command.size() - 1) + outputFilename);
    }

    {
      String p = properties.getProperty("platform.linkpath.prefix", "");
      String p2 = properties.getProperty("platform.linkpath.prefix2");
      for (String s : properties.get("platform.linkpath")) {
        if (new File(s).isDirectory()) {
          if (p.endsWith(" ")) {
            command.add(p.trim());
            command.add(s);
          } else {
            command.add(p + s);
          }
          if (p2 != null) {
            if (p2.endsWith(" ")) {
              command.add(p2.trim());
              command.add(s);
            } else {
              command.add(p2 + s);
            }
          }
        }
      }
    }

    {
      String p = properties.getProperty("platform.link.prefix", "");
      String x = properties.getProperty("platform.link.suffix", "");
      int i = command.size(); // to inverse order and satisfy typical compilers
      for (String s : properties.get("platform.link")) {
        String[] libnameversion = s.split("@");
        if (libnameversion.length == 3 && libnameversion[1].length() == 0) {
          // Only use the version number when the user gave us a double @
          s = libnameversion[0] + libnameversion[2];
        } else {
          s = libnameversion[0];
        }
        if (p.endsWith(" ") && x.startsWith(" ")) {
          command.add(i, p.trim());
          command.add(i + 1, s);
          command.add(i + 2, x.trim());
        } else if (p.endsWith(" ")) {
          command.add(i, p.trim());
          command.add(i + 1, s + x);
        } else if (x.startsWith(" ")) {
          command.add(i, p + s);
          command.add(i + 1, x.trim());
        } else {
          command.add(i, p + s + x);
        }
      }
    }

    {
      String p = properties.getProperty("platform.frameworkpath.prefix", "");
      for (String s : properties.get("platform.frameworkpath")) {
        if (new File(s).isDirectory()) {
          if (p.endsWith(" ")) {
            command.add(p.trim());
            command.add(s);
          } else {
            command.add(p + s);
          }
        }
      }
    }

    {
      String p = properties.getProperty("platform.framework.prefix", "");
      String x = properties.getProperty("platform.framework.suffix", "");
      for (String s : properties.get("platform.framework")) {
        if (p.endsWith(" ") && x.startsWith(" ")) {
          command.add(p.trim());
          command.add(s);
          command.add(x.trim());
        } else if (p.endsWith(" ")) {
          command.add(p.trim());
          command.add(s + x);
        } else if (x.startsWith(" ")) {
          command.add(p + s);
          command.add(x.trim());
        } else {
          command.add(p + s + x);
        }
      }
    }

    String text = "";
    boolean windows = platform.startsWith("windows");
    for (String s : command) {
      boolean hasSpaces = s.indexOf(" ") > 0;
      if (hasSpaces) {
        text += windows ? "\"" : "'";
      }
      text += s;
      if (hasSpaces) {
        text += windows ? "\"" : "'";
      }
      text += " ";
    }
    logger.info(text);

    ProcessBuilder pb = new ProcessBuilder(command);
    if (environmentVariables != null) {
      pb.environment().putAll(environmentVariables);
    }
    return pb.inheritIO().start().waitFor();
  }