Укажите выходной путь для динамической компиляции - PullRequest
9 голосов
/ 08 января 2010

Моя динамическая компиляция в Java 6 работает отлично. Тем не менее, я хотел бы изменить выходной путь. Я перепробовал кучу вещей (я тебя пощадил) безрезультатно. Во всяком случае, вот рабочий код

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

Но вывод идет в исходный каталог, а это не то, что мне нужно.

Я подозреваю, что ответ может лежать в compiler.getTask, но API не очень ясно указывает, что могут означать некоторые параметры. Или, возможно, что-то с файловым менеджером. Я пробовал

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

но, опять же, догадки, вероятно, не очень хорошая идея.

Спасибо!

Редактировать: Я тоже пытался использовать опции, вот так (извините, если есть более компактный способ):

    final List<String> optionsList = new ArrayList<String>();
    optionsList.add("-d what");
    Iterable<String> options = new Iterable<String>() {         
        public Iterator<String> iterator() {
            return optionsList.iterator();
        }
    };

, а затем передать параметры getTask, но сообщение об ошибке «Недопустимый флаг».

Ответы [ 3 ]

9 голосов
/ 08 сентября 2010

Я столкнулся с этой же проблемой сегодня.

Ответ (с использованием обычного метода getTask вместо `run) заключается в указании выходного каталога в FileManager:

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

И это все !! :)

Документация немного вводит в заблуждение, я имею в виду, что образец может оказаться очень полезным. Но в конце концов это привело меня туда.

РЕДАКТИРОВАТЬ

Вот пример работы:

    // 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();
6 голосов
/ 23 сентября 2011

Код в первом посте будет работать, но выдается следующая ошибка:

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

Это потому, что передача "-d folder" заставляет парсер думать, что он анализирует один из вариантов. Опции должны быть разделены как "-d", "folder".

Ниже приведен рабочий пример:

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();
4 голосов
/ 08 января 2010

У меня 0 опыта работы с инструментами динамического компилятора Java 6. Но никто не ответил:)

Задача компиляции получает объект FileManager. Если вы используете стандартный, то классы генерируются в исходном дереве каталогов. Что вы можете сделать, это предоставить свой собственный подкласс FileManager с переопределенным методом getFileForOutput. Описание API getFileForOutput указывает, что это будет влиять на то, куда пойдут ваши выходные файлы (= class).

Обновление

Как подключить файловые менеджеры

ForwardingJavaFileManager, ForwardingFileObject и ForwardingJavaFileObject Подклассы недоступны для переопределения поведения стандартного файлового менеджера, так как он создается путем вызова метода компилятора, а не вызова конструктора. Вместо этого следует использовать пересылку (или делегирование). Эти классы облегчают переадресацию большинства вызовов в данный файловый менеджер или файловый объект, позволяя при этом настраивать поведение. Например, рассмотрим, как регистрировать все вызовы 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();

Обновление 2

Я прочитал о динамической компиляции и создал для этого собственное приложение. Этот код содержит слишком много церемоний (то есть его можно упростить), но он работает!

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

}

Я не уверен, как заставить этот код работать с динамически генерируемым списком файлов Java; Я бы, вероятно, просто сделал compiler.run отдельно для каждого исходного файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...