Главная идея статьи — это показать как заставить ЭТО (kotlin & maven toolchain) работать вместе. Детального описания Maven toolchain здесь не будет, не хочу заниматься банальным переводом руководств.
Начну с прелюдии. Как котлинисту, мне новые версии java как-то по боку, но тут в JDK 22 подъехала годнота — panama/foreign вышла из инкубатора. Для тех кто не в теме, эта фича дает вам возможность вызывать нативный код из 'динамической библиотеки' dll/so (прямо из java кода). Теперь вы можете вызывать системные функции сами, а не подключать неизвестные вам библиотеки.
Вкратце о Maven toolchain.
Эта фича позволяет подключать нужную версию jdk (или других инструментов) автоматически. До апреля 2024 года maven toolchain плагин был довольно слабенький (по сравнению с gradle toolchains) — он позволял выбирать toolchain/jdk только из
Но вот недавно (в апреле 2024) подъехала новая версия, которая поддерживает
$home/.m2/toolchains.xml файл
может подхватывать текущий JDK ($JAVA_HOME), если он удовлетворяет заданным критериям
делает поиск в стандартных директориях (например, C:/Program Files/…)
Реально прикольная штука, ничего вообще делать не нужно. Проверил на Windows — реально работает. Какое стандартное расположение жабы в Linux — не имею понятия, но можно хотя бы ввести разные JAVA_XXX_HOME (это уже неплохо).
делает поиск в переменных окружения по паттерну (например: JAVA11_HOME, JAVA22_HOME). Паттерн конфигурируем.
Между прочим, gradle toolchains тоже поддерживают этот подход, но насколько я знаю, переменные нужно добавлять файл проекта вручную.
custom toolchains
Сейчас maven toolchain даже немного лучше своего собрата из gradle. В gradle есть неприятный баг по игнорированию vendor (и др атрибутов) из $home/.m2/toolchains.xml, в результате невозможно отличить Oracle (standard) JDK от Oracle Graal JDK.
Перейдем к главному.
У нас всё ещё есть одна проблемка — maven kotlin plugin не дружит с maven toolchain plugin. По крайней мере я не нашел как ему сказать, чтобы он подружился.
Но… у maven kotlin plugin есть конфигурационный параметр jdkHome, который мапится на maven property «toolchain.jdk.version». Это и будет нашим спасением — нужно взять JDK home, найденный toolchain plugin и установить его в соответсвующее свойство. Как по мне решение ± надежное (весь рискованный код помещен в try/catch), но это уже ваш выбор использовать ли его в production, или только в домашнем проекте. В худшем случае, оно просто не будет работать и вы просто вернетесь к старой доброй установке JAVA_HOME.
...
[22,)22${java.version}1.7.01.715true${kotlin.version}org.apache.maven.pluginsmaven-toolchains-plugin3.2.0select-jdk-toolchain${toolchain.jdk.version}${toolchain.jdk.version}org.codehaus.mojobuild-helper-maven-plugin3.4.0use-maven-toolchain-jdk-for-kotlinbsh-property 0)
toolChainJdk = config.getChild(0).getValue().trim();
}
} catch (Exception ex) {
log.error("toolchain-jdk is not found. " + ex.getMessage(), ex);
// Or we can rethrow error just there.
// throw new IllegalStateException("toolchain-jdk is not found.", ex);
}
String requiredJdkVersion = project.getProperties().getProperty("toolchain.jdk.version");
if (toolChainJdk != null && !toolChainJdk.isEmpty()) {
project.getProperties().setProperty("kotlin.compiler.jdkHome", toolChainJdk);
log.info("toolchain-jdk for version '" + requiredJdkVersion + "' is " + toolChainJdk);
log.info("It will be used for kotlin compiler");
}
else {
String currentJavaHome = System.getProperty("java.home");
log.info("toolchain-jdk for version '" + requiredJdkVersion + "' is not found.");
log.info(" Possible reasons");
log.info(" * default java_home matches required java version ");
log.info(" * maven-toolchains-plugin is not configured properly");
log.info(" ");
log.info("Default " + currentJavaHome + " will be used.");
}
]]>