Change JDK for running <ANT> task from within build xml - java

I have build.xml which calls swfbuild.xml. I want parent build.xml to use IBM JDK 1.5 and swfbuild.xml to use Sun JDK 1.6
Is there any option in <ant> task to specify different JDK to use?
I tried setting JAVACMD like below but that doesn't work either
How can I use different JDK for swfbuild.xml?
<target name="Compile_SWF">
<exec executable="cmd">
<env key="JAVACMD" value="C:/Program Files/Java/jdk1.6.0_18" />
</exec>
<echo message="Start to Compile SWF content" />
<ant antfile="swfbuild.xml" target="swf-masterbuild" />
<exec executable="cmd">
<env key="JAVACMD" value="C:/IBM/SDP/runtimes/base_v61/java" />
</exec>
</target>

In each xml file, you can specify the executable to use inside the javac task. You must include the fork=yes in addition to the executable= parameter.
<javac fork="yes" executable="C:/Program Files/Java/jdk1.7.0_17/bin/javac">

Related

Ant with Jar Target

I need help, to understand the problem of jar packaging with ant. Here my simple code:
<target name="build" depends="compile,test">
<jar
basedir="${bin}/swing.gui"
destfile="${mod}/swing.gui.jar">
<manifest>
<attribute name="Main-Class" value="swing.main.Main"/>
</manifest>
</jar>
</target>
The little program is modularized and as you can see the module swing.gui should be packaged in a jar file. The problem here, when I try to start the module with:
java --module-path bin/mod --module swing.gui
It does not work. The error message says that there is no MainClass attribute and I should try -m / instead.
When I execute this line on the console:
jar --create --file=bin/mod/swing.gui.jar --main-class=swing.main.Main -C bin/src/swing.gui .
It just works! Is that a bug in ant?
Not a bug, exactly. Ant is just doing what you told it to do.
The Main-Class manifest attribute is not used by module loaders. The --main-class option of jar has nothing to do with manifests; it sets a binary class attribute on the jar’s module-info.class entry.
So, your Ant build file is doing something entirely different from what your jar command is doing.
Until Ant’s <jar> task has direct support for this, the workaround is to call the JDK’s jar command directly. Something like this:
<condition property="exec-suffix" value=".exe" else="">
<os family="windows"/>
</condition>
<property name="jar.tool"
location="${java.home}/bin/jar${exec-suffix}"/>
<exec executable="${jar.tool}" failonerror="true">
<arg value="-u"/>
<arg value="-f"/>
<arg file="${mod}/swing.gui.jar"/>
<arg value="-e"/>
<arg value="swing.main.Main"/>
</exec>

Adding autoprefix-cli to ANT build

I am trying to add autoprefix-cli to my ANT build. Below is my code.
<target name="auto">
<apply executable="autoprefixer-cli.bat" verbose="true" force="true" failonerror="true">
<arg value="-d" /> <!-- Turn on verbose -->
<arg value="prefix" />
<arg value="*.css" />
</apply>
</target>
When i do a ant build, it gives me an error saying resource not specified.
BUILD FAILED
D:\tempTest\AntTestProject\build.xml:25: no resources specified
Note: I can access autoprefix-cli from command line, its installed with -g flag and also it works when i directly use it from commandline.
The apply task basically loops the exec task on a batch of resources (files, directories, URLs, etc). If you only want to run one command, use exec instead.
However, you will likely also need to alter your command. From Ant's exec task documentation:
Note that .bat files cannot in general by executed directly. One
normally needs to execute the command shell executable cmd using the
/c switch.
https://ant.apache.org/manual/Tasks/exec.html
So instead you should have:
<exec executable="cmd" verbose="true" force="true" failonerror="true">
<arg value="/c" />
<arg value="autoprefixer-cli.bat" />
<arg value="-d" />
<arg value="prefix" />
<arg value="*.css" />
</exec>

Eclipse/Ant Making a jar in version 1.9, even though everything seems to be set for 1.8

