Especificar ruta de salida para la dinámica de Compilación
-
19-09-2019 - |
Pregunta
Mi compilación dinámica en Java 6 está funcionando perfectamente. Sin embargo, me gustaría cambiar la ruta de salida. He probado un montón de cosas (Les ahorraré) fue en vano. De todos modos, aquí está el código de trabajo
String[] filesToCompile = { "testFiles/Something.java" };
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(filesToCompile);
CompilationTask task = compiler.getTask(null, fileManager, null,null, null, compilationUnits);
System.out.println("Good? " + task.call());
Sin embargo, la salida va al directorio de origen, que no es lo que quiero.
Sospecho que la respuesta puede estar en la compiler.getTask
pero la API no es muy explícito en cuanto a lo que algunos de los parámetros podría significar. O tal vez algo con el administrador de archivos. He intentado
fileManager.setLocation(StandardLocation.locationFor("testFiles2"), null);
pero de nuevo, adivinando probablemente no es una buena idea.
Gracias!
Editar He intentado usar opciones, también, como esto (lo siento si hay una manera más compacta):
final List<String> optionsList = new ArrayList<String>();
optionsList.add("-d what");
Iterable<String> options = new Iterable<String>() {
public Iterator<String> iterator() {
return optionsList.iterator();
}
};
y luego pasar a las opciones getTask, pero mensaje de error es "bandera no válida."
Solución
Código en el primer post iba a funcionar, pero el siguiente de error que se consiga:
java.lang.IllegalArgumentException: invalid flag: -d folder
Esto se debe a que al pasar "-d folder"
hace que el analizador creo que es una de las opciones de análisis. Las opciones deben estar separados como "-d", "folder"
.
Ejemplo de trabajo sigue:
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager sjfm = javaCompiler.getStandardFileManager(null, null, null);
String[] options = new String[] { "-d", "output" };
File[] javaFiles = new File[] { new File("src/gima/apps/flip/TestClass.java") };
CompilationTask compilationTask = javaCompiler.getTask(null, null, null,
Arrays.asList(options),
null,
sjfm.getJavaFileObjects(javaFiles)
);
compilationTask.call();
Otros consejos
Yo estaba frente a este mismo problema hoy en día.
La respuesta (utilizando el método getTask
regular en lugar de `run) es especificar el dir de salida en el el FileManager:
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(outputDir));
Y eso es todo !! :)
La documentación es un poco engañosa, es decir, una muestra podría ser muy útil. Pero con el tiempo que me llevó allí.
Editar
Esto es una muestra ejecutando:
// write the test class
File sourceFile = new File("First.java");
FileWriter writer = new FileWriter(sourceFile);
writer.write(
"package load.test;\n" +
"public class First{}"
);
writer.close();
// Get the java compiler for this platform
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(
null,
null,
null);
//-- H E R E --//
// Specify where to put the genereted .class files
fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
Arrays.asList(new File("/tmp")));
// Compile the file
compiler
.getTask(null,
fileManager,
null,
null,
null,
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile)))
.call();
fileManager.close();
// delete the file
sourceFile.deleteOnExit();
Tengo 0 experiencia con las herramientas de compilación de Java 6 dinámicos. Pero nadie ha contestado:)
La tarea de recopilación obtiene un objeto FileManager
. Si utiliza el estándar, a continuación, las clases se generan en el árbol de directorio de origen. Lo que podría hacer es proporcionar su propia subclase Gestión de archivos con un método getFileForOutput
reemplazado. La descripción de la API de getFileForOutput indica que esto influirá en los archivos de su salida (= clase) irán.
Actualizar
Cómo conectar los administradores de archivos
ForwardingJavaFileManager, ForwardingFileObject y ForwardingJavaFileObject Subclases no está disponible para anular el comportamiento de un administrador de archivos estándar, ya que se crea llamando a un método en un compilador, no mediante la invocación de un constructor. En lugar de reenvío (o delegación) debe ser utilizado. Estas clases hace que sea fácil que transmita la mayoría de las llamadas a un gestor de archivos o archivos objeto dado al tiempo que permite la personalización de la conducta. Por ejemplo, considere la forma de registrar todas las llamadas a JavaFileManager.flush ():
final Logger logger = ...;
Iterable<? extends JavaFileObject> compilationUnits = ...;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) {
public void flush() {
logger.entering(StandardJavaFileManager.class.getName(), "flush");
super.flush();
logger.exiting(StandardJavaFileManager.class.getName(), "flush");
}
};
compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
Actualización 2
He leído en la compilación dinámica y construido mi propia aplicación para hacer esto. Este código contiene un poco demasiado ceremonia (es decir, que podría ser simplificado) pero funciona!
package yar;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class DynamicCompiler {
JavaCompiler compiler;
public DynamicCompiler() {
this.compiler = ToolProvider.getSystemJavaCompiler();
if (this.compiler == null) {
throw new NullPointerException("Cannot provide system compiler.");
}
}
public void compile() {
this.compiler.run(null, System.out, System.err,
"-d", "testFiles2",
"testFiles/Hello1.java", "testFiles/Hello2.java");
}
/**
* @param args
*/
public static void main(String[] args) {
try {
DynamicCompiler dc = new DynamicCompiler();
dc.compile();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
No estoy seguro de cómo obtener este código para trabajar con una lista generada dinámicamente de archivos Java; Probablemente me acabo de hacer compiler.run
por separado para cada archivo de origen.