appassembler-maven-plugin - как включить файлы собственных библиотек при создании сценариев для Windows и Unix
Привет, я работаю над приложением Java, которое встроено в дистрибутивный файл (zip-файл) с помощью appassembler-maven-plugin. Конечные пользователи извлекают содержимое почтового индекса.
Используя этот плагин, мы создаем структуру распространения, которая включает необходимые jar-файлы и два сценария выполнения (сценарий оболочки для unix и пакетный сценарий для windows). Эти сценарии генерируются автоматически в процессе сборки.
Файл POM содержит следующее:
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<attach>true</attach>
<descriptors>
<descriptor>src/main/resources/distribution.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- this is used for inheritance merges -->
<phase>package</phase>
<!-- bind to the packaging phase -->
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<executions>
<execution>
<id>assemble-standalone</id>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
<configuration>
<programs>
<program>
<name>mixnet</name>
<mainClass>com.company.products.Application</mainClass>
</program>
</programs>
<repositoryLayout>flat</repositoryLayout>
<repositoryName>lib</repositoryName>
<configurationDirectory>properties</configurationDirectory>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<configurationSourceDirectory>src/main/resources</configurationSourceDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach-distribution</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>target/${project.artifactId}-${project.version}-distribution.zip</file>
<type>zip</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Сгенерированный сценарий оболочки содержит следующую строку, которая делает фактический вызов Java:
%JAVACMD% %JAVA_OPTS% %EXTRA_JVM_ARGUMENTS% -classpath%CLASSPATH_PREFIX%;%CLASSPATH% -Dapp.name="mixnet" -Dapp.repo="%REPO%" -Dbasedir="%BASEDIR%" com.company.products.Application %CMD_LINE_ARGS%
Пакетный скрипт содержит следующую строку, которая делает фактический вызов Java:
exec "$JAVACMD" $JAVA_OPTS \
$EXTRA_JVM_ARGUMENTS \
-classpath "$CLASSPATH" \
-Dapp.name="mixnet" \
-Dapp.pid="$$" \
-Dapp.repo="$REPO" \
-Dapp.home="$BASEDIR" \
-Dbasedir="$BASEDIR" \
com.company.products.Application \
"$@"
Теперь мы расширили программу Java так, чтобы она использовала собственные файлы библиотек, эти файлы включены в дистрибутив в папку, называемую "native" (файлы.dll для windows и.so файлы для сред unix включены в собственный каталог)
Я хотел бы отредактировать процесс сборки так, чтобы сгенерированные сценарии (как сценарий оболочки для Unix, так и пакетный сценарий для Windows) включали параметр "-Djava.library.path=PATH_OF_LIBRARY_FILES".
Я провел некоторый поиск, но не могу найти какую-либо документацию относительно поддержки этого параметра в плагине appassembler.
Я попытался найти "хакерское" решение, добавив тег "extraJvmArguments" в файл pom приложения и указав там параметр "-Djava.library.path", но столкнулся с проблемами, связанными с разделителем пути в Windows и Linux ("\" или "/"). Я также подумал об использовании "extraJvmArguments" и использовании системной переменной для указания пути к каталогу (который должен был бы определить пользователь), но у этого подхода также есть проблемы с платформой, поскольку на системную переменную ссылаются с помощью $VARIABLE_NAME в linux, но с%VARIABLE_NAME% на окнах.
Мы могли бы попросить конечных пользователей отредактировать сценарий выполнения самостоятельно, прежде чем они его выполнят, но было бы намного лучше, если бы этот процесс был автоматическим и полностью прозрачным для конечных пользователей. Таким образом, конечные пользователи даже не будут знать, что они запускают приложение Java, которое использует JNI для вызова собственной библиотеки.
Я не знаю ни одного платформенно-нейтрального решения. Appassembler уже поддерживает это требование? или как это должно быть обработано?
3 ответа
Согласно источникам maven-assembly-plugin здесь и здесь, одиночная настройка <repositoryName>lib</repositoryName>
контролирует оба java.library.path
и jar classpath dir.
Не стесняйтесь голосовать за запрос функции, чтобы разделить их:
Возможность иметь собственные библиотеки в отдельном каталоге, не видна в classpath #62
Я нашел способ получить желаемый результат, но он включает в себя дублирование довольно большой части пом. Я продублировал секцию исполнения и в каждом исполнении добавлял значение extraJvmArguments для конкретной платформы, как показано ниже. Затем процесс сборки создает сценарии выполнения с правильными путями, специфичными для платформы.
<executions>
<execution>
<id>assemble-standalone-windows</id>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
<configuration>
<extraJvmArguments>-Djava.library.path=.\..\native\lib</extraJvmArguments>
<programs>
<program>
<platforms>
<platform>windows</platform>
</platforms>
<name>mixnet</name>
<mainClass>com.company.products.Application</mainClass>
</program>
</programs>
<repositoryLayout>flat</repositoryLayout>
<repositoryName>lib</repositoryName>
<configurationDirectory>properties</configurationDirectory>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<configurationSourceDirectory>src/main/resources</configurationSourceDirectory>
</configuration>
</execution>
<execution>
<id>assemble-standalone-unix</id>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
<configuration>
<extraJvmArguments>-Djava.library.path=./../native/lib</extraJvmArguments>
<programs>
<program>
<platforms>
<platform>unix</platform>
</platforms>
<name>mixnet</name>
<mainClass>com.scytl.products.ov.mixnet.Application</mainClass>
</program>
</programs>
<repositoryLayout>flat</repositoryLayout>
<repositoryName>lib</repositoryName>
<configurationDirectory>properties</configurationDirectory>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<configurationSourceDirectory>src/main/resources</configurationSourceDirectory>
</configuration>
</execution>
</executions>
Пожалуйста, поделитесь, если вы знаете лучший способ решения проблемы.
Вот пример с официального сайта: https://maven.apache.org/plugins/maven-assembly-plugin/usage.html
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>your main class</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>