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>
Другие вопросы по тегам