Как заставить компилятор Java ТОЛЬКО компилировать указанный мной исходный файл? - PullRequest
3 голосов
/ 08 мая 2019

Компилятор java 12.0.1 (все мои тесты здесь выполняются в MS Windows) имеет довольно странное поведение при использовании аргумента -sourcepath в отношении того, что он решает скомпилировать. Самый простой способ объяснить это - привести два примера и привести различия в поведении.

Пример 1:

Исходный файл "A.java"

public class A {
    public static void main(String[] args) {
        System.out.println("Hello World");
        B.myMethod();
    }
}

Исходный файл "B.java"

public class B {
    public static void myMethod() {
        System.out.println("Goodbye!");
    }
}

Для компиляции примера 1 мы просто используем следующее:

javac -sourcepath . A.java

Это скомпилирует A.java и B.java и создаст A.class и B.class. Мы ожидаем, что он также скомпилирует B.java, потому что A зависит от него. Теперь подождите секунду или около того и без изменения исходного файла ".java", просто повторите команду компиляции, приведенную выше. Вы обнаружите, что он перекомпилирует A.java, и создается новый класс A.class (с обновленной отметкой времени), но B.class не перекомпилируется. Хорошо, это почти то, что можно ожидать. Теперь давайте сравним это со следующим примером ниже.

Пример 2:

Исходный файл "example2 / A.java"

package example2;
public class A {
    public static void main(String[] args) {
        System.out.println("Hello World");
        B.myMethod();
    }
}

Исходный файл "example2 / B.java"

package example2;
public class B {
    public static void myMethod() {
        System.out.println("Goodbye!");
    }
}

Исходные файлы одинаковы, за исключением того, что все перемещено в пакет. Мы хотим скомпилировать два исходных файла, находясь в данный момент в папке «example2». Поэтому мы используем следующую команду:

javac -sourcepath .. A.java

Это снова скомпилирует A.java и B.java и создаст A.class и B.class. Здесь нет проблем, как и раньше. Обратите внимание, что -sourcepath теперь "..", потому что теперь это корневая папка с исходным кодом, когда все в пакете. Теперь подождите секунду или около того и без изменения любого исходного файла, просто повторите команду компиляции выше. Вы обнаружите, что он перекомпилирует ОБА A.java и B.java, и создается новый файл A.class и B.class (с обновленными временными метками).

Обратите внимание на разницу в поведении компиляции при повторном запуске команды javac. Когда -sourcefile был "." и файлы не были в пакете, вторая команда «javac» компилирует только исходный файл, указанный в командной строке. Но когда -sourcefile равен ".." и классы находятся в пакете, вторая команда "javac" ВСЕГДА компилирует все зависимые исходные файлы, независимо от того, нужно ли перекомпилировать неуказанные исходные файлы.

Вопрос в том, почему? Какие аргументы я могу передать в командную строку javac, чтобы остановить пример 2 от безусловной перекомпиляции всех зависимых исходных файлов, если их файлы классов имеют более новую временную метку, чем исходные файлы?

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Эта проблема возникает из-за того, что javac сравнивает временные метки между файлом .java и файлом .class.Он использует -sourcepath для поиска исходных файлов и -classpath для поиска файлов классов.Поэтому вашу проблему можно исправить, указав classpath:

javac -sourcepath .. -classpath .. A.java
0 голосов
/ 10 мая 2019

Это похоже на ... Если вы перейдете к исходному корню, пакет по умолчанию:

cd ..
javac -sourcepath . ex/A.java

все работает (у меня дома): нет перекомпиляции B.java.

Возможно, это также связано с -classpath, но я бы скорее подумал о некоторой эзотерической проблеме с путями к пакетам.

0 голосов
/ 10 мая 2019

РЕДАКТИРОВАТЬ: я удалил мое предположение, что это ошибка, так как я принял другой ответ в качестве лучшего объяснения.

Кроме того, кажется, что нет разумного способа сообщить об этом как об ошибке в OpenJDK. Я гуглил и искал по всему сайту OpenJDK, и кажется, что bugs.openjdk.java.net предназначен только для доверенных разработчиков. Я думаю, я мог бы выбросить его в список рассылки OpenJDK, но это похоже на хак. Так что я даже не уверен, куда сообщить об этой ошибке, к сожалению.

...