Pergunta

Meu compilação dinâmica em Java 6 está funcionando perfeitamente. No entanto, eu gostaria de mudar o caminho de saída. Eu tentei toneladas de coisas (vou poupá-lo) sem sucesso. De qualquer forma, aqui está o código de trabalho

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());

Mas a saída vai para o diretório de origem, o que não é o que eu quero.

Eu suspeito que a resposta pode estar na compiler.getTask mas a API não é muito explícito quanto ao que alguns dos parâmetros poderia significar. Ou talvez algo com o gerenciador de arquivos. Eu tentei

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

mas, novamente, supondo que provavelmente não é uma boa idéia.

Obrigado!

Editar: Eu tentei usar opções, também, como este (desculpe se há uma maneira mais 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();
        }
    };

e, em seguida, passar as opções para getTask, mas a mensagem de erro é "bandeira inválido."

Foi útil?

Solução

Código no primeiro post iria funcionar, mas o seguinte get de erro é jogado:

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

Isto porque, passando "-d folder" faz com que o analisador acho que analisar uma opção. As opções devem ser separadas como "-d", "folder".

Exemplo de aplicação seguintes:

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();

Outras dicas

Eu estava enfrentando o mesmo problema hoje.

A resposta (usando o método getTask regular em vez de `run) é especificar o dir de saída no FileManager:

fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(outputDir));

E é isso !! :)

A documentação é um pouco enganosa, quer dizer, uma amostra poderia vir muito útil. Mas eventualmente ele me levou lá.

Editar

Aqui está um exemplo em execução:

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

Eu tenho 0 experiência com as ferramentas de compilação dinâmica Java 6. Mas ninguém respondeu:)

A tarefa de compilação obtém um objeto FileManager. Se você usar o padrão, então classes são geradas na árvore de diretório de origem. O que você poderia fazer é fornecer sua própria subclasse FileManager com um método getFileForOutput substituído. A descrição API de getFileForOutput indica que isso irá influenciar onde a sua saída (= classe) arquivos irá.

Atualizar

Como ligar os gerenciadores de arquivos

ForwardingJavaFileManager, ForwardingFileObject e ForwardingJavaFileObject Subclassing não está disponível para substituir o comportamento de um gerenciador de arquivos padrão como ele é criado por chamar um método em um compilador, não invocando um construtor. Em vez de encaminhamento (ou delegação) deve ser usado. Essas classes torna mais fácil de transmitir a maioria das chamadas para um determinado gerenciador de arquivos ou objeto de arquivo, permitindo comportamento personalizando. Por exemplo, considere como para registrar todas as chamadas para 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();

Update 2

I ler sobre a compilação dinâmica e construí meu próprio aplicativo para fazer isso. Este código contém um pouco demais cerimônia (ou seja, ele pode ser simplificado) mas 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());
      }
   }

}

Eu não tenho certeza de como obter este código para trabalhar com uma lista gerada dinamicamente de arquivos Java; Eu provavelmente apenas fazer compiler.run separadamente para cada arquivo-fonte.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top