Как сказать Айви, чтобы положить загруженные банки в пользовательский каталог?

Я новичок в общении с Ivy и очень стараюсь, чтобы выучить обычно используемые библиотеки, такие как Guava и Gson, которые доступны в центральном репозитории Maven

<ivy-module version="2.0">
    <info organisation="com.company" module="foobar"/>    
    <dependencies>
        <dependency org="com.google.guava" name="guava" rev="10.0.1"/>
        <dependency org="com.google.code.gson" name="gson" rev="2.0"/>
    </dependencies>    
</ivy-module>

В Windows по умолчанию Ivy хранит свои файлы в %USERPROFILE%\.ivy2\cache\; на Unix-y-системах они загружаются в $HOME/.ivy2/.

Я предполагаю, что это довольно простой вопрос: как сказать Ivy для загрузки как двоичных файлов, так и источников, а также поместить двоичные банки в одну (произвольную) директорию и исходные банки в другой каталог?

Например, я бы хотел, чтобы Ivy помещал все загруженные двоичные банки в [project_home]/WebContent/WEB-INF/lib.

Обратите внимание, что я использую Ivy через Ant, в следующих строках, а не в плагин IDE.

<project xmlns:ivy="antlib:org.apache.ivy.ant" name="ivy" default="resolve" > 
    <target name="resolve" description="retrieve dependencies with ivy">
        <ivy:retrieve/>
    </target>

    <path id="ivy.lib.path">
        <fileset dir="tools/buildlibs" includes="*.jar"/>
    </path>
    <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>        
</project>

Ответы

Ответ 1

Другой SO ответ описывает, как конфигурации используются, чтобы отдельные группы зависимостей были разделены. Однако эта проблема может потребовать, чтобы зависимости были объявлены более одного раза, чтобы вписаться в различные конфигурации плюща.

Попробуйте следующее:

ivy.xml

<ivy-module version="2.0">
    <info organisation="com.company" module="foobar"/>    
    <configurations>
        <conf name="sources"  description="Source jars"/>
        <conf name="binaries" description="binary jars"/>
    </configurations>
    <dependencies>
        <dependency org="com.google.guava" name="guava" rev="10.0.1" conf="sources->sources"/>
        <dependency org="com.google.code.gson" name="gson" rev="2.0" conf="sources->sources"/>

        <dependency org="com.google.guava" name="guava" rev="10.0.1" conf="binaries->default"/>
        <dependency org="com.google.code.gson" name="gson" rev="2.0" conf="binaries->default"/>
    </dependencies>    
</ivy-module>

build.xml

<project xmlns:ivy="antlib:org.apache.ivy.ant" name="hello-ivy" default="resolve">

    <target name="resolve" description="retrieve dependencies with ivy">
        <ivy:retrieve conf="sources" pattern="lib/[conf]/[artifact](-[classifier]).[ext]"/>
        <ivy:retrieve conf="binaries" pattern="lib/[conf]/[artifact](-[classifier]).[ext]"/>
    </target>

    <target name="clean" description="Remove build directories">
        <delete dir="lib"/>
    </target>

    <target name="clean-all" depends="clean" description="clean ivy cache">
        <ivy:cleancache />
    </target>

</project>

Примечание: Обновлено для добавления цели, которая очищает кэш плюща.

Сборка выполняется следующим образом, чтобы гарантировать, что артефакты будут загружены только:

$ ant clean-all resolve

Результат

$ find . -type f
./build.xml
./ivy.xml
./lib/sources/gson-sources.jar
./lib/sources/guava-sources.jar
./lib/binaries/gson.jar
./lib/binaries/jsr305.jar
./lib/binaries/guava.jar

Доказательство того, что исходный артефакт содержит java файлы:

