How can I execute an ant target depending on the value of an environment variable? - if-statement

I want to execute an ant script on two different computers. Depending on the name of the computer either one of the two targets should be executed. Following doesn't work:
<project name="import" default="all">
<property environment="env"/>
<target name="staging" if="${env.COMPUTERNAME}='STG'">
<echo>executed on staging</echo>
</target>
<target name="production" if="${env.COMPUTERNAME}='PRD'">
<echo>executed on production</echo>
</target>
<target name="all" depends="staging,production" description="STG or PRD"/>
</project>
As I understood, "if" can only be used with property and it checks whether a property is set or not. But is there a way to to make a condition depending on the value of a property?

I would suggest writing an "init" target that sets any conditions you need for later build steps, and also fails the build if certain required properties don't evaluate to what's expected.
For example:
<target name="all" depends="staging,production,init" />
<target name="staging" if="staging.environment" depends="init">
<echo message="executed on staging" />
</target>
<target name="production" if="production.environment" depends="init">
<echo message="executed on production" />
</target>
<target name="init">
<condition property="staging.environment">
<equals arg1="${env.COMPUTERNAME}" arg2="STG" />
</condition>
<condition property="production.environment">
<equals arg1="${env.COMPUTERNAME}" arg2="PRD" />
</condition>
<fail message="Neither staging nor production environment detected">
<condition>
<not>
<or>
<isset property="staging.environment" />
<isset property="production.environment" />
</or>
</not>
</condition>
</fail>
</target>

Related

Execute selected ant tasks for a selected set of projects

I have defined targets in ant for our games, e.g. clean, build-ios, build-android, deploy-ios, deploy-android, etc. Now I would like to define a new set of targets that represent our games, say game1, game2, game3.
My goal is to be able to launch ant with a set of target games and a set of target tasks so that for each selected game, each selected task is executed.
Example pseudo code: Foreach [game1, game3]: clean, build-ios, deploy-ios
How can I achieve this with ant? A requirement would be to define which games and which tasks are selected through targets, not to write them in a file that is altered manually.
The subant task is useful for situations where you have multiple subprojects that share similar structures.
In your main build.xml, define a target that rubs the desired build target on your game subdirectories, along with all of the generalized build targets.
<target name="deploy-all">
<subant target="deploy">
<dirset dir="." includes="game-*" />
</subant>
<echo message="All games deployed." />
</target>
<target name="deploy" depends="deploy-ios,deploy-android">
<echo message="${ant.project.name} build complete." />
</target>
<target name="clean">
<echo message="Cleaning ${ant.project.name}" />
</target>
<target name="build-ios" depends="clean">
<echo message="Building iOS ${ant.project.name}" />
</target>
<target name="build-android" depends="clean">
<echo message="Building Android ${ant.project.name}" />
</target>
<target name="deploy-ios" depends="build-ios">
<echo message="Deploying iOS ${ant.project.name}" />
</target>
<target name="deploy-android" depends="build-android">
<echo message="Deploying Android ${ant.project.name}" />
</target>
Then, in the game-* subdirectories, create a simple build.xml that links back to the common one.
game-1/build.xml:
<project name="game-1" default="build">
<import file="../build.xml" />
<echo message="=== Building Game 1 ===" />
</project>
game-2/build.xml:
<project name="game-2" default="build">
<import file="../build.xml" />
<echo message="=== Building Game 2 ===" />
</project>
Edit: If your build needs to include/exclude certain subprojects based on the user's input or a pre-defined property, you can modify the subant task's nested resource collection to accommodate for this.
<property name="game.includes" value="game-*" />
<property name="game.excludes" value="" />
<subant target="deploy">
<dirset dir="." includes="${game.includes}" excludes="${game.excludes}" />
</subant>
The user can then run a command that optionally passes values for game.includes and/or game.excludes. If these properties are not specified, the values defined above by the property task will be used as defaults.

MsBuild Cpp BeforeBuild not working