I have a project I build using ant and eclipse which I'd like to have be compatible with Java 8.
When I try running the jar using Java 8, I get the following error:
$ /usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar hypnos.jar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError:
org/joshuad/musicplayer/MusicPlayerUI has been compiled by a more recent version of
the Java Runtime (class file version 53.0), this version of the Java Runtime only
recognizes class file versions up to 52.0
So it appears that it's compiling using Oracle's Java 9 (which is installed on my system) but I can't find the place in eclipse where this is designated. Everything I see seems to suggest that we're using java 8 (screenshots below).
I feel like I must be missing something, but I can't figure out where. What do I have to do to get this jar to be compatible with Java 8 / class file version 52.0?
Project > Properties > Java Build Path
Project > Properties > Java Compiler
Window > Preferences > Compiler
Right Click Ant Build File > Run As > External Tools Configuration
Ant Build File
<project name="Hypnos Music Player" default="compile" basedir=".">
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="jarFile" location="hypnos.jar"/>
<path id="class.path">
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
<pathelement location="${jarFile}" />
</path>
<target name="init">
<tstamp/>
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init" description="compile the source">
<javac fork="yes" includeantruntime="false" srcdir="${src}" destdir="${build}">
<classpath refid="class.path" />
</javac>
</target>
<target name="jar" depends="compile" description="Create a jar.">
<jar destfile="${jarFile}" basedir="${build}">
<manifest>
<attribute name="Main-Class" value="org.joshuad.musicplayer.MusicPlayerUI" />
<attribute name="Class-Path" value="lib/commons-cli-1.4.jar lib/jaad-0.8.4-nospi.jar
lib/jaudiotagger-2.2.6-SNAPSHOT.jar lib/jflac-1.2.jar
lib/jl1.0.1.jar lib/jogg-0.0.7.jar lib/jorbis-0.0.15.jar
lib/vorbisspi1.0.3.jar" />
</manifest>
</jar>
</target>
</project>
What is your $JAVA_HOME environment variable?
I recently had a similar problem and it turns out that Ant seems to ignore many settings provided by Eclipse and only uses $JAVA_HOME. I discovered this by placing the following in build.xml:
<target name="jdk_version_validation">
<echo message="Java Version: ${java.version}" />
<echo message="Java home: ${java.home}" />
<echo message="JAVA_HOME: ${env.JAVA_HOME}" />
<echo message="JAVACMD: ${env.JAVACMD}" />
</target>
Which got me this:
jdk_version_validation:
[echo] Java Version: 1.7.0_80
[echo] Java home: C:\Program Files\Java\jre7
[echo] JAVA_HOME: C:\Program Files\Java\jdk1.8.0_131\
[echo] JAVACMD: C:\Program Files\Java\jdk1.7.0_80\bin
I found that the only sure way to predict which version Ant will produce is by brute-forcing the following in build.xml:
<property name="ant.build.javac.source" value="1.7"/>
<property name="ant.build.javac.target" value="1.7"/>
So, my recommendation to you: Try placing in your build.xml the following:
<property name="ant.build.javac.source" value="1.8"/>
<property name="ant.build.javac.target" value="1.8"/>
Update, for the benefit of those with a variation of the problem described in the OP, to eliminate any possibility of "Eclipse fooling Ant":
Go to Window > Preferences > Java > Installed JREs and try leaving only the target JRE, making sure it is the one inside the JDK folder (not the sibling one directly under the Java folder).
Go to Project > Properties > Java Compiler and check Enable project specific settings, making sure that the Compiler compliance level is set to the target JRE java version.
In addition to what datv said above, I'll add from experience:
Ant's javac, java, and junit tasks have a jvm attribute that determines how to run the JDK/JRE, if fork="true". Unfortunately, it only sets the raw launcher, and doesn't change all the other settings. When I set the jvm attribute to the full path of a Java 8 JRE, turning on ant's -d switch shows that it is being used as the executable, but followed by
'-Djava.specification.version=9'
'-Dsun.boot.library.path=C:\Java\x64\jdk-9.0.1\bin'
'-Djava.home=C:\Java\x64\jdk-9.0.1'
'-Djava.runtime.version=9.0.1+11'
'-Djava.version=9.0.1'
'-Djava.library.path=...;C:\Java\x64\jdk-9.0.1\bin;.....
'-Djava.vm.version=9.0.1+11'
'-Djava.class.version=53.0'
all of which take precedence.
It turns out that Ant cares more about the JAVACMD environment variable when it starts up. In the situation above, our build framework had set JAVACMD to C:\Java\x64\jdk-9.0.1\bin\java, and the individual jvm= and executable= attributes on specific tasks were... not "ignored" really, merely pointless and misleading.

using ant svn task to get the version of a working copy?