$ unzip -t ./lib/sources/gson-sources.jar
Archive:  ./lib/sources/gson-sources.jar
    testing: META-INF/                OK
    testing: META-INF/MANIFEST.MF     OK
    testing: com/                     OK
    testing: com/google/              OK
    testing: com/google/gson/         OK
    testing: com/google/gson/annotations/   OK
    testing: com/google/gson/internal/   OK
    testing: com/google/gson/internal/bind/   OK
    testing: com/google/gson/reflect/   OK
    testing: com/google/gson/stream/   OK
    testing: com/google/gson/annotations/Expose.java   OK
    testing: com/google/gson/annotations/package-info.java   OK
    testing: com/google/gson/annotations/SerializedName.java   OK
    testing: com/google/gson/annotations/Since.java   OK
    testing: com/google/gson/annotations/Until.java   OK
    testing: com/google/gson/AnonymousAndLocalClassExclusionStrategy.java   OK
    testing: com/google/gson/Cache.java   OK
    testing: com/google/gson/CamelCaseSeparatorNamingPolicy.java   OK
    testing: com/google/gson/CompositionFieldNamingPolicy.java   OK
    testing: com/google/gson/DefaultTypeAdapters.java   OK
    testing: com/google/gson/DisjunctionExclusionStrategy.java   OK
    testing: com/google/gson/ExclusionStrategy.java   OK
    testing: com/google/gson/ExposeAnnotationDeserializationExclusionStrategy.java   OK
    testing: com/google/gson/ExposeAnnotationSerializationExclusionStrategy.java   OK
    testing: com/google/gson/FieldAttributes.java   OK
    testing: com/google/gson/FieldNamingPolicy.java   OK
    testing: com/google/gson/FieldNamingStrategy.java   OK
    testing: com/google/gson/FieldNamingStrategy2.java   OK
    testing: com/google/gson/FieldNamingStrategy2Adapter.java   OK
    testing: com/google/gson/Gson.java   OK
    testing: com/google/gson/GsonBuilder.java   OK
    testing: com/google/gson/GsonToMiniGsonTypeAdapterFactory.java   OK
    testing: com/google/gson/InnerClassExclusionStrategy.java   OK
    testing: com/google/gson/InstanceCreator.java   OK
    testing: com/google/gson/internal/$Gson$Preconditions.java   OK
    testing: com/google/gson/internal/$Gson$Types.java   OK
    testing: com/google/gson/internal/bind/ArrayTypeAdapter.java   OK
    testing: com/google/gson/internal/bind/BigDecimalTypeAdapter.java   OK
    testing: com/google/gson/internal/bind/BigIntegerTypeAdapter.java   OK
    testing: com/google/gson/internal/bind/CollectionTypeAdapterFactory.java   OK
    testing: com/google/gson/internal/bind/DateTypeAdapter.java   OK
    testing: com/google/gson/internal/bind/ExcludedTypeAdapterFactory.java   OK
    testing: com/google/gson/internal/bind/JsonElementReader.java   OK
    testing: com/google/gson/internal/bind/JsonElementWriter.java   OK
    testing: com/google/gson/internal/bind/MapTypeAdapterFactory.java   OK
    testing: com/google/gson/internal/bind/MiniGson.java   OK
    testing: com/google/gson/internal/bind/ObjectTypeAdapter.java   OK
    testing: com/google/gson/internal/bind/Reflection.java   OK
    testing: com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java   OK
    testing: com/google/gson/internal/bind/SqlDateTypeAdapter.java   OK
    testing: com/google/gson/internal/bind/StringToValueMapTypeAdapterFactory.java   OK
    testing: com/google/gson/internal/bind/TimeTypeAdapter.java   OK
    testing: com/google/gson/internal/bind/TypeAdapter.java   OK
    testing: com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java   OK
    testing: com/google/gson/internal/bind/TypeAdapters.java   OK
    testing: com/google/gson/internal/ConstructorConstructor.java   OK
    testing: com/google/gson/internal/LazilyParsedNumber.java   OK
    testing: com/google/gson/internal/ObjectConstructor.java   OK
    testing: com/google/gson/internal/package-info.java   OK
    testing: com/google/gson/internal/Pair.java   OK
    testing: com/google/gson/internal/ParameterizedTypeHandlerMap.java   OK
    testing: com/google/gson/internal/Primitives.java   OK
    testing: com/google/gson/internal/Streams.java   OK
    testing: com/google/gson/internal/UnsafeAllocator.java   OK
    testing: com/google/gson/JavaFieldNamingPolicy.java   OK
    testing: com/google/gson/JsonArray.java   OK
    testing: com/google/gson/JsonDeserializationContext.java   OK
    testing: com/google/gson/JsonDeserializer.java   OK
    testing: com/google/gson/JsonDeserializerExceptionWrapper.java   OK
    testing: com/google/gson/JsonElement.java   OK
    testing: com/google/gson/JsonElementVisitor.java   OK
    testing: com/google/gson/JsonIOException.java   OK
    testing: com/google/gson/JsonNull.java   OK
    testing: com/google/gson/JsonObject.java   OK
    testing: com/google/gson/JsonParseException.java   OK
    testing: com/google/gson/JsonParser.java   OK
    testing: com/google/gson/JsonPrimitive.java   OK
    testing: com/google/gson/JsonSerializationContext.java   OK
    testing: com/google/gson/JsonSerializer.java   OK
    testing: com/google/gson/JsonStreamParser.java   OK
    testing: com/google/gson/JsonSyntaxException.java   OK
    testing: com/google/gson/LongSerializationPolicy.java   OK
    testing: com/google/gson/LowerCamelCaseSeparatorNamingPolicy.java   OK
    testing: com/google/gson/LowerCaseNamingPolicy.java   OK
    testing: com/google/gson/LruCache.java   OK
    testing: com/google/gson/ModifierBasedExclusionStrategy.java   OK
    testing: com/google/gson/ModifyFirstLetterNamingPolicy.java   OK
    testing: com/google/gson/package-info.java   OK
    testing: com/google/gson/RecursiveFieldNamingPolicy.java   OK
    testing: com/google/gson/reflect/package-info.java   OK
    testing: com/google/gson/reflect/TypeToken.java   OK
    testing: com/google/gson/SerializedNameAnnotationInterceptingNamingPolicy.java   OK
    testing: com/google/gson/stream/JsonReader.java   OK
    testing: com/google/gson/stream/JsonScope.java   OK
    testing: com/google/gson/stream/JsonToken.java   OK
    testing: com/google/gson/stream/JsonWriter.java   OK
    testing: com/google/gson/stream/MalformedJsonException.java   OK
    testing: com/google/gson/stream/StringPool.java   OK
    testing: com/google/gson/SyntheticFieldExclusionStrategy.java   OK
    testing: com/google/gson/UpperCamelCaseSeparatorNamingPolicy.java   OK
    testing: com/google/gson/UpperCaseNamingPolicy.java   OK
    testing: com/google/gson/VersionConstants.java   OK
    testing: com/google/gson/VersionExclusionStrategy.java   OK