I want to execute a target before project builds.
I have define the following in the .vcxproj file.
<Target Name="BeforeBuild">
<Message Text="BeforeBuilds" />
<CallTarget Targets="myTarget" />
</Target>
<Import Project="..\GetCat.targets" />
<Target Name="DefaultBeforeTarget" BeforeTargets="Default">
<CallTarget Targets="myTarget" />
</Target>
<Target Name="myTarget" Inputs="$(TargetPath)" Outputs="$(TargetDir)$(TargetName).tlb" DependsOnTargets="GetCat">
<Message Text="Calling myTarget" />
<Exec Command="mkdri HelloW" />
</Target>
The myTarget <Message> is not getting called.
How to fix this?

Nant Build script undifined Issue

I have the following code in a nant build script:
<project name="fgs">
<property name="build.dir" value="build"/>
<property name="build.bin.dir" value="${build.dir}/bin"/>
<fileset id="provider.1.0-references" basedir="${build.bin.dir}">
<include name="thenameofadllfile.*"/>
</fileset>
<macrodef name="build-dist">
<attributes>
<attribute name="version"/>
<attribute name="service.references"/>
<attribute name="release.type"/>
</attributes>
<sequential>
<echo message="service.references: ${service.references}" />
<copy todir="${build.dist.dir}/server/${version}/${release.type}/bin" >
<fileset refid="#{service.references}" casesensitive="false" />
</copy>
</sequential>
</macrodef>
<target name="create-dist">
<server-staging-dist release.type="staging" version="1.0" service.references="service.1.0-references" />
</target>
however when i run this code I get: fileset reference '#{service.references}' is not defined.
i have tried it with changing the doller sign for the # symbol. Not sure what the difference is?
Thanks in advance for any help or advice given.
Try <fileset refid="provider.1.0-references" casesensitive="false" />

I want to use NAnt's foreach to iterate files in a folder, how to force alphabetic iteration?

