/bbb-screenshare/jws/webstart/src/main/java/org/bytedeco/javacpp/tools/Builder.java
Java | 809 lines | 630 code | 34 blank | 145 comment | 204 complexity | 61e17c353da834236d1c6973db697f0f MD5 | raw file
Possible License(s): LGPL-3.0
- /*
- * Copyright (C) 2011-2016 Samuel Audet
- *
- * Licensed either under the Apache License, Version 2.0, or (at your option)
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation (subject to the "Classpath" exception),
- * either version 2, or any later version (collectively, the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- * http://www.gnu.org/licenses/
- * http://www.gnu.org/software/classpath/license.html
- *
- * or as provided in the LICENSE.txt file that accompanied this code.
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.bytedeco.javacpp.tools;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.FilenameFilter;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.net.URI;
- import java.net.URISyntaxException;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.LinkedHashMap;
- import java.util.LinkedHashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Properties;
- import java.util.jar.JarOutputStream;
- import java.util.zip.ZipEntry;
- import org.bytedeco.javacpp.ClassProperties;
- import org.bytedeco.javacpp.Loader;
- /**
- * The Builder is responsible for coordinating efforts between the Parser, the
- * Generator, and the native compiler. It contains the main() method, and basically
- * takes care of the tasks one would expect from a command line build tool, but
- * can also be used programmatically by setting its properties and calling build().
- *
- * @author Samuel Audet
- */
- public class Builder {
- /**
- * Calls {@link Parser#parse(File, String[], Class)} after creating an instance of the Class.
- *
- * @param classPath an array of paths to try to load header files from
- * @param cls The class annotated with {@link org.bytedeco.javacpp.annotation.Properties}
- * and implementing {@link InfoMapper}
- * @return the target File produced
- * @throws IOException on Java target file writing error
- * @throws ParserException on C/C++ header file parsing error
- */
- File parse(String[] classPath, Class cls) throws IOException, ParserException {
- return new Parser(logger, properties).parse(outputDirectory, classPath, cls);
- }
- /**
- * 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
- */
- 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;
- try {
- javaHome = new File(System.getProperty("java.home")).getParentFile().getCanonicalFile();
- } catch (IOException | NullPointerException e) {
- logger.warn("Could not include header files from java.home:" + e);
- return;
- }
- 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();
- File[] files = d.listFiles(filter);
- if (dpath == null || files == null) {
- continue;
- }
- for (File f : files) {
- 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");
- }
- }
- }
- /**
- * 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, File workingDirectory)
- 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");
- for (int i = 1; i < 2 || output != null; i++,
- output = properties.getProperty("platform.compiler.output" + i)) {
- 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);
- // Use the library output path as the working directory so that all
- // build files, including intermediate ones from MSVC, are dumped there
- pb.directory(workingDirectory);
- if (environmentVariables != null) {
- pb.environment().putAll(environmentVariables);
- }
- return pb.inheritIO().start().waitFor();
- }
- /**
- * Generates a C++ source file for classes, and compiles everything in
- * one shared library when {@code compile == true}.
- *
- * @param classes the Class objects as input to Generator
- * @param outputName the output name of the shared library
- * @return the actual File generated, either the compiled library or its source
- * @throws IOException
- * @throws InterruptedException
- */
- File generateAndCompile(Class[] classes, String outputName) throws IOException, InterruptedException {
- File outputFile = null, outputPath = outputDirectory;
- ClassProperties p = Loader.loadProperties(classes, properties, true);
- String platform = p.getProperty("platform");
- String sourcePrefix = new File(outputPath, outputName).getPath();
- String sourceSuffix = p.getProperty("platform.source.suffix", ".cpp");
- String libraryPath = p.getProperty("platform.library.path", "");
- String libraryName = p.getProperty("platform.library.prefix", "") + outputName + p.getProperty("platform.library.suffix", "");
- if (outputPath == null) {
- URI uri = null;
- try {
- String resourceName = '/' + classes[classes.length - 1].getName().replace('.', '/') + ".class";
- String resourceURL = classes[classes.length - 1].getResource(resourceName).toString();
- File packageDir = new File(uri = new URI(resourceURL.substring(0, resourceURL.lastIndexOf('/') + 1)));
- File targetDir = libraryPath.length() > 0
- ? new File(uri = new URI(resourceURL.substring(0, resourceURL.length() - resourceName.length() + 1)))
- : new File(packageDir, platform);
- outputPath = new File(targetDir, libraryPath);
- sourcePrefix = new File(packageDir, outputName).getPath();
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(e + ": " + uri);
- }
- }
- if (!outputPath.exists()) {
- outputPath.mkdirs();
- }
- Generator generator = new Generator(logger, p);
- String sourceFilename = sourcePrefix + sourceSuffix;
- String headerFilename = header ? sourcePrefix + ".h" : null;
- String classPath = System.getProperty("java.class.path");
- for (String s : classScanner.getClassLoader().getPaths()) {
- classPath += File.pathSeparator + s;
- }
- logger.info("Generating " + sourceFilename);
- if (generator.generate(sourceFilename, headerFilename, classPath, classes)) {
- generator.close();
- if (compile) {
- logger.info("Compiling " + outputPath.getPath() + File.separator + libraryName);
- int exitValue = compile(sourceFilename, libraryName, p, outputPath);
- if (exitValue == 0) {
- if (deleteJniFiles) {
- logger.info("Deleting " + sourceFilename);
- new File(sourceFilename).delete();
- } else {
- logger.info("Keeping " + sourceFilename);
- }
- outputFile = new File(outputPath, libraryName);
- } else {
- System.exit(exitValue);
- }
- } else {
- outputFile = new File(sourceFilename);
- }
- } else {
- logger.info("Nothing generated for " + sourceFilename);
- }
- return outputFile;
- }
- /**
- * Stores all the files in the given JAR file. Also attempts to root the paths
- * of the filenames to each element of a list of classpaths.
- *
- * @param jarFile the JAR file to create
- * @param classPath an array of paths to try to use as root for classes
- * @param files a list of files to store in the JAR file
- * @throws IOException
- */
- void createJar(File jarFile, String[] classPath, File ... files) throws IOException {
- logger.info("Creating " + jarFile);
- JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile));
- for (File f : files) {
- String name = f.getPath();
- if (classPath != null) {
- // Store only the path relative to the classpath so that
- // our Loader may use the package name of the associated
- // class to get the file as a resource from the ClassLoader.
- String[] names = new String[classPath.length];
- for (int i = 0; i < classPath.length; i++) {
- String path = new File(classPath[i]).getCanonicalPath();
- if (name.startsWith(path)) {
- names[i] = name.substring(path.length() + 1);
- }
- }
- // Retain only the shortest relative name.
- for (int i = 0; i < names.length; i++) {
- if (names[i] != null && names[i].length() < name.length()) {
- name = names[i];
- }
- }
- }
- ZipEntry e = new ZipEntry(name.replace(File.separatorChar, '/'));
- e.setTime(f.lastModified());
- jos.putNextEntry(e);
- FileInputStream fis = new FileInputStream(f);
- byte[] buffer = new byte[1024];
- int length;
- while ((length = fis.read(buffer)) != -1) {
- jos.write(buffer, 0, length);
- }
- fis.close();
- jos.closeEntry();
- }
- jos.close();
- }
- /**
- * Default constructor that simply initializes everything.
- */
- public Builder() {
- this(Logger.create(Builder.class));
- }
- /**
- * Constructor that simply initializes everything.
- * @param logger where to send messages
- */
- public Builder(Logger logger) {
- this.logger = logger;
- System.setProperty("org.bytedeco.javacpp.loadlibraries", "false");
- properties = Loader.loadProperties();
- classScanner = new ClassScanner(logger, new ArrayList<Class>(),
- new UserClassLoader(Thread.currentThread().getContextClassLoader()));
- compilerOptions = new ArrayList<String>();
- }
- /** Logger where to send debug, info, warning, and error messages. */
- final Logger logger;
- /** The directory where the generated files and compiled shared libraries get written to.
- * By default they are placed in the same directory as the {@code .class} file. */
- File outputDirectory = null;
- /** The name of the output generated source file or shared library. This enables single-
- * file output mode. By default, the top-level enclosing classes get one file each. */
- String outputName = null;
- /** The name of the JAR file to create, if not {@code null}. */
- String jarPrefix = null;
- /** If true, compiles the generated source file to a shared library and deletes source. */
- boolean compile = true;
- /** If true, preserves the generated C++ JNI files after compilation */
- boolean deleteJniFiles = true;
- /** If true, also generates C++ header files containing declarations of callback functions. */
- boolean header = false;
- /** If true, also copies to the output directory dependent shared libraries (link and preload). */
- boolean copyLibs = false;
- /** Accumulates the various properties loaded from resources, files, command line options, etc. */
- Properties properties = null;
- /** The instance of the {@link ClassScanner} that fills up a {@link Collection} of {@link Class} objects to process. */
- ClassScanner classScanner = null;
- /** User specified environment variables to pass to the native compiler. */
- Map<String,String> environmentVariables = null;
- /** Contains additional command line options from the user for the native compiler. */
- Collection<String> compilerOptions = null;
- /** Splits argument with {@link File#pathSeparator} and appends result to paths of the {@link #classScanner}. */
- public Builder classPaths(String classPaths) {
- classPaths(classPaths == null ? null : classPaths.split(File.pathSeparator));
- return this;
- }
- /** Appends argument to the paths of the {@link #classScanner}. */
- public Builder classPaths(String ... classPaths) {
- classScanner.getClassLoader().addPaths(classPaths);
- return this;
- }
- /** Sets the {@link #outputDirectory} field to the argument. */
- public Builder outputDirectory(String outputDirectory) {
- outputDirectory(outputDirectory == null ? null : new File(outputDirectory));
- return this;
- }
- /** Sets the {@link #outputDirectory} field to the argument. */
- public Builder outputDirectory(File outputDirectory) {
- this.outputDirectory = outputDirectory;
- return this;
- }
- /** Sets the {@link #compile} field to the argument. */
- public Builder compile(boolean compile) {
- this.compile = compile;
- return this;
- }
- /** Sets the {@link #deleteJniFiles} field to the argument. */
- public Builder deleteJniFiles(boolean deleteJniFiles) {
- this.deleteJniFiles = deleteJniFiles;
- return this;
- }
- /** Sets the {@link #header} field to the argument. */
- public Builder header(boolean header) {
- this.header = header;
- return this;
- }
- /** Sets the {@link #copyLibs} field to the argument. */
- public Builder copyLibs(boolean copyLibs) {
- this.copyLibs = copyLibs;
- return this;
- }
- /** Sets the {@link #outputName} field to the argument. */
- public Builder outputName(String outputName) {
- this.outputName = outputName;
- return this;
- }
- /** Sets the {@link #jarPrefix} field to the argument. */
- public Builder jarPrefix(String jarPrefix) {
- this.jarPrefix = jarPrefix;
- return this;
- }
- /** Sets the {@link #properties} field to the ones loaded from resources for the specified platform. */
- public Builder properties(String platform) {
- if (platform != null) {
- properties = Loader.loadProperties(platform, null);
- }
- return this;
- }
- /** Adds all the properties of the argument to the {@link #properties} field. */
- public Builder properties(Properties properties) {
- if (properties != null) {
- for (Map.Entry e : properties.entrySet()) {
- property((String)e.getKey(), (String)e.getValue());
- }
- }
- return this;
- }
- /** Sets the {@link #properties} field to the ones loaded from the specified file. */
- public Builder propertyFile(String filename) throws IOException {
- propertyFile(filename == null ? null : new File(filename));
- return this;
- }
- /** Sets the {@link #properties} field to the ones loaded from the specified file. */
- public Builder propertyFile(File propertyFile) throws IOException {
- if (propertyFile == null) {
- return this;
- }
- FileInputStream fis = new FileInputStream(propertyFile);
- properties = new Properties();
- try {
- properties.load(new InputStreamReader(fis));
- } catch (NoSuchMethodError e) {
- properties.load(fis);
- }
- fis.close();
- return this;
- }
- /** Sets a property of the {@link #properties} field, in either "key=value" or "key:value" format. */
- public Builder property(String keyValue) {
- int equalIndex = keyValue.indexOf('=');
- if (equalIndex < 0) {
- equalIndex = keyValue.indexOf(':');
- }
- property(keyValue.substring(2, equalIndex),
- keyValue.substring(equalIndex+1));
- return this;
- }
- /** Sets a key/value pair property of the {@link #properties} field. */
- public Builder property(String key, String value) {
- if (key.length() > 0 && value.length() > 0) {
- properties.put(key, value);
- }
- return this;
- }
- /** Requests the {@link #classScanner} to add a class or all classes from a package.
- * A {@code null} argument indicates the unnamed package. */
- public Builder classesOrPackages(String ... classesOrPackages) throws IOException, ClassNotFoundException, NoClassDefFoundError {
- if (classesOrPackages == null) {
- classScanner.addPackage(null, true);
- } else for (String s : classesOrPackages) {
- classScanner.addClassOrPackage(s);
- }
- return this;
- }
- /** Sets the {@link #environmentVariables} field to the argument. */
- public Builder environmentVariables(Map<String,String> environmentVariables) {
- this.environmentVariables = environmentVariables;
- return this;
- }
- /** Appends arguments to the {@link #compilerOptions} field. */
- public Builder compilerOptions(String ... options) {
- if (options != null) {
- compilerOptions.addAll(Arrays.asList(options));
- }
- return this;
- }
- /**
- * Starts the build process and returns an array of {@link File} produced.
- *
- * @return the array of File produced
- * @throws IOException
- * @throws InterruptedException
- * @throws ParserException
- */
- public File[] build() throws IOException, InterruptedException, ParserException {
- if (classScanner.getClasses().isEmpty()) {
- return null;
- }
- List<File> outputFiles = new ArrayList<File>();
- Map<String, LinkedHashSet<Class>> map = new LinkedHashMap<String, LinkedHashSet<Class>>();
- for (Class c : classScanner.getClasses()) {
- if (Loader.getEnclosingClass(c) != c) {
- continue;
- }
- ClassProperties p = Loader.loadProperties(c, properties, false);
- if (!p.isLoaded()) {
- logger.warn("Could not load platform properties for " + c);
- continue;
- }
- String target = p.getProperty("target");
- if (target != null && !c.getName().equals(target)) {
- File f = parse(classScanner.getClassLoader().getPaths(), c);
- if (f != null) {
- outputFiles.add(f);
- }
- continue;
- }
- String libraryName = outputName != null ? outputName : p.getProperty("platform.library", "");
- if (libraryName.length() == 0) {
- continue;
- }
- LinkedHashSet<Class> classList = map.get(libraryName);
- if (classList == null) {
- map.put(libraryName, classList = new LinkedHashSet<Class>());
- }
- classList.addAll(p.getEffectiveClasses());
- }
- for (String libraryName : map.keySet()) {
- LinkedHashSet<Class> classSet = map.get(libraryName);
- Class[] classArray = classSet.toArray(new Class[classSet.size()]);
- File f = generateAndCompile(classArray, libraryName);
- if (f != null) {
- outputFiles.add(f);
- if (copyLibs) {
- // Do not copy library files from inherit properties ...
- ClassProperties p = Loader.loadProperties(classArray, properties, false);
- List<String> preloads = new ArrayList<String>();
- preloads.addAll(p.get("platform.preload"));
- preloads.addAll(p.get("platform.link"));
- // ... but we should use all the inherited paths!
- p = Loader.loadProperties(classArray, properties, true);
- File directory = f.getParentFile();
- for (String s : preloads) {
- URL[] urls = Loader.findLibrary(null, p, s, true);
- File fi;
- try {
- fi = new File(urls[0].toURI());
- } catch (Exception e) {
- continue;
- }
- File fo = new File(directory, fi.getName());
- if (fi.exists() && !outputFiles.contains(fo)) {
- logger.info("Copying " + fi);
- FileInputStream fis = new FileInputStream(fi);
- FileOutputStream fos = new FileOutputStream(fo);
- byte[] buffer = new byte[1024];
- int length;
- while ((length = fis.read(buffer)) != -1) {
- fos.write(buffer, 0, length);
- }
- fos.close();
- fis.close();
- outputFiles.add(fo);
- }
- }
- }
- }
- }
- File[] files = outputFiles.toArray(new File[outputFiles.size()]);
- if (jarPrefix != null && files.length > 0) {
- File jarFile = new File(jarPrefix + "-" + properties.get("platform") + ".jar");
- File d = jarFile.getParentFile();
- if (d != null && !d.exists()) {
- d.mkdir();
- }
- createJar(jarFile, outputDirectory == null ? classScanner.getClassLoader().getPaths() : null, files);
- }
- // reset the load flag to let users load compiled libraries
- System.setProperty("org.bytedeco.javacpp.loadlibraries", "true");
- return files;
- }
- /**
- * Simply prints out to the display the command line usage.
- */
- public static void printHelp() {
- String version = Builder.class.getPackage().getImplementationVersion();
- if (version == null) {
- version = "unknown";
- }
- System.out.println(
- "JavaCPP version " + version + "\n" +
- "Copyright (C) 2011-2016 Samuel Audet <samuel.audet@gmail.com>\n" +
- "Project site: https://github.com/bytedeco/javacpp");
- System.out.println();
- System.out.println("Usage: java -jar javacpp.jar [options] [class or package (suffixed with .* or .**)]");
- System.out.println();
- System.out.println("where options include:");
- System.out.println();
- System.out.println(" -classpath <path> Load user classes from path");
- System.out.println(" -d <directory> Output all generated files to directory");
- System.out.println(" -o <name> Output everything in a file named after given name");
- System.out.println(" -nocompile Do not compile or delete the generated source files");
- System.out.println(" -nodelete Do not delete generated C++ JNI files after compilation");
- System.out.println(" -header Generate header file with declarations of callbacks functions");
- System.out.println(" -copylibs Copy to output directory dependent libraries (link and preload)");
- System.out.println(" -jarprefix <prefix> Also create a JAR file named \"<prefix>-<platform>.jar\"");
- System.out.println(" -properties <resource> Load all properties from resource");
- System.out.println(" -propertyfile <file> Load all properties from file");
- System.out.println(" -D<property>=<value> Set property to value");
- System.out.println(" -Xcompiler <option> Pass option directly to compiler");
- System.out.println();
- }
- /**
- * The terminal shell interface to the Builder.
- *
- * @param args an array of arguments as described by {@link #printHelp()}
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- boolean addedClasses = false;
- Builder builder = new Builder();
- for (int i = 0; i < args.length; i++) {
- if ("-help".equals(args[i]) || "--help".equals(args[i])) {
- printHelp();
- System.exit(0);
- } else if ("-classpath".equals(args[i]) || "-cp".equals(args[i]) || "-lib".equals(args[i])) {
- builder.classPaths(args[++i]);
- } else if ("-d".equals(args[i])) {
- builder.outputDirectory(args[++i]);
- } else if ("-o".equals(args[i])) {
- builder.outputName(args[++i]);
- } else if ("-cpp".equals(args[i]) || "-nocompile".equals(args[i])) {
- builder.compile(false);
- } else if ("-nodelete".equals(args[i])) {
- builder.deleteJniFiles(false);
- } else if ("-header".equals(args[i])) {
- builder.header(true);
- } else if ("-copylibs".equals(args[i])) {
- builder.copyLibs(true);
- } else if ("-jarprefix".equals(args[i])) {
- builder.jarPrefix(args[++i]);
- } else if ("-properties".equals(args[i])) {
- builder.properties(args[++i]);
- } else if ("-propertyfile".equals(args[i])) {
- builder.propertyFile(args[++i]);
- } else if (args[i].startsWith("-D")) {
- builder.property(args[i]);
- } else if ("-Xcompiler".equals(args[i])) {
- builder.compilerOptions(args[++i]);
- } else if (args[i].startsWith("-")) {
- builder.logger.error("Invalid option \"" + args[i] + "\"");
- printHelp();
- System.exit(1);
- } else {
- builder.classesOrPackages(args[i]);
- addedClasses = true;
- }
- }
- if (!addedClasses) {
- builder.classesOrPackages((String[])null);
- }
- builder.build();
- }
- }