我是Java和Travis CI的新手,并且在配置我的项目时遇到了错误。我用ant来构建,用ivy来管理依赖关系。如果在本地找不到ivy jar文件,我的ant构建会直接下载它。这在我的机器上工作得很好,但是当我推到Travis时就失败了。
令人费解的事情:看起来它在bootstrap-ivy
任务期间下载了jar并将其放在/home/travis/.ant/lib/
中,但随后在resolve
任务中未能找到它。知道是怎么回事吗?完整的错误、我的ant构建文件和我的.travis.yml
都包含在下面。
下面是完整的Travis错误:
Using worker: worker-linux-3-1.bb.travis-ci.org:travis-linux-13
git.1
$ git clone --depth=50 --branch=master git://github.com/ecmendenhall/Java-TTT.git ecmendenhall/Java-TTT
Cloning into 'ecmendenhall/Java-TTT'...
remote: Counting objects: 613, done.
remote: Compressing objects: 100% (345/345), done.
remote: Total 613 (delta 325), reused 421 (delta 133)
Receiving objects: 100% (613/613), 102.29 KiB, done.
Resolving deltas: 100% (325/325), done.
$ cd ecmendenhall/Java-TTT
git.2
$ git checkout -qf 3a5201cc7e850d7cbad69712fce28a36c86ea6d1
$ jdk_switcher use oraclejdk7
Switching to Oracle JDK7 (java-7-oracle), JAVA_HOME will be set to /usr/lib/jvm/java-7-oracle
update-alternatives: error: no alternatives for apt.
update-alternatives: error: no alternatives for mozilla-javaplugin.so.
update-alternatives: error: no alternatives for apt.
$ java -version
java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
$ javac -version
javac 1.7.0_17
$ ant resolve
Buildfile: /home/travis/build/ecmendenhall/Java-TTT/build.xml
[mkdir] Created dir: /home/travis/build/ecmendenhall/Java-TTT/lib
check-ivy:
[echo] Checking for Ivy .jar in local directories.
bootstrap-ivy:
[echo] Bootstrapping Ivy installation.
[mkdir] Created dir: /home/travis/.ant/lib
[get] Getting: http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.3.0/ivy-2.3.0.jar
[get] To: /home/travis/.ant/lib/ivy.jar
resolve:
[echo] Resolving project dependencies.
BUILD FAILED
/home/travis/build/ecmendenhall/Java-TTT/build.xml:52: Problem: failed to create task or type antlib:org.apache.ivy.ant:retrieve
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
No types or tasks have been defined in this namespace yet
This appears to be an antlib declaration.
Action: Check that the implementing library exists in one of:
-/usr/share/ant/lib
-/home/travis/.ant/lib
-a directory added on the command line with the -lib argument
Total time: 3 seconds
The command "ant resolve" failed and exited with 1 during install.
Your build has been stopped.
这是我的ant构建文件:
<?xml version="1.0" encoding="UTF-8"?>
<project name="TicTacToe" basedir="." default="jar" xmlns:ivy="antlib:org.apache.ivy.ant">
<description>Builds the TicTacToe command line application and its associated tests.</description>
<!-- Source and build directory defaults -->
<property name="src.dir" value="src"/>
<property name="resources.dir" value="resources"/>
<property name="build.dir" value="build"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir" value="${build.dir}/jar"/>
<property name="main-class" value="com.cmendenhall.Main"/>
<mkdir dir="lib" />
<property name="lib.dir" value="lib"/>
<property name="test.dir" value="test" />
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
</path>
<path id="classpath.test">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
<pathelement location="${classes.dir}" />
<pathelement location="${resources.dir}" />
</path>
<path id="application" location="${jar.dir}/${ant.project.name}.jar"/>
<!-- Automatically download Ivy -->
<property name="ivy.jar.dir" value="${user.home}/.ant/lib" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<target name="check-ivy" unless="INTERN-ivy.jar.exists" description="Check if the Ivy .jar is already installed.">
<echo message="Checking for Ivy .jar in local directories." />
<available property="INTERN-ivy.jar.exists" file="${ivy.jar.file}"/>
</target>
<target name="bootstrap-ivy"
description="Installs the Ivy jar before downloading dependencies."
unless="INTERN-ivy.jar.exists"
depends="check-ivy">
<echo message="Bootstrapping Ivy installation." />
<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.3.0/ivy-2.3.0.jar"/>
<mkdir dir="/usr/share/ant/lib" />
<get dest="/usr/share/ant/lib/ivy.jar"
src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.3.0/ivy-2.3.0.jar" />
</target>
<target name="resolve" description="Retrieve dependencies with Ivy." depends="check-ivy, bootstrap-ivy">
<echo message="Resolving project dependencies." />
<ivy:retrieve />
</target>
<target name="clean" description="Cleans up automatically generated files and directories.">
<echo message="Cleaning up build directory." />
<delete dir="${build.dir}"/>
</target>
<target name="compile" depends="resolve" description="Compiles project.">
<echo message="Compiling project." />
<mkdir dir="${classes.dir}"/>
<javac includeantruntime="false" debug="true" srcdir="${src.dir}" destdir="${classes.dir}" >
<classpath refid="classpath" />
</javac>
</target>
<target name="compile-tests" depends="resolve" description="Compiles JUnit tests." >
<echo message="Compiling JUnit tests." />
<javac includeantruntime="false" debug="true" srcdir="${test.dir}" destdir="${classes.dir}" >
<classpath refid="classpath" />
</javac>
</target>
<target name="jar" depends="compile" description="Packages project as .jar file.">
<echo message="Packaging project as .jar file." />
<mkdir dir="${jar.dir}"/>
<jar destfile="${jar.dir}/${ant.project.name}.jar">
<manifest>
<attribute name="Main-class" value="${main-class}"/>
</manifest>
<fileset dir="${classes.dir}">
<include name="**/*.class" />
</fileset>
<fileset dir="${resources.dir}">
<include name="**/*.properties" />
</fileset>
</jar>
</target>
<property name="junitpath" refid="classpath.test" />
<target name="test" depends="compile, compile-tests" description="Runs JUnit tests.">
<echo message="Running JUnit tests." />
<junit printsummary="on" haltonfailure="yes" failureproperty="test.failure">
<jvmarg value="-Dfile.encoding=UTF-8:-XX:-UseSplitVerifier" />
<formatter type="brief" usefile="false" />
<classpath>
<path refid="classpath.test"/>
</classpath>
<batchtest fork="on">
<fileset id="matchedtests" dir="${classes.dir}">
<include name="**/*Test.class"/>
<exclude name="**/TicTacToeTest.class" />
</fileset>
</batchtest>
</junit>
</target>
<target name="clean-build" depends="clean, jar" description="Cleans output directory and builds .jar.">
<echo message="Cleaning build directory and rebuilding .jar." />
</target>
<target name="build-all" depends="clean, jar, test" description="Cleans output directory, retrieves dependencies, builds and packages project and tests.">
<echo message="Finishing build." />
</target>
</project>
我的.travis.yml
:
language: java
install: ant resolve
jdk:
- oraclejdk7
- openjdk7
- openjdk6
:下面是我的解决方案,感谢下面的建议。
我用官方文档中推荐的download-ivy
和init-ivy
任务替换了我的自定义bootstrap-ivy
任务:
<property name="ivy.install.version" value="2.1.0-rc2" />
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME" />
</condition>
<property name="ivy.home" value="${user.home}/.ant" />
<property name="ivy.jar.dir" value="${ivy.home}/lib" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<target name="download-ivy" unless="offline">
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>
<target name="init-ivy" depends="download-ivy">
<!-- try to load ivy here from ivy home, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
我在.travis.yml
中添加了before_install
步骤,在尝试解决依赖关系之前运行ant init-ivy
(这里是Travis构建周期的文档):
language: java
before_install: ant init-ivy
install: ant resolve
jdk:
- oraclejdk7
- openjdk7
- openjdk6
现在一切正常了!
这与Ant从.ant/lib
加载jar的方式有关。这个文件夹是在Ant启动时查找的,如果在那里找到任何jar,则将其添加到其核心类加载器中。在这里,.ant/lib
是在执行构建时被填充的,所以为时已晚。
有两种解决方法:
- 发射蚂蚁两次;一个用于填充
.ant/lib
,另一个用于执行实际构建 而不是把Ivy的jar放在
.ant/lib
,只是把它放在一个任意的地方,并通过taskdef
Ant任务加载它。参见http://ant.apache.org/ivy/history/latest-milestone/install.html的"自动"部分