ant file that depends on another ant file - ant

I have two projects, each with its own ant build file.
What should I do so that, when I build project B, it will first build project A using project A's antfile?

You can achieve this by using the ant task, which runs ant on an external buildfile.
Example:
<ant antfile="../otherproject/build.xml" target="compile"/>
Properties
By default all current properties are passed to the invoked ant build, this can be disabled by setting inheritAll="false", if you want the other build to behave natively.
Properties that are need can be passed by nested tags:
<ant inheritAll="false" antfile="../otherproject/build.xml" target="compile">
<property name="my.property" value="myValue"/>
</ant>

Related

Jenkins ant plugin has wrong value for ${user.dir} working directory

I have the following build file in C:\A\B
<project name="demo" default="printCWD">
<target name="printCWD">
<echo message="user.dir=${user.dir}"/>
</target>
</project>
and run this command whilst in C:\A
ant -buildfile B\build.xml
it prints "C:\A"
But from the Ant plug-in installed on a Jenkins CI machine, which has the Buildfile setting set to "B/build.xml", it prints "/workspace/B"
Why is it on my local machine it prints the folder from which I invoked the ant command, yet on the Jenkins CI server it prints the folder that the buildfile is in?
Many thanks for any help.
Paul
It's because the Jenkins Ant plugin is changing the working directory to the directory containing the buildfile just before executing it, therefore causing user.dir to point to that directory (/workspace/B).
A look at the source code of the Ant plugin at https://github.com/jenkinsci/ant-plugin/blob/master/src/main/java/hudson/tasks/Ant.java reveals that the working directory is changed to the parent of the build file, specifically in this line (note the call to pwd(buildFilePath.getParent()):
r = launcher.launch().cmds(args).envs(env).stdout(aca).pwd(buildFilePath.getParent()).join();
Given this difference in behavior between locally and on Jenkins, I wouldn't personally rely on the user.dir property. If you want to access the current workspace of the Jenkins job, you can use the built-in environment variables provided by Jenkins:
<property environment="env"/>
<target name="printCWD">
<echo message="workspace=${env.WORKSPACE}"/>
</target>
If you don't want to explicitly reference the WORKSPACE env variable in the buildfile, you can provide a custom property to pass it from outside (with the default value set to user.dir):
<property name="root.dir" value="${user.dir}" /> <!-- default value -->
<target name="printCWD">
<echo message="root.dir=${root.dir}"/>
</target>
Then pass -Droot.dir=${WORKSPACE} in the Jenkins job.

Checking inputs before running dependent tasks

I've got a Ant build script which I need to compile part of my project (it links into a third-party build system for the JavaScript libraries we use).
I want to wrap Gradle around this, so I've imported the Ant build, and I can successfully invoke the Ant targets via Gradle. I've even added input and output checking to the targets, so that they won't run if they don't need to
The Ant targets have setup work that they do - mostly importing configurations and settings. They do this via a dependency on an init target, which takes about 4-5 seconds to run. What I would like to do is prevent that init target running if the inputs on the main task have been satisfied.
Any suggestions?
Example Ant build script (build.xml):
<?xml version="1.0" encoding="utf-8"?>
<project name="MyProject" default="build">
<target name="init" />
<target name="build" depends="init">
<echo message="hello" file="output.txt" />
</target>
</project>
Example Gradle script to go with it (build.gradle):
ant.importBuild 'build.xml'
build {
inputs.dir file('src')
outputs.file file('output.txt')
}
Ideally, when I run gradle build, I don't want init to run if build is up-to-date.
Any suggestions?
The up-to-date check for build will only happen after init has run. What you can do is to declare the same inputs for init, and if it has no file outputs, outputs.upToDateWhen { true }. Perhaps this meets your needs.

Using "antcall" in included ant files