I have an NAnt task "ship" to package my current .sql scripts into a build, then name the build with an incrementing int {######} and copy it to a build folder.
I have another NAnt task which executes those build scripts.
They must execute in order, but in my last attempt, they were not. Can I "force" NAnt to work alphabetically?
FAIL:
<fileset basedir="source\tsql\builds\" id="buildfiles">
<include name="*.sql.template.sql" />
<exclude name="*.sql" />
<exclude name="*asSentTo*" />
</fileset>
<foreach item="File" property"filename">
<in refid="buildfiles">
<echo message="${filename}" />
</in>
</foreach>
PASS:
<foreach item="File" property="filename" in="source\tsql\builds">
<do>
<if test="${string::ends-with(filename,'.sql.template.sql')}">
<echo message="${filename}" />
</if>
</do>
</foreach>
To satisfy my curiosity I tried to reproduce the problem with this script:
<?xml version="1.0"?>
<project name="foreach.test" default="foreach.alpha">
<target name="foreach.alpha">
<foreach item="File" in="C:\foo" property="filename">
<do>
<echo message="${filename}" />
</do>
</foreach>
</target>
</project>
The filenames are printed out in alphabetical order. So conventional use of foreach already seems to be the solution to the problem.
Here is how you do it with a fileset
<fileset id="mySet">
<include name="*.sql" />
</fileset>
<copy>
<fileset refid="mySet" />
</copy>
<foreach item="File" property="filename">
<in>
<items refid="mySet" />
</in>
<do>
<echo message="Copied files: ${filename} to directory: ${Folder}." />
</do>
</foreach>

Publish WebApplication using NAnt

Is it possible to accomplish publish (as in Visual Studio publish on Web Application project) on solution using NAnt? I just can't find the solution.
They key is to use the built-in "_CopyWebApplication" target.
Here is what i do
<target name="compile" description="Compiles the project.">
<exec basedir="." program="${DotNetPath}msbuild.exe" commandline=" src/MyProject.Web/MyProject.Web.csproj /nologo
/t:Rebuild
/t:ResolveReferences;_CopyWebApplication
/p:OutDir=../../output/build/bin/
/p:WebProjectOutputDir=../../output/build/
/p:Debug=${debug}
/p:Configuration=${configuration}
/v:m"
workingdir="." failonerror="true" />
</target>
with the dir structure of:
/project.build
/src/myprojct.sln
/src/myporject.web/myproject.web.csproj
/output
Edit: i also use this to use the YUI compression to compress my css and js
<target name="compress-js">
<foreach item="File" property="filename">
<in>
<items basedir="output/build/assets/javascript/">
<include name="/**/*.js" />
<exclude name="/**/*.min.js" />
<exclude name="/**/*.pack.js" />
</items>
</in>
<do>
<exec basedir="." program="${JavaPath}java" commandline=" -jar S:\yuicompressor-2.4.1\build\yuicompressor-2.4.1.jar --type js --charset utf-8 -o "${filename}" "${filename}"" failonerror="true" />
</do>
</foreach>
</target>
<target name="compress-css" depends="combine-css">
<foreach item="File" property="filename">
<in>
<items basedir="output/build/assets/css/">
<include name="/**/*.css" />
<exclude name="/**/*.min.css" />
<exclude name="/**/*.pack.css" />
</items>
</in>
<do>
<exec basedir="." program="S:\Java\jdk1.6.0_11\bin\java" commandline=" -jar S:\yuicompressor-2.4.1\build\yuicompressor-2.4.1.jar --type css --charset utf-8 -o "${filename}" "${filename}"" failonerror="true" />
</do>
</foreach>
</target>
Using MSBuild beats the purpose of using NAnt, NAnt is something that replaces MSBuild, use the below to do a clean NAnt compilation of Web Application Projects as in VS 2003/2005/2008.
It works for me!
<?xml version="1.0"?>
<project name="MyTest" default="run">
<property name="basename" value="MyTest1x"/>
<property name="debug" value="false"/>
<property name="copytarget" value="c:\temp"/>
<target name="clean">
<delete>
<fileset basedir="${copytarget}">
<include name="bin/${basename}.dll"/>
<include name="**/*.???x"/>
<include name="Web.config"/>
</fileset>
</delete>
</target>
<target name="build">
<mkdir dir="${copytarget}/bin" />
<csc target="library" output="${copytarget}/bin/${basename}.dll" >
<sources>
<include name="*.cs"/>
</sources>
</csc>
</target>
<target name="run" depends="clean,build">
<copy todir="${copytarget}" overwrite="true">
<fileset basedir=".">
<include name="**/*.???x" />
<include name="Web.config" />
</fileset>
</copy>
</target>
</project>
I know this is an old question, but I just learned something, so I decided I'd share: While it is 100% true that the "_CopyWebApplication" target exists and works, as of .NET 4.0 it has been superseded by the "_WPPCopyWebApplication" target in Microsoft.Web.Publishing.targets, which supports new features like web.config transformation syntax, etc.
(reposting to all the similarly worded questions, so don't vote for this one :) )
Here is how you can do it using the MSBUILD task for nant:
<property name="debug" value="AutomatedDebug" />
<property name="configuration" value="Debug;TargetFrameworkVersion=v3.5" />
<msbuild project="src\WebApplication1\WebApplication1.csproj" failonerror="true">
<arg value="/nologo" />
<arg value="/t:Rebuild" />
<arg value="/t:ResolveReferences;_CopyWebApplication" />
<arg value="/p:OutDir=../../build/Debug/WebApplication/" />
<arg value="/p:WebProjectOutputDir=../../build/Debug/WebApplication-Deploy/" />
<arg value="/p:Debug=${debug}" />
<arg value="/p:Configuration=${configuration}" />
<arg value="/v:m" />
</msbuild>
This will compile the WebApplication into a deployable folder, just like using the "Publish" feature from within Visual Studio.