Is there a way use the svn ant task to get the svn revision number of a working copy and put it into a variable?
I would like to add an entry in my Java manifest file which includes the svn revision number, e.g. 0.9.65361 where 65361 is the revision number.
Aha, I found this idea, which depends only on the svnversion command-line utility in SVN.
<project name="ant-exec-example" default="svnversion" basedir=".">
<target name="svnversion">
<exec executable="svnversion" outputproperty="svnversion" />
<echo message="SVN Version: ${svnversion}"/>
</target>
</project>
Here's where it captures the version in an ant property:
<exec executable="svnversion" outputproperty="svnversion" />
There are a couple of ways -
Use a utility - I believe you are looking for this - https://code.google.com/p/svntask/ I have used it for some side
projects and it works well.
Use commandline utility. - "svn info http://svn.myweb.com/myproject". To use this method simply create a
batch file and put this command in the batch file. Then call this
batch file from your ant task and get the revision number from the
text by searching for that starts with line "Revision:". Or you can
just dump the whole result.
Here is my variant to bundle svn revisions info within the application artifact:
<target name="svn_revisions">
<hostinfo prefix="HOST"/>
<echo file="${dir.out}/.revisions" message="Built by ${user.name} on ${HOST.NAME}${line.separator}"/>
<exec dir="${basedir}" executable="svn" output="${dir.out}/.revisions" append="true">
<arg line="info"/>
</exec>
<exec dir="${basedir}" executable="svn" output="${dir.out}/.revisions" append="true">
<arg line="status -u"/>
</exec>
</target>
<target name="build-war" depends="compile, svn_revisions">
<war basedir="web" file="${dir.out}/ROOT.war" webxml="web/WEB-INF/web.xml">
<!-- main stuff -->
<zipfileset dir="${dir.out}" prefix="META-INF" includes=".revisions"/>
</war>
</target>

Using Eclipse Compiler in Jenkins to get compiler warnings/errors

I want to have the eclipse compiler warnings shown in my Jenkins Job.
I know that it is possible to use the Eclipse Compiler using the ant javac adapter.
That way Eclipse compiler warnings are shown when using ant.
Problem is that when i use an ant script in Jenkins he ignores the javac settings and just uses the normal compiler.
Did anyone try to use the eclipse compiler in jenkins and get the compiler warnings? maybe even send the compiler warnings to Sonar?
After having trouble with the Eclipse compiler ant javac adapter, I use the batch compiler instead in a separate target for generating Eclipse warnings. I then use the Warnings Plugin to parse the generated compiler warnings in Jenkins.
The batch compiler is conveniently packaged in a separate jar, downloadable under the "JDT Core Batch Compiler" section on an Eclipse project download page and also available in public maven repositories as Eclipse ECJ.
Provided you've staged the ecj jar to ecj.dir, the following build script may be leveraged to generate Eclipse warnings,
build.xml
<?xml version="1.0" encoding="UTF-8" ?>
<project name="some-project" default="eclipse-warnings" basedir=".">
<target name="eclipse-warnings" depends="init">
<property name="ecj.log.dir" value="${build.dir}/ecj" />
<property name="ecj.warnings.file" value="${ecj.log.dir}\eclipse_compiler_out.txt"/>
<delete dir="${ecj.log.dir}" />
<mkdir dir="${ecj.log.dir}" />
<property name="ecj.properties" value="${basedir}\etc\ecj\eclipse_compiler.properties" />
<!-- Redirect output to tempfile if you don't want results also on console -->
<tempfile property="ecj.output.tempfile" suffix=".log" deleteonexit="true" />
<echo message="Generating Eclipse warnings to ${ecj.warnings.file}" />
<java
jar="${ecj.dir}/ecj.jar"
fork="true"
maxmemory="512m"
output="${ecj.output.tempfile}">
<arg value="-cp" />
<arg value="${toString:compile.classpath}" />
<arg value="-d" />
<arg value="none" />
<arg value="-enableJavadoc" />
<arg value="-log" />
<arg value="${ecj.warnings.file}" />
<arg value="-${javac.source.version}" />
<arg value="-properties" />
<arg value="${ecj.properties}" />
<arg value="${src.dir}" />
<arg value="${test.dir}" />
</java>
<!-- Echo number of warnings found -->
<loadfile srcfile="${ecj.warnings.file}" property="ecj.warnings.file.summary">
<filterchain>
<tailfilter lines="1" />
</filterchain>
</loadfile>
<echo message="${ecj.warnings.file.summary}" />
</target>
</project>
eclipse_compiler.properties contains the compiler warn/error settings and may be copied from a project's .settings/org.eclipse.jdt.core.prefs file or defined in the CompilerOptions class.
eclipse_compiler.properties
#Eclipse compiler warnings and errors
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
If you wish to use a different compiler interface than those supplied with ant, you can write a class that implements the CompilerAdapter interface (package org.apache.tools.ant.taskdefs.compilers).
Supply the full classname in the build.compiler property or the compiler attribute.
This should work

Categories