No errors detected in compressed data of ./lib/sources/gson-sources.jar.

Ответ 2

~/.ivy2 - это только ivy cache.

Вы должны установить шаблон ivy retrieve. Это определит, где загружаются зависимости.

<ivy:retrieve pattern="${project_home}/WebContent/WEB-INF/lib/[artifact].[ext]" conf="jars"/>

И, возможно, второе восстановление для источников:

<ivy:retrieve pattern="${project_home}/sources/[artifact].[ext]" conf="sources"/>

Это также сработает и поместит зависимости источников и банок в разные каталоги:

<ivy:retrieve pattern="${project_home}/[conf]/[artifact].[ext]" conf="sources, jars"/>

Это зависит от того, как источники/баннеры назначаются в вашем репозитории.

И на стороне примечания: перед тем, как использовать задачу, должно возникнуть taskdef.

И вы должны определить резольвер как сопутствующий:

<ibiblio name="maven2" m2compatible="true"/>

Ответ 3

У меня были подобные проблемы, но с немного более сложной ситуацией, для которой предоставленное решение не сработало. У меня был основной файл ivy.xml, который не определял конфигурацию, поэтому унаследовал конфигурацию по умолчанию, которая создается без вашего уведомления (см. doc), Применение свежеприготовленного "основного" conf на всех зависимостях просто сломало сборку. У меня не было выбора, кроме как определить новый модуль в другом файле, скажем ivy_extra.xml, и загрузить его в новую цель, просто как это!

Файл примера:

<!-- ivy_extra.xml -->
<ivy-module version="2.0">
    <info organisation="com.myorg" module="mymodule"/>
    <configurations>
        <conf name="download" visibility="private" />
    </configurations>
    <dependencies>
        <dependency org="com.google.guava" name="guava" rev="10.0.1" conf="download->default"/>
    </dependencies>
</ivy-module>

Загружено в ваш build.xml следующим образом:

<target name="download-guava" description="Retrieve guava">
    <echo>Retrieving guava</echo>
    <ivy:resolve file="ivy_agent.xml"/>
    <ivy:retrieve conf="download" type="jar" pattern="guava/[artifact]-[revision].jar"/>
</target>