Ant if statement - ant

Below is a snippet from my build.xml file.
I want to modify the file so that the jar name is set depending on the value of a variable within the build file.
<info
jarName="java get"
jarUrl="${deploy-url}${polish.jarName}"
/>
So something like -
<info
if(${deploy-url} == "test")
jarName="java get"
else
jarName="java test"
jarUrl="${deploy-url}${polish.jarName}"
/>
Or can I call a java program to return the jar name, so something like -
<info
jarName=java programToExecute
jarUrl="${deploy-url}${polish.jarName}"
/>
Thanks for any suggestions,
Adrian

The Ant Contrib project has a selection of custom tasks, including an <if> task that will let you do this. It's clumsy, but it works.

Related

msbuild custom compiler/build script

I'm attempting to use TFS and MSBuild as a build and source control for a non-.NET project. This project contains a series of individual called .skbsrc files, that each compile into a .skb file. I'm trying to figure out if it's possible to use MSBuild in a way to build these files.
Say I'm using the example on the msdn website:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Include="testfile.skbsrc" />
</ItemGroup>
<Target Name="Build">
<Csc Sources="#(Compile)"/>
</Target>
</Project>
Csc is clearly used for C# code, and runs the csc.exe program. Is there a way I can make a block like this for my own compiler (skbuilder) so I could run like:
<Skbuilder Sources="#(Compile)" />
which in turn would run
>skbuilder testfile.skbsrc
If this is possible with msbuild, could anyone post an example? I've been unable to find anything in my searches.
Thank you so much.
You can create a customized task in msbuild to do it. "CSC" is a default task in C#, so what you need is to implement a similar task for your exe.
This MSDN article explains how to write a task for msbuild.
Take a look at the Exec Task.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<SourceFiles Include="*.skbsrc"/>
</ItemGroup>
<Target Name="Build">
<Exec Command="skbuilder "%(SourceFiles.Identity)""/>
</Target>
</Project>
You'll also need to pass an argument to your skbuilder program telling it to output it's files to the $(OutDir) directory or use Copy Task to pick up *.skb to $(OutDir). Use quotes around the argument incase the TFS workspace path has spaces in it.
Finally you can test this on your own machine without using TFS by creating a simple .BAT file:
set PATH=%CD%;C:\Windows\Microsoft.NET\Framework\v4.0.30319
msbuild build.proj > build.log

JarJar with Ant - how to use a Rule file

I would like to know how to run JarJar with Ant, passing the rules in with an external Rules file.
1) I know I can pass the rules in one by one as below:
<jarjar destfile="B.jar" >
<zipfileset src="A.jar" />
<rule pattern="com.a.**" result="test.b.#1" />
</jarjar>
2) I know I can pass the rules in a file if I run it from the command line:
java -jar jarjar.jar process <rulesFile> <inJar> <outJar>
3) I can use the above command line in an Ant <exec> task. (best workaround)
4) I found some reference to using a <rulesFile> tag in Maven.
The above options are not ideal for what I would like to do.
I want to run JarJar from an Ant task, passing in a rules file.
I have been unable to get any information about this, from any forum, or by mailing the developers of JarJar, so I have decided to answer this question with a workaround that I am using:
Use the DOCTYPE & ENTITY xml entities (as per suggestion on Ant website)
As an example, the below build.xml file includes the contents of another test.txt file inline. I import the text file using the tag include_this (this is my name - you can use any name here):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project [
<!ENTITY include_this SYSTEM "test.txt">
]>
<project name="Test" default="build" >
<target name="build" >
&include_this;
</target>
</project>
In this simple example, the contents of the test.txt file is:
<echo>This is a test.</echo>
So I've been using this workaround to replace the rules in the jarjar call. Putting the rules in the test.txt file:
<rule pattern="com.**" result="${project.output}.com.#1" />
<rule pattern="org.**" result="${project.output}.org.#1" />
My jarjar call then becomes:
<!-- jarjar uses the same syntax as the jar task -->
<jarjar destfile="${jarjar.output.dir}/${project.output}.jar" >
<!-- source files -->
<zipfileset src="${jar.output.dir}/${project.output}.jar" />
<!-- refactoring rules -->
&include_this;
</jarjar>

Liferay SDK portlet plugin: use ant target to modify .war file after being created

