2010-01-08 3 views
6

Ma compilation dynamique dans Java 6 fonctionne parfaitement. Cependant, je voudrais changer le chemin de sortie. J'ai essayé des tonnes de choses (je vous épargnerai) en vain. Quoi qu'il en soit, voici le code de travailSpécifier le chemin de sortie pour la compilation dynamique

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 suppose que la réponse peut se trouver dans le compiler.getTask mais l'API n'est pas très explicite quant à ce que certains des paramètres pourraient signifier. Ou peut-être quelque chose avec le gestionnaire de fichiers. J'ai essayé

fileManager.setLocation(StandardLocation.locationFor("testFiles2"), null); 

mais encore une fois, deviner n'est probablement pas une bonne idée.

Merci!

Edit: J'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 « non valide Drapeau."

+0

+1 pour me faire savoir qu'il ya une telle chose que la compilation dynamique maintenant! –

+0

Il y en avait toujours, maintenant c'est intégré! –

+0

Ma réponse a été mise à jour. –

Répondre

5

code dans le premier poste travaillerait, mais ce get d'erreur suivant jeté:

java.lang.IllegalArgumentException: invalid flag: -d folder 

En effet, en passant "-d folder" fait penser à l'analyseur qu'il analyse 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(); 
+0

qu'en est-il des chemins comme "c: \\ foo bar \\ foo" ou "c:/foo bar/foo"? L'espace ou les barres obliques peuvent-ils être analysés correctement? – Gobliins

+0

Je ne sais pas, mais je suppose qu'il n'est pas nécessaire d'échapper car les arguments sont maintenant passés correctement (et parce que la nature du problème original était exactement celle des paramètres n'étant pas analysés séparément). Essayer de faire un rapport? – Gima

4

J'ai 0 expérience avec les outils du compilateur dynamique Java 6. Mais personne d'autre n'a répondu :)

La tâche de compilation obtient un objet FileManager. Si vous utilisez le standard, 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 substituée. La description de l'API de getFileForOutput indique que cela influencera l'emplacement des fichiers de sortie (= classe).

Mise à jour

Comment raccorder les gestionnaires de fichiers

ForwardingJavaFileManager, ForwardingFileObject et ForwardingJavaFileObject Subclassing ne sont pas disponibles pour des raisons impérieuses le comportement d'un gestionnaire de fichiers standard est créé en appelant un méthode sur un compilateur, pas en invoquant un constructeur. Au lieu de transmettre (ou délégation) devrait être utilisé. Ces classes facilitent le transfert de la plupart des appels vers un gestionnaire de fichiers ou un objet fichier donné tout en permettant le comportement de personnalisation. 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

j'ai lu sur la compilation dynamique et construit ma propre application pour le faire. Ce code contient un peu trop de cérémonie (c'est-à-dire qu'il pourrait être simplifié) mais ça marche! Je ne suis pas sûr comment obtenir ce code pour fonctionner avec une liste générée dynamiquement de fichiers Java; Je ferais probablement juste compiler.run séparément pour chaque fichier source.

+0

Cela peut être vrai, mais malheureusement, getJavaFileObjects est seulement sur le StandardJavaFileManager .... Je vais voir ce qui peut être fait de toute façon. Si c'était Ruby, votre réponse suffirait à corriger le singe et à être fait :) –

+0

En Java, le chemin à parcourir est le sous-classement ... 'ForwardingJavaFileManager' implémente' StandardJavaFileManager' et c'est celui que vous utiliseriez. –

+0

En fait, il a un constructeur que vous pouvez enrouler autour du FileManager que vous obtiendriez de 'compiler'. Vous voudrez rendre ce constructeur public dans votre classe dérivée, bien sûr. –

8

Je faisais face à ce même problème aujourd'hui.

La réponse (en utilisant la méthode getTask régulière au lieu de'Exécuter) 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 trompeuse, je veux dire, un échantillon pourrait être très utile. Mais finalement, il m'a fallu là-bas.

EDIT

Voici un exemple de fonctionnement:

// 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(); 
+0

Cela fait un moment que j'ai regardé ce problème. Donc vous dites que votre réponse résout le problème dans sa totalité? –

+0

Yeap !!!, à peu près. Je vais mettre à jour la réponse avec un exemple – OscarRyz

+0

Fonctionne bien - même chose qu'en utilisant "-d" dans le paramètre options getTask(), mais plus propre. – Atorian

Questions connexes