I have a shared ant script b.ant which internally use antcall. It calculates a property that the client scripts use. I use include instead of import client scripts to avoid unintentional overwriting of targets, but this gives me a problem with the antcall.
When using include all targets in b are prefixes, and depends attributes in b are updated accordingly. This is however not true for antcall. Is there a there are way to handle this, i.e. make antcall always call the "local" ant target?
I can workaround this by using import, but then I'll get all the overwrite problems. It is not possible to use depends instead of antcall.
Example files
I have two files:
a.ant
<project>
<include file="b.ant" as="b" />
<target name="test-depends" depends="b.depend">
<echo>${calculated-property}</echo>
</target>
<target name="test-call" depends="b.call">
<echo>${calculated-property}</echo>
</target>
</project>
b.ant
<project>
<target name="depend" depends="some-target">
<property name="calculated-property" value="Hello World"/>
</target>
<target name="call">
<antcall target="some-target" inheritrefs="true"/>
<property name="calculated-property" value="Hello World"/>
</target>
<target name="some-target"/>
</project>
Example output
Calling test-depend works as expected but test-call fails with this output:
b.call:
BUILD FAILED
D:\ws\rambo2\ws-dobshl\ant-test\b.ant:6: The following error occurred while executing this line:
Target "some-target" does not exist in the project "null".
Total time: 258 milliseconds
Ant is a dependency matrix specification language. Usually a bunch of <antcall/>, <ant/>, <include/> and <import/> is a sign of a poorly written build script. It's a developer trying to force Ant to act like a programming language.
For developer, it makes sense to break up a program into smaller files. Even Python and Perl scripts can benefit from this. However, breaking up an Ant build script usually causes problems. We had a developer who went through every project and broke up all the build.xml files into six or seven separate build files in order to improve the process. It basically broke the whole Ant dependency mechanism. To fix it, he then tossed in a bunch of <ant/> calls and <include> tasks. In the end, it meant that each target was called between 12 to 20 times.
Not using <import/> and <antcall/> isn't a hard and fast rule. But, I've been using Ant for years and rarely ever used these mechanisms. When I do, it's usually for a shared build file that multiple projects will use (which sounds like what you have) but instead of defining targets in my shared build file, I define macros. This eliminates the target namespace issues that you are having, and the macros work better because they act more like Ant tasks. This is especially true with the introduction of <local/> in Ant 1.8.
See if you can restructure the shared build file into using <macrodef/> instead of targets. It will make it much easier to include your shared build file.
Give a name to the <project> in b.ant and then change the target of the <antcall>:
<project name="b"> <!-- Give the project a name -->
<target name="depend" depends="some-target">
<property name="calculated-property" value="In b.depend"/>
</target>
<target name="call">
<!-- Specify the name of the project containing the target -->
<antcall target="b.some-target" inheritrefs="true"/>
<property name="calculated-property" value="In b.call"/>
</target>
<target name="some-target"/>
</project>
The result of ant -f a.ant test-call:
b.call:
b.some-target:
test-call:
[echo] In b.call
BUILD SUCCESSFUL
With the changes to b.ant, the <include> in a.ant can be simplified by removing the as attribute:
<include file="b.ant" />

Does using the 'ant' tag in an ant script start a seperate JVM?

Does using the 'ant' tag in an ant script start a seperate JVM?
My code is like:
<target name="run" description="base tests">
<ant dir="suite1"/>
<ant dir="suite2"/>
<ant dir="suite3"/>
</target
From ANT manual, it says that if we use 'ant' inside target tag, it is not part of same build file, but when I monitor the Java process, only one Java process runs on my machine.
It runs as a separate project within the same JVM

Ant, set environmental variable for <ant> task?

I want to run another ant build file from ant, and the <ant> task looks perfect for this.
The other build file uses environmental variables for a couple things. Is there a way to set environmental variables for the child ant process?
I see that the <exec> task seems to support nested <env>s, but nothing similar for <ant>.
From the documentation of ant task,
By default, all of the properties of the current project will be available
in the new project.
You can also set properties in the new project from the old project by using
nested property tags.
<ant antfile="subproject/property_based_subbuild.xml">
<property environment="env"/>
</ant>
by default the inner ant call inherits the parent properties
<ant inheritAll="true" antfile="subproject/subbuild.xml">
<!--inheritAll="true" is default value, this is unecessary -->
<property name="myprop" value="foo"/>
<antcall target="myTarget"></antcall>
<ant antfile="myAntFile"></ant>
</ant>
In this case, "myTarget" and all targets on "myAntFile" can get "foo" as "myprop" value.

Resources