In a liferay portlet, the autogenerated build.xml (created with the SDK in eclipse, autogenerated by the wizard) always looks like this
<?xml version="1.0"?>
<project name="my-service-portlet" basedir="." default="deploy">
<import file="../build-common-portlet.xml" />
</project>
Is it advisable to add custom targets to this? I want to modify the .war file after it is created. Like this:
Is there a way with Apache Ant to update a jar file after it's been built?
My war-file is huge because it is autocreated by Liferay's service builder, and it seems to be in need of a few optimizations. I want to remove the WEB-INF/src/.java files (and those WEB-INF/classes/.class files in the .war) that are also in the WEB-INF/lib/.jar. They seem to be duplicated. Can I do this to save space during deployment and to simplify and speed-up the deployment process.
How would such an ant-target look like?
Sure, that's totally possible:
<project name="MyPortlet" basedir="." default="updateWarAndDeploy">
<import file="../build-common-portlet.xml" />
<target name="updateWarAndDeploy">
<antcall target="war"/>
-- modify war file --
<copy file="${plugin.file}" todir="${auto.deploy.dir}" />
</target>
</project>

Ant: "Duplicated project name in import" with imported build file

I have several build files which all import the same base build file, like this:
base.xml:
<project name="base">
<!-- does not define a 'build' target -->
</project>
buildA.xml:
<project name="buildA">
<import file="base.xml" />
<target name="build">
<ant antfile="buildB.xml" target="build"
inheritall="false" inheritrefs="false" />
</target>
</project>
buildB.xml:
<project name="buildB">
<import file="base.xml" />
<target name="build">
...snip...
</target>
</project>
(Module A depends on module B.)
Now, the above calling of B's build target from buildA.xml gives the following error:
Duplicated project name in import. Project base defined first in buildA.xml and again in buildB.xml
Since both buildA.xml and buildB.xml inherit the same base.xml, this seems unavoidable.
How could I get rid of this error?
Based on sudocode's answer, I solved the problem. Because the absolute path to base.xml is different in both cases, Ant does not recognize it as the same file. Even though inheritAll is set to false, the context of the calling task is preserved and this causes the name clash.
To solve this, one can omit the name attribute from base.xml. Since Ant 1.8, the import task has an attribute as, which can be used to reference base targets when the base project is nameless. If you don't override any targets, you can use include instead of import. I'm on 1.7, so that does not help me.
For previous versions of Ant, you can go through an exec call to prevent proliferation of the Ant context entirely (then you get two running Ant instances). Better yet, find a way to import the exact same base.xml (with the same absolute path) in both files.
Are you using Ant 1.6? This resolved Ant bug looks like the same issue.
EDIT
I tried to reproduce the dir structure you refer to in your recent comment.
./base.xml
./buildA
./buildA/buildA.xml
./buildB
./buildB/buildB.xml
And amended the build files accordingly, e.g.
<project name="buildA">
<import file="../base.xml"/>
<target name="build">
<ant antfile="../buildB/buildB.xml" target="build" inheritall="false" inheritrefs="false"/>
</target>
</project>
I still get no build error for the following with ant 1.8.2 or 1.7.1:
ant -f buildA/buildA.xml build

BND Ant task - wrap non-OSGi jars

I'm trying to use Ant bndwrap task to wrap non-OSGi jars in a directory. My current Ant configuration for this is:
<target name="wrap-jars" description="Wrap non-OSGi jars">
<taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${biz.aQute:bnd:jar}"/>
<bndwrap output="${dist.dir}/app-modules">
<fileset dir="${dist.dir}/app-modules" includes="*.jar" />
</bndwrap>
<move overwrite="true" todir="${dist.dir}/app-modules" >
<fileset dir="${dist.dir}/app-modules" includes="*.bar" />
<mapper type="glob" from="*.bar" to="*.jar" />
</move>
</target>
This works fine, but the problem is that it also wraps existing OSGi jar, which causes problems. For instance, I noticed it changes Bundle-SymbolicName header to some default value. It might be changing something else, which I don't want. I only want it to operate on jars that have no OSGi info at all.
Is there some way to tell BND to ignore existing OSGi headers in manifest, or complete jars that are already OSGi-fied?
I would store non-OSGi jars in a separate folder and modify the fileset to process only that folder.
I've noticed that recent bnd versions (for example, 2.1.0) now honour the Bundle-SymbolicName when rewrapping OSGi jars.
just change your fileset to exclude that jar

Resources