问题
Building with Ant Ivy, I'm trying to separate my jars into one configuration for 3rd party jars and another configuration for the jars I build and publish. ProjectA uses 3rd party jars and builds a jar that ProjectB depends on, but when I use Ant Ivy confs I can't get ProjectB to retrieve the ProjectA jar.
When I execute the ant script for ProjectB, it builds ProjectA fine. The ProjectA build publishes a jar to the local repository. ProjectB retrieves the necessary jars from the public repository with no problem, but when it tries to retrieve the ProjectA jar, it says UNRESOLVED DEPENDENCY: testproject#ProjectA;2.0.0: configuration not found in testproject#ProjectA;2.0.0: 'localjars'. It was required from testproject#ProjectB;2.0.0 localjars
If I remove all references to the 2nd configuration, localjars, and just use default for everything, it works fine. I really need to sort my jars into the different confs though.
I've successfully used a revision value passed from the ant script in place of "2.0.0" below and referenced with ${revision}, but the conf error is the same.
ProjectA ivy.xml (with a subset of dependencies for brevity):
<ivy-module version="2.0">
<info organisation="testproject" module="ProjectA" revision="2.0.0" status="release" publication="20160524124555"/>
<configurations>
<conf name="default" transitive="false" visibility="public"/>
<conf name="localjars" extends="default" visibility="public"/>
</configurations>
<publications>
<artifact name="projectA-jar-2.0.0" type="jar" conf="localjars" ext="jar"/>
</publications>
<dependencies>
<dependency org="commons-beanutils" name="commons-beanutils" rev="1.7.0" conf="default->master"/>
<dependency org="commons-collections" name="commons-collections" rev="3.1" conf="default->master"/>
</dependencies>
</ivy-module>
ProjectA build.xml publish target:
<target name="publish" depends="package"
description="--> compile test and publish this project in the local ivy repository">
<ivy:publish artifactspattern="${DEPLOY_DIR_LIB}/[artifact].[ext]"
resolver="local" pubrevision="2.0.0" status="release"
srcivypattern="${ivy.dep.file}" forcedeliver="true" overwrite="true" conf="localjars,default"/>
<echo message="project ${ant.project.name} released with version 2.0.0" />
</target>
ProjectB ivy.xml:
<ivy-module version="2.0">
<info organisation="testproject" module="ProjectB" revision="2.0.0" status="release" publication="20160524103113"/>
<configurations>
<conf name="default"/>
<conf name="localjars" extends="default"/>
</configurations>
<publications>
<artifact name="projectB-2.0.0" conf="localjars" type="jar" ext="jar"/>
</publications>
<dependencies>
<dependency org="testproject" name="ProjectA" rev="${revision}" transitive="true" conf="localjars->localjars; default->default"/>
</dependencies>
ProjectB Ant resolve target:
<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="${DEPLOY_DIR_LIB}/[artifact]-2.0.0.[ext]" revision="2.0.0" conf="localjars" />
</target>
Any idea what's wrong? Thanks!
Patrick
回答1:
Not entirely certain why your configuration is not working. One thing I'd advise is not to disable transitive dependencies. You'll note I have a different approach in creating the "default" configuration in the working example below.
Example
Each project has its own local build and ivy file. Collaboration is via jars published to the "local" repository.
├── build.xml
├── ProjectA
│ ├── build.xml
│ ├── ivy.xml
│ └── src
│ └── Hello.txt
└── ProjectB
├── build.xml
├── ivy.xml
└── src
└── Hello.txt
build.xml
Master build file that builds all modules in the correct order, using the buildlist task.
Additionally I normally include an extra target for installing ivy.
<project name="main" default="publish" xmlns:ivy="antlib:org.apache.ivy.ant">
<available classname="org.apache.ivy.Main" property="ivy.installed"/>
<target name="install-ivy" unless="ivy.installed">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.4.0/ivy-2.4.0.jar"/>
<fail message="Ivy has been installed. Run the build again"/>
</target>
<target name="publish" depends="install-ivy">
<ivy:buildlist reference="build-path">
<fileset dir="." includes="*/build.xml"/>
</ivy:buildlist>
<subant target="publish" buildpathref="build-path"/>
</target>
<target name="clean">
<subant target="clean">
<fileset dir="." includes="*/build.xml"/>
</subant>
</target>
<target name="clean-all" depends="clean">
<ivy:cleancache/>
</target>
</project>
ProjectA/ivy.xml
The "master" configuration contains only artifacts. This naming convention mirrors the scopes used by Maven.
Note also how the "default" configuration extends both "master" and "runtime". This enables clients to pull down everything they will need.
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="ProjectA"/>
<configurations>
<conf name="default" description="Master artifact and runtime dependencies" extends="master,runtime"/>
<conf name="master" description="Artifact published by this module"/>
<conf name="compile" description="Required to compile application"/>
<conf name="runtime" description="Additional run-time dependencies" extends="compile"/>
<conf name="test" description="Required for test only" extends="runtime"/>
</configurations>
<publications>
<artifact name="ProjectA" type="jar" ext="jar" conf="master"/>
</publications>
<dependencies>
<!-- compile dependencies -->
<dependency org="org.slf4j" name="slf4j-api" rev="1.7.5" conf="compile->default"/>
<!-- runtime dependencies -->
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.7.5" conf="runtime->default"/>
<!-- test dependencies -->
<dependency org="junit" name="junit" rev="4.11" conf="test->default"/>
</dependencies>
</ivy-module>
ProjectB/ivy.xml
Note how ProjectA is the only dependency and it maps the remote "default" configuration to the local "compile" configuration.
Another subtle issue is the use of the "latest.integration" dynamic revision. This means we don't need to hardcode the revision of ProjectA.
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="ProjectB"/>
<configurations>
<conf name="default" description="Master artifact and runtime dependencies" extends="master,runtime"/>
<conf name="master" description="Artifact published by this module"/>
<conf name="compile" description="Required to compile application"/>
<conf name="runtime" description="Additional run-time dependencies" extends="compile"/>
<conf name="test" description="Required for test only" extends="runtime"/>
</configurations>
<publications>
<artifact name="ProjectB" type="jar" ext="jar" conf="master"/>
</publications>
<dependencies>
<dependency org="com.myspotontheweb" name="ProjectA" rev="latest.integration" conf="compile->default"/>
</dependencies>
</ivy-module>
ProjectA/build.xml
The revision to be published is set as a property, which can be overridden if necessary.
Note also how ivy configurations can be used to control classpaths within the build, using the cachepath task
<project name="ProjectA" default="build" xmlns:ivy="antlib:org.apache.ivy.ant">
<property name="build.dir" location="build"/>
<property name="pub.version" value="1.0"/>
<property name="pub.resolver" value="local"/>
<target name="resolve">
<ivy:resolve/>
<ivy:cachepath pathid="compile.path" conf="compile"/>
<ivy:cachepath pathid="test.path" conf="test"/>
</target>
<target name="build" depends="resolve">
<mkdir dir="${build.dir}"/>
<jar destfile="${build.dir}/${ant.project.name}.jar" basedir="src"/>
</target>
<target name="publish" depends="build">
<ivy:publish pubrevision="${pub.version}" resolver="${pub.resolver}" overwrite="true">
<artifacts pattern="${build.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>
<target name="clean">
<delete dir="${build.dir}"/>
</target>
</project>
ProjectB/build.xml
Identical to the other project just having a different name attribute.
<project name="ProjectB" default="build" ....
来源:https://stackoverflow.com/questions/37420103/ant-ivy-conf-specific-retrieve-is-failing-on-my-published-jar