I have a cross-platform application and we use ant to build different things on different platforms. Now a new requirement came up and I need to do things differently if building on Snow Leopard or later vs Leopard.
I've looked at http://www.devdaily.com/blog/post/java/how-determine-operating-system-os-ant-build-script which shows how to distinguish between Windows and Macintosh etc., and http://www.jajakarta.org/ant/ant-1.6.1/docs/en/manual/api/org/apache/tools/ant/taskdefs/condition/Os.html which shows additional properties for os, like ${os.version}.
What I haven't figured out is how can I compare the os.version value and if it is 10.6 or higher do the Snow Leopard thing. If I could set a variable snow_leopard to 1 when on Snow Leopard I think I would be able to figure the rest of it out.
You might use the condition task for this. The available conditions, notable for os are here.
It would work in the same way as for 'os family':
<condition property="isSnowLeopard">
<os family="mac" version="10.6.6" />
</condition>
But that means you have to put in the incremental version number - the version string has to match exactly.
For a 'fuzzier' alternative, you could use a matches condition, something like this perhaps
<condition property="isSnowLeopard">
<matches string="${os.version}" pattern="^10.6." />
</condition>
When OSX Lion emerges, you may want to extend the pattern like the this:
<condition property="isSnowLeopardOrGreater">
<matches string="${os.version}" pattern="^10.[67]." />
</condition>
Or introduce a separate check for 10.7.
Using the <if> task provided by ant-contrib, you can achieve this to an extent, by making an equals check for the os version.
...
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/location/of/ant-contrib-1.0b3.jar"/>
</classpath>
</taskdef>
<target name="oscheck">
<property name="osver" value="${os.version}"/>
<if>
<equals arg1="${os.version}" arg2="6.1"/>
<then>
<echo message="Windows 7"/>
...
</then>
</if>
</target>
...
Related
I'm trying to write a target like so
<!-- Properties that must be set when invoking via antcall:
DestinationDir Directory to compile classes to.
ReleaseVer Java version this is being compiled for (i.e. 8, 9, etc). Must be at least 8.
Debug Whether to compile with debug information. Either 'on' or 'off'.
-->
<target name="java-support-compile" description="compile JavaSupport source">
<mkdir dir="${DestinationDir}"/>
<condition property="ModulesSupported">
<not>
<equals arg1="${ReleaseVer}" arg2="8" />
</not>
</condition>
<!-- Compile GSSUtilWrapper separately, since we can't use the 'release' option when referencing the sun.security.jgss.GSSUtil package,
and we need to add an --add-exports option to access the java.security.jgss module for ${ReleaseVer} > 9 -->
<javac srcdir="${javasupport.src.dir}" source="1.${ReleaseVer}" target="1.${ReleaseVer}" debug="${Debug}" destdir="${DestinationDir}">
<include name="${GSSUtilWrapperFile}"/>
<compilerarg if="${ModulesSupported}" line="--add-exports java.security.jgss/sun.security.jgss=ALL-UNNAMED" />
</javac>
<javac srcdir="${javasupport.src.dir}" release="${ReleaseVer}" debug="${Debug}" destdir="${DestinationDir}">
<exclude name="${GSSUtilWrapperFile}"/>
</javac>
</target>
The error I'm getting is compilerarg doesn't support the "if" attribute. I need it to be conditional as if I pass in ReleaseVer=8, I get the error error: option --add-exports not allowed with target 8
I got that syntax from http://ant-contrib.sourceforge.net/compilerarg.html, but I didn't realize this wasn't in core ant (and I don't want to install anything else if possible).
How can I do this in standard ant?
One option, perhaps not the cleanest, would be to modify your <condition> task to set the text of the compiler arg, rather than a boolean, and use that. Something like this:
<condition property="javac_arg"
value="--add-exports java.security.jgss/sun.security.jgss=ALL-UNNAMED"
else="">
<not>
<equals arg1="${ReleaseVer}" arg2="8" />
</not>
</condition>
<javac compiler="modern" srcdir="." includeantruntime="no">
<compilerarg line="${javac_arg}" />
</javac>
Note the else parameter, which ensures the arg passed to javac is empty when the condition is false.
my app-builder ant task is like that:
<target name="build.app" depends="eval.dev.params, prepare.app, install.plugin.pay">
<exec executable="/usr/sbin/ipconfig" outputproperty="ip.addr" osfamily="mac">
<arg value="getifaddr"/>
<arg value="en0"/>
</exec>
<condition property="current.ip" value="${server.path}">
<not>
<equals arg1="${build.env}" arg2="dev"/>
</not>
</condition>
<condition property="current.ip" value="http://${ip.addr}:${server.port}">
<equals arg1="${build.env}" arg2="dev"/>
</condition>
<echo message="${current.ip}"/>
<app-builder applicationFolder="${build.path}/${context.root}"
nativeProjectPrefix="${context.root}" outputFolder="${build.path}"
worklightserverhost="${worklight.server.host}"/>
</target>
The problem is that after this step I get two xcodeprojects instead of one and the ios build then fails and I don't know how to inspect "app-builder" work.
The two resulting xcode projects are named this way:
/workspace/kWallet/build/myAppEnv/iphone/native/myAppMyAppIphone.xcodeproj
/workspace/kWallet/build/myAppEnv/iphone/native/myAppEnvMyAppIphone.xcodeproj
Are you sure that they both are being build by ant???
The myAppMyAppIphone.xcodeproj, by looking at name format, is the one built by the ant utility and the other myAppEnvMyAppIphone.xcodeproj was built by eclipse.
When you use eclipse to build the ios env it uses the format
<project><app><env>.xcodeproj
where as ant uses the format
<app><app><env>.xcodeproj
<app-builder applicationFolder="${build.path}/${context.root}"
nativeProjectPrefix="${context.root}" outputFolder="${build.path}"
worklightserverhost="${worklight.server.host}"/>
If you provide the nativeProjectPrefix to be the projectname then we get the xcode file name as same.
I'd like to execute subant on some condition. something like:
<if>
<equals value="value1" property="${some.property">
<then>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref1" />
</subant>
</then>
<else>
<subant target="#{target}" failonerror="true" inheritall="false">
<buildpath refid="some-ref2" />
</subant>
</else>
</if>
But can't find a way to do it. Read the ant manual and googled, but no solution is found.
Thanks.
I believe the error may lie in your equals tag. Instead of using the 'value' and 'propery' attributes, try using 'arg1' and 'arg2', i.e.:
<equals arg1="value1" arg2="${some.property}">
Check out the examples in the ant-contrib doc: http://ant-contrib.sourceforge.net/tasks/tasks/if.html.
If the problem is that your 'if', 'then', and/or 'else' tags are not resolving properly, then you may be missing the ant-contrib libraries. Ant-contrib is not natively included with ant, but you can download it here: http://sourceforge.net/projects/ant-contrib/files/
Per the ant-contrib site (http://ant-contrib.sourceforge.net/), here's what you must do to install ant-contrib:
Option 1: Copy ant-contrib-0.3.jar to the lib directory of your Ant installation. If you want to use one of the tasks in your own project, add the lines
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
to your build file.
Option 2: Keep ant-contrib-0.3.jar in a separate location. You now have to tell Ant explicitly where to find it (say in /usr/share/java/lib):
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>
Please look up a <target if="${some.property}>. You may want another target with an unless.
If the property has to do with a file existing, see Ant task to check a file exists?. Even if this is not your main concern, I am sure you can get the idea from the accepted answer.
Do you mean calling another target
if so here is
<if>
<equals value="value1" property="${some.property">
<then>
<antcall target="#{target}" failonerror="true" inheritall="false">
</then>
<else>
<antcall target="#{target}" failonerror="true" inheritall="false">
</else>
</if>
I have an ant target I don't want called unless I am running ant on Linux (Not called on Windows)
<target name="jar.all" depends="clean,compile.nic,jar,jar.resources"/>
The target that I don't want called on Windows is: compile.nic
How can I do this?
Insert an if property to your compile.nic target.
<target name="compile.nic" if="windowsos">
And use this conditions before running your target
<condition property="windowsos">
<os family="windows" />
</condition>
<condition property="linuxos">
<os family="unix" />
</condition>
Here is a real-world example for Windows vs. UNIX commands. The ELSE improves on previous answers.
<condition property="maven.executable" value="mvn.bat" else="mvn">
<os family="windows" />
</condition>
<target name="clean">
<exec executable="${maven.executable}">
<arg value="clean" />
</exec>
</target>
Can I make the Ant copy task OS-specific?
Additionally some tasks support os attribute. for example exec:
<exec executable="cmd" os="windows"/>
You can use the os condition to set a property, and then skip your target by adding either the if or unless attributes (depending on how you define your property)
I have an Ant script that performs a copy operation using the 'copy' task. It was written for Windows, and has a hardcoded C:\ path as the 'todir' argument. I see the 'exec' task has an OS argument, is there a similar way to branch a copy based on OS?
I would recommend putting the path in a property, then setting the property conditionally based on the current OS.
<condition property="foo.path" value="C:\Foo\Dir">
<os family="windows"/>
</condition>
<condition property="foo.path" value="/home/foo/dir">
<os family="unix"/>
</condition>
<fail unless="foo.path">No foo.path set for this OS!</fail>
As a side benefit, once it is in a property you can override it without editing the Ant script.
The previously posted suggestions of an OS specific variable will work, but many times you can simply omit the "C:" prefix and use forward slashes (Unix style) file paths and it will work on both Windows and Unix systems.
So, if you want to copy files to "C:/tmp" on Windows and "/tmp" on Unix, you could use something like:
<copy todir="/tmp" overwrite="true" >
<fileset dir="${lib.dir}">
<include name="*.jar" />
</fileset>
</copy>
If you do want/need to set a conditional path based on OS, it can be simplified as:
<condition property="root.drive" value="C:/" else="/">
<os family="windows" />
</condition>
<copy todir="${root.drive}tmp" overwrite="true" >
<fileset dir="${lib.dir}">
<include name="*.jar" />
</fileset>
</copy>
You could use the condition task to branch to different copy tasks... from the ant manual:
<condition property="isMacOsButNotMacOsX">
<and>
<os family="mac"/>
<not>
<os family="unix"/>
</not>
</and>
Declare a variable that is the root folder of your operation. Prefix your folders with that variable, including in the copy task.
Set the variable based on the OS using a conditional, or pass it as an argument to the Ant script.
You can't use a variable and assign it depending on the type? You could put it in a build.properties file. Or you could assign it using a condition.
Ant-contrib has the <osfamily /> task. This will expose the family of the os to a property (that you specify the name of). This could be of some benefit.