I think I donot understand well the conf feature of ivy even if I have read the tutorial. Think about I have two dependency;
guava.jar
foeu.jar
I need foeu.jar in compile time only but I need guava.jar not only in compile time but also in runtime. To implement these needs, I have wrote, in ivy.xml;
<configurations defaultconfmapping="runtime->compile">
<conf name="default"
visibility="public" />
<conf name="compile"
visibility="private"/>
<conf name="runtime"
extends="compile"
visibility="public"/>
</configurations>
and, dependency as;
<dependencies>
<dependency org="Google Guava" name="guava-17.0" rev="17.0"
conf="runtime->default"/>
<dependency org="Foeu" name="foeu" rev="5.5.1"
conf="compile->default"/>
</dependencies>
Really, something wrong with conf understanding of mine. What is the problem and what should I do?
UPDATE:
In build.xml, I am using it like;
ivy-initialization;
<target name="init-ivy" description="Initialize ivy requirements">
<property name="ivy.dep.file" value="${script.directory}/ivy/ivy.xml" />
<ivy:configure file="${script.directory}/ivy/ivyconf.xml"/>
<ivy:resolve/>
<ivy:cachepath pathid="ivy.compile.path" conf="compile" />
<ivy:cachepath pathid="ivy.runtime.path" conf="runtime" />
</target>
compile;
<target name="compile" depends="init-ivy" description="Compiling Java source codes with external libraries">
<javac compiler="javac1.7"
destdir="${class.directory}"
source="1.7"
target="1.7"
failonerror="true"
includeantruntime="false">
<src path="${source.directory}" />
<classpath refid="ivy.compile.path" />
</javac>
</target>
jar
<target name="create-jar" depends="compile" description="Creating jar files">
<jar destfile="${build.directory}/jar/${ant.project.name}.jar"
basedir="${class.directory}">
<manifest>
<attribute name="Main-Class" value="dataScience.management.Management"/>
</manifest>
</jar>
</target>
run
<target name="runtime" depends="create-jar" description="Running Java based application">
<java jar="${jar.directory}/${ant.project.name}.jar"
fork="yes"
maxmemory="400m">
<jvmarg value="-ea"/>
<classpath refid="ivy.runtime.path" />
</java>
</target>
Configurations are a tricky concept to understand. My recommendation is to create one for each functional group of dependencies in your build.
The bit you're looking for is the "extends" attribute. It enables membership inheritance. For example:
<configurations>
<conf name="compile" description="Libraries needed for compilation" />
<conf name="runtime" extends="compile" description="Libraries needed at runtime"/>
</configurations>
In this way all compile dependencies are automatically part of the runtime configuration.
For more detailed example take a look at the following answer:
Ivy, what is the master configuration and why is it not pulling jvyaml?
Update
This is not an ivy issue. Executable jars require main class and classpath to be present in the manifest file.
Build your jar file as follows:
<target name="build" depends="compile">
<ivy:retrieve pattern="${dist.dir}/lib/[artifact].[ext]" conf="runtime"/>
<manifestclasspath property="jar.classpath" jarfile="${dist.jar}">
<classpath>
<fileset dir="${dist.dir}/lib" includes="*.jar"/>
</classpath>
</manifestclasspath>
<jar destfile="${dist.jar}" basedir="${build.dir}/classes">
<manifest>
<attribute name="Main-Class" value="${dist.main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
</manifest>
</jar>
</target>
The ivy retrieve task populates a local dir with the runtime dependencies. The manifestclasspath task creates a list of relative links to these files and finally the "Class-Path" entry is added to the manifest file. You will then be able to run the jar as follows:
<java jar="${dist.jar}" fork="yes" maxmemory="400m">
<jvmarg value="-ea"/>
</java>
In conclusion there is basically two ways to run a jar. Specify the classpath and mainclass or create jar with the main class and classpath in the manifest.
Hope this solves your issue.
Related
<target name="build">
<delete dir="classes" failonerror="false"/>
<mkdir dir="classes"/>
<javac destdir="classes" includeAntRuntime="false" srcdir="src">
<withKotlin/>
</javac>
<jar destfile="hello.jar">
<fileset dir="classes"/>
</jar>
</target>
Kotlin Website
I am working on integrating Kotlin with my existing Java project (ivy and ant). Currently we use ivy.xml for dependency management and ant for build scripts.
If I used IVY, does it make specifying classpath="${kotlin.lib}/kotlin-ant.jar" redundant ?
I get an error org/jetbrains/kotlin/ant/antlib.xml not found in classpath. How to resolve it ?
How to add kotlin-ant.jar & and all its dependencies using using Ivy ?
If Ivy is used, then no need for specifying classpath="${kotlin.lib}/kotlin-ant.jar"
Regarding 2 & 3.
Create configurations for the Kotlin Dependencies in the ivy.xml
<configurations>
<conf name="kotlin" description="Kotlin Tasks"/>
</configurations>
<dependencies>
<dependency org="xxxxx" name="kotlin-ant" rev="xxxxx" conf="kotlin->default"/>
</dependencies>
In Build.xml, update the configuration.
<target name="resolve">
<ivy:resolve />
<ivy:cachepath pathid="kotlin.classpath" conf="kotlin"/>
</target>
<target name="build" depends="resolve">
<typedef resource="org/jetbrains/kotlin/ant/antlib.xml" classpathref="kotlin.classpath"/>
<kotlinc .....
</kotlinc>
</target>
I have a Java project that uses SWT and compiles/runs perfectly.
When I try to compile via Ant, however, javac cannot find the SWT library despite the build.xml specifying the correct classpath.
The SWT library is located in C:\my_work\Eclipse\3.6-64\plugins\. As seen below (under the javac tags, this classpath is specified as such.
build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project default="run" name="My Project">
<target name="run" depends="compile">
<java classname="com.company.program.project">
<classpath path="staging\" location="C:\my_work\Eclipse\3.6-64\plugins\"/>
</java>
</target>
<target name="compile">
<javac includeantruntime="false" srcdir="./src" destdir="staging">
<classpath path="C:\my_work\Eclipse\3.6-64\plugins\"></classpath>
</javac>
</target>
<jar destfile="./build/jars/swtgui.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="org.swtgui.MainGui" />
<attribute name="Class-Path" value="." />
</manifest>
<fileset dir="./bin/com/company/program/project" includes="**/*.class" />
<fileset dir="C:\my_work\Eclipse\3.6-64\plugins\" includes="org.eclipse.swt.win32.win32.x86_64_3.6.0.v3650b.jar" />
</jar>
<record name="./MyProject.log" loglevel="verbose" action="start"/>
The above gives me errors on import statements such as the following:
error: package org.eclipse.swt does not exist
import org.eclipse.swt.SWT;
^
Why does javac not find the SWT library when the classpath is correctly specified?
Also how can I find out where javac is looking? The logs -- even in verbose mode -- tell me nothing about where javac is trying to find these import statements.
SWT provides a separate Jar for standalone Java applications.
You can download the latest one from here - look at the 'SWT Binary and Source' section near the bottom of the page.
it seems <classpath path="C:\my_work\Eclipse\3.6-64\plugins\"></classpath> is not adding dependencies to compile classpath
this way works for me:
<target name="compile">
<javac includeantruntime="false" srcdir="./src" destdir="staging">
<classpath>
<fileset dir="C:\my_work\Eclipse\3.6-64\plugins">
<!-- <include name="**/*.jar" /> -->
<include name="org.eclipse.swt.*.jar" />
</fileset>
</classpath>
</javac>
</target>
I have been able to successfully compile and run this project using ant. But when i try to run my test files, it gives me a strange Reference ./lib/junit-4.11.jar not found. I probably am doing something wrong in the refid that i have to mention in the junit task. Please point out the mistake.
<target name="clean">
<delete dir="build"/>
</target>
<target name="compile">
<mkdir dir="build/classes"/>
<javac srcdir="./src/com/twu/biblioteca/" destdir="build/classes"/>
</target>
<target name="jar">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/Application.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="com.twu.biblioteca.Application"/>
</manifest>
</jar>
</target>
<target name="run">
<java jar="build/jar/Application.jar" fork="true"/>
</target>
<target name="junit" depends="compile">
<junit printsummary="yes" haltonfailure="no">
<!-- Project classpath, must include junit.jar -->
<classpath refid="./lib/junit-4.11.jar" />
<!-- test class -->
<classpath location="./test/BooksController" />
<test name="com.twu.biblioteca.BooksControllerTest"
haltonfailure="no" todir="./report">
<formatter type="plain" />
<formatter type="xml" />
</test>
</junit>
</target>
The problem is with your junit classpath elements. The refid attribute allows you to refer to a predefined reference and ant is notifying you that there is no such reference. Additionally, you should have only one classpath element under the junit task (it may work with more than one, but the documentation supports only one).
Remove those classpath elements and replace them with
<classpath>
<pathelement location="lib/junit-4.11.jar"/>
<pathelement location="test/BooksController"/>
</classpath>
and it should work. Here we build up the classpath by adding the junit jar to the path and then the directory containing your tests. You will probably have to add your main classes to this as well, with another pathelement giving their location.
See the ant documentation for more on these path-like structures.
My problem is , i have to build the manifest entry classpath from the path like
C:\Users\rosansamuel.ivy2\cache\log4j\log4j\jars\log4j-1.2.14.jar
Can you please any one suggest some ideas?
Below code is , i am trying with propertyregex, but actually i can't able to get the jar names.
<for list="${ofsml.manifest.classpath.list}" delimiter=";" param="individual.path">
<sequential>
<property name="single.artifact.path" value="#{individual.path}"/>
<echo message="single aritfact path name : ${single.artifact.path}"/>
<path id="my.base.path">
<pathelement path="${single.artifact.path}"/>
</path>
<property name="artifact.id.file" refid="my.base.path"/>
<echo message=" artifact.id.file: ${artifact.id.file}"/>
<propertyregex property="artifact.id" input="${artifact.id.file}" regexp=".*.jar" select="\1"/>
<echo message="jar name : ${artifact.id}"/>
<echo message="individual.path = #{individual.path}"/>
</sequential>
</for>
There is a manifestclasspath task in ANT that can generate a list of relative filepaths from a fileset.
I also see that you're using ivy, so why not use its retrieve task to place your dependency jars in a local directory relative to the jar you are building. Otherwise your jar will be hard-coded to expect its dependencies to be an absolute path that works on your machine, but not very portable.
Here's an small snippet:
<target name="build" depends="compile">
<ivy:retrieve pattern="${dist.dir}/lib/[artifact].[ext]"/>
<manifestclasspath property="jar.classpath" jarfile="${dist.jar}">
<classpath>
<fileset dir="${dist.dir}/lib" includes="*.jar"/>
</classpath>
</manifestclasspath>
<jar destfile="${dist.jar}" basedir="${build.dir}/classes">
<manifest>
<attribute name="Main-Class" value="${dist.main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
</manifest>
</jar>
</target>
For a more complete example, see:
How to avoid copying dependencies with Ivy
I have the following setup for my application:
The project TestAll currently contain a java file that run all the TestAll javafiles in all my other projects and this works as expected. The problem im facing is that I want this TestAll.java to be run from a ant script and have it record the result in a report file. This javafile is dependent on all the other projects in my application.
This is what I have so far:
<?xml version="1.0"?>
<project name="Ant-Test" default="main" basedir=".">
<!-- Sets variables which can later be used. -->
<property name="src.dir" location="" />
<property name="build.dir" location="../bin" />
<property name="dist.dir" location="../dist" />
<property name="lib.dir" location="../lib" />
<property name="test.dir" location="../src" />
<property name="test.report.dir" location="../testreport" />
<target name="clean">
<delete dir="${build.dir}" />
<delete dir="${dist.dir}" />
</target>
<!-- Define the classpath which includes the junit.jar and the classes after compiling-->
<path id="junit.class.path">
<pathelement location="${lib.dir}/junit.jar" />
<pathelement location="${build.dir}" />
</path>
<target name="makedir">
<mkdir dir="${build.dir}" />
<mkdir dir="${dist.dir}" />
<mkdir dir="${test.report.dir}" />
</target>
<!-- Compiles the java code (including the usage of library for JUnit -->
<target name="compile" depends="clean, makedir">
<javac srcdir="${src.dir}" destdir="${build.dir}">
<classpath refid="junit.class.path" />
</javac>
</target>
<target name="junit" depends="compile">
<junit printsummary="on" fork="true" haltonfailure="yes">
<classpath refid="junit.class.path" />
<formatter type="xml" />
<batchtest todir="${test.report.dir}">
<fileset dir="${src.dir}">
<include name="**/*Test*.java" />
</fileset>
</batchtest>
</junit>
</target>
<!--Creates the deployable jar file -->
<target name="jar" depends="compile">
<jar destfile="${dist.dir}\se.testall.jar" basedir="${build.dir}">
<manifest>
<attribute name="Main-Class" value="test.Main" />
</manifest>
</jar>
</target>
<target name="main" depends="compile, jar, junit">
<description>Main target</description>
</target>
</project>
And the errors im getting is:
[javac] Compiling 1 source file to C:\Repositories\MyProject\TestAllProjects\bin
[javac] C:\Repositories\MyProject\TestAllProjects\src\se\testall\src\TestAllClass.java:6: error: package se.tlv.AProject.testall does not exist
[javac] import se.tlv.AnotherProject.testall.*;
[javac] ^
[javac] C:\Repositories\TestAllProjects\src\se\src\TestAllClass.java:7: error: package se.AnotherProject.testall does not exist
..and so on for all the internal imports in my TestAll project
This is most likley a classpath error where ANT in unable to find the files it needs, but I have no idea how to resolve it and have been trying for almost a full day. Any help is appreciated
The classpath provided to the javac task is: the junit jar, the build directory and the current directory.
Unless the current directory (where build.xml is located) is se, the javac task won't be able to find any java files to compile them.
Given that, the classpath for the javac task will need to include a path to each se directory in each project.
Edit:
Note: Unless you're planning on packaging the tests with the rest of the code, you should have two javac tasks that build to a build directory and a test build directory, then provide a path to each of those to junit so it can run the tests, but provide only the build directory path to the jar task.