سؤال

تجميعي الديناميكي في 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. لقد حاولت

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، ولكن رسالة الخطأ هي "علم غير صالح".

هل كانت مفيدة؟

المحلول

كود في المشاركة الأولى سيعمل، ولكن الخطأ التالي يحصل على:

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

نصائح أخرى

كنت تواجه هذه المشكلة نفسها اليوم.

الجواب (باستخدام العادية getTask الطريقة بدلا من `Run) هي تحديد DIR الإخراج في 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();

لدي خبرة 0 مع أدوات الجافا 6 المترجم الحيوي. لكن لا أحد آخر قد أجاب :)

مهمة التجميع تحصل على FileManager هدف. إذا كنت تستخدم معيار واحد، يتم إنشاء الفصول الدراسية في شجرة الدليل المصدر. ما يمكنك فعله هو توفير فرعية FileManager الخاصة بك مع تجاوز getFileForOutput طريقة. يشير وصف API ل GetFileForoutPut إلى أن هذا سوف يؤثر على حيث ستذهب ملفات الإخراج (= فئة).

تحديث

كيفية ربط مديري الملفات

Forwardingjavafilemanager، ForwardingFileObject، و ForwardingjavaFaFileObject Subverclassing غير متوفر لتجاوز سلوك إدارة الملفات القياسية كما يتم إنشاؤه عن طريق الاتصال بطريقة مترجم، وليس عن طريق استدعاء منشئ. بدلا من ذلك يجب إعادة توجيه (أو تفويض). تجعل هذه الفئات من السهل توجيه معظم المكالمات إلى إدارة ملفات أو كائن ملف معين أثناء السماح بتخصيص السلوك. على سبيل المثال، فكر في كيفية تسجيل جميع المكالمات إلى 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 بشكل منفصل لكل ملف مصدر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top