Spécifiez le chemin de sortie pour la compilation dynamique
-
19-09-2019 - |
Question
Ma compilation dynamique en Java 6 fonctionne parfaitement. Cependant, je voudrais changer le chemin de sortie. J'ai essayé des tonnes de choses (je vais vous épargner) en vain. Quoi qu'il en soit, voici le code de travail
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());
Mais la sortie va dans le répertoire source, ce qui est pas ce que je veux.
Je soupçonne que la réponse réside peut-être dans le compiler.getTask
mais l'API est pas très explicite quant à ce que certains des paramètres pourrait signifier. Ou peut-être quelque chose avec le gestionnaire de fichiers. J'ai essayé
fileManager.setLocation(StandardLocation.locationFor("testFiles2"), null);
mais encore une fois, devinant est probablement pas une bonne idée.
Merci!
Modifier Je l'ai essayé d'utiliser des options aussi, comme ça (désolé s'il y a une façon plus compacte):
final List<String> optionsList = new ArrayList<String>();
optionsList.add("-d what");
Iterable<String> options = new Iterable<String>() {
public Iterator<String> iterator() {
return optionsList.iterator();
}
};
et en faisant passer les options à getTask, mais le message d'erreur est "Drapeau non valide".
La solution
code dans le premier poste travaillerait, mais de l'obtenir d'erreur suivant jeté:
java.lang.IllegalArgumentException: invalid flag: -d folder
En effet, en passant "-d folder"
fait l'analyseur pense qu'il est l'analyse syntaxique une option. Les options doivent être séparées comme "-d", "folder"
.
Exemple de travail suit:
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();
Autres conseils
Je faisais face à ce même problème aujourd'hui.
La réponse (en utilisant la méthode de getTask
ordinaire au lieu de `run) est de spécifier la sortie dir dans le gestionnaire de fichiers:
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(outputDir));
Et voilà !! :)
La documentation est un peu trompeur, je veux dire, un échantillon pourrait venir très pratique. Mais finalement, il m'a emmené.
EDIT
Voici un exemple en cours d'exécution:
// 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();
J'ai 0 expérience avec les Java 6 outils du compilateur dynamique. Mais personne d'autre a répondu:)
La tâche de compilation devient un objet FileManager
. Si vous utilisez la version standard, puis les classes sont générées dans l'arborescence du répertoire source. Ce que vous pouvez faire est de fournir votre propre sous-classe FileManager avec une méthode getFileForOutput
surchargée. La description de l'API de getFileForOutput indique que cela influencera où vos fichiers de sortie (= classe) vont.
Mise à jour
Comment raccorder les gestionnaires de fichiers
ForwardingJavaFileManager, ForwardingFileObject et ForwardingJavaFileObject Subclassing n'est pas disponible pour des raisons impérieuses le comportement d'un gestionnaire de fichiers standard est créé en appelant une méthode sur un compilateur, et non en invoquant un constructeur. expédition au lieu (ou délégation) devrait être utilisé. Ces classes, il est facile de transmettre la plupart des appels à un gestionnaire de fichier donné ou un objet fichier tout en permettant la personnalisation de comportement. Par exemple, considérez comment enregistrer tous les appels à 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();
Mise à jour 2
Je lis sur la compilation dynamique et construit ma propre application pour le faire. Ce code contient un peu trop cérémonie (ce pourrait être simplifié), mais ça marche!
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());
}
}
}
Je ne sais pas comment obtenir ce code pour travailler avec une liste générée dynamiquement des fichiers Java; Je serais probablement juste faire compiler.run
séparément pour chaque fichier source.