integrating grunt with ant - gruntjs

Are there any good tutorials for integrating grunt with ant? Our current build uses ant because we are a Java shop. However, the front-end is beginning to become a first class citizen, and we are examining using node and grunt for the front-end build. I need to integrate the front-end build with the ant build. I need to know how to normalize the exit codes for all my custom tasks as well as the built in grunt tasks and limit the console output to these predefined codes when the grunt tasks are called by ant. Any help would be greatly appreciated.

You could use this macro:
<macrodef name="exec-node">
<attribute name="module" description="The name of the NodeJS module to execute"/>
<attribute name="failonerror" default="true" description="Fail if the exit code is not 0"/>
<element name="args" implicit="yes" description="Argument to pass to the exec task"/>
<sequential>
<exec executable="cmd.exe" failonerror="#{failonerror}" osfamily="winnt">
<arg line="/c #{module}" />
<args/>
<!-- Windows cmd output workaround: http://stackoverflow.com/a/10359327/227349 -->
<!-- Forces node's stderror and stdout to a temporary file -->
<arg line=" > _tempfile.out 2<&1"/>
<!-- If command exits with an error, then output the temporary file -->
<!-- to stdout delete the temporary file and finally exit with error level 1 -->
<!-- so that the apply task can catch the error if #failonerror="true" -->
<arg line=" || (type _tempfile.out & del _tempfile.out & exit /b 1)"/>
<!-- Otherwise, just type the temporary file and delete it-->
<arg line=" & type _tempfile.out & del _tempfile.out &"/>
</exec>
<exec executable="#{module}" failonerror="#{failonerror}" osfamily="unix">
<args/>
</exec>
</sequential>
</macrodef>
And you can call any command: example:
<target name="jshint">
<exec-node module="grunt">
<arg value="jshint" />
</exec-node>
</target>
works like a charm: also ensures the stderr is also printed, which is a common problem when calling grunt.

Grunt can call out to the command line, so you could easily create several tasks in grunt that do nothing but execute an ant task via the shell.
The grunt-shell library makes it especially easy to execute external commands from a grunt task: https://github.com/sindresorhus/grunt-shell
Since you're talking about custom exit codes, though, you'll probably have to end up writing your own custom grunt task that executes a shell command and then looks at the response code (perhaps using the grunt.helpers.spawn helper): https://github.com/gruntjs/grunt/blob/master/docs/api_utils.md#gruntutilsspawn
My advice? My organization recently went through the same thing and it's best if possible to just make a clean break from ant and get rid of it entirely for your JavaScript-related projects.
Grunt has such a growing and useful library of plugins I'd be surprised if you couldn't duplicate your ant build files and create a 100% javascript solution.

you might use http://abc.tools.qafoo.com/ which includes an npm module *1)
The only thing you then need is a custom Target like:
…
<target
name="-mm:compile:main~hooked"
extensionOf="-compile:main~hook"
depends="
-my-compile-npm-hook
"
>
<target
name="-my-compile-npm-hook"
>
<echo>install local grunt-cli</echo>
<antcall target="npm:install">
<param name="in.npm.package.name" value="grunt-cli" />
</antcall>
</target>
…
after that you might run grunt in the .npm/node_modules/.bin/ directory alias ${npm.local.modulesdir}/.bin/
^^ don't miss to include or define properties from src/main/resources/extensions/npm/npm.properties
*1): unfortunatly buggy with current node.js version

Related

Why is my custom MSBuild script not able to copy project references when invoked from Visual Studio?

I am trying to simplify the deployment for one of our web projects by supplying an installer that takes care of everything the application needs to be initialized. I've chosen the WiX toolset for this and created a custom build script following this and partly this tutorial. To reproduce the problem I am facing, you can download the sources of the first tutorial link.
My general goal is to be able to create an installer directly from Visual Studio. The tutorial describes how to write a build script that generates the installer. Basically I want to invoke this script by clicking "Build" within Visual Studio (2012, if it matters).
First I've added a WiX project to the solution (relocate it to the setup-directory!). I've added all the setup-files and the required WiX references (UI, Util, IIS, SQL). By simply invoking the build now, WiX complains about an undefined var.publishDir variable. So I ran the supplied build script using the following command inside the VS developer console:
msbuild /t:Build;CreateInstaller;DeleteTmpFiles build_setup.build
First this gave me an error 9009 (command not found) when trying to invoke the heat tool for harvesting. I fixed this by replacing the "$(WixPath)heat" call with "$(WiX)\bin\heat". After that everything worked as desired, so I started hooking into the build process of the .wixproj file in order to call the build script from there. I did this by defining the following build targets (right below the item groups):
<Target Name="Build">
<MSBuild Projects="build_setup.build" Targets="Build;CreateInstaller" Properties="" />
</Target>
<Target Name="Rebuild">
<MSBuild Projects="build_setup.build" Targets="Build;CreateInstaller;DeleteTmpFiles" Properties="" />
</Target>
<Target Name="Clean">
<MSBuild Projects="build_setup.build" Targets="DeleteTmpFiles" Properties="" />
</Target>
Also I checked, if the installer project is excluded from solution-wide builds inside the build configuration manager for all configurations (but especially Release|AnyCPU since this is the desired configuration for deployment). For sake of clarity I've fixed both MSBuild calls within the build_setup.build script and added my desired platform:
<!-- Define default target with name 'Build' -->
<Target Name="Build">
<!-- Compile whole solution in release mode -->
<MSBuild Projects="..\MyWeb\MyWeb.sln" Targets="ReBuild"
Properties="Configuration=Release;Platform=Any CPU" />
</Target>
<!-- Define creating installer in another target -->
<Target Name="CreateInstaller">
<RemoveDir Directories="$(PublishF)" ContinueOnError="false" />
<MSBuild Projects="..\MyWeb\MyWeb\MyWeb.csproj" Targets="ResolveReferences;_CopyWebApplication"
Properties="OutDir=$(Publish)bin\;WebProjectOutputDir=$(Publish);Configuration=Release;Platform=AnyCPU" />
<!-- ... -->
</Target>
Now when I invoke the build by right-clicking the installer project and "Build", the build is successfully triggered from Visual Studio - exactly what I want.
The problem begins with adding project references: I've added a new library project (defined a simple class in there, referenced the library from the website and created an instance of the library class there). As soon as I try to build the project from Visual Studio now, I get an error that the referenced assembly cannot be copied from the publish-directory, because it does not exist:
Microsoft.WebApplication.targets(175,5): error MSB3030: Could not copy file "...\WixWebDeploy\Setup\publish\bin\MyWeb.Model.dll" because it was not found.
The strange thing is, that everything works fine, if I invoke the build script from the developer console! Also this only affects project references (the project is published using the targets ResolveReferences and _CopyWebApplication). NuGet packages or static library references are copied without any problems.
I appreciate any ideas that point me into the right direction to tackle down this issue. For example I am interested in the difference between calling msbuild from console or Visual Studio (if there is any...). Thanks in advance!
I finally figured out how to fix this issue. The solution was to use OutputPath argument instead of OutDir call a command line script from MSBuild:
<Target Name="Build">
<Exec Command="echo Building solution with '$(MSBuildToolsPath)\msbuild'..." />
<!--<MSBuild Projects="build_setup.build" Targets="CreateInstaller" Properties="Configuration=Release;Platform=AnyCPU" />-->
<Exec Command="call build_setup.cmd $(MSBuildToolsPath) CreateInstaller" />
</Target>
<Target Name="Rebuild">
<Exec Command="echo Building solution with '$(MSBuildToolsPath)\msbuild'..." />
<!--<MSBuild Projects="build_setup.build" Targets="Build;CreateInstaller" Properties="" />-->
<Exec Command="call build_setup.cmd $(MSBuildToolsPath) Build CreateInstaller" />
</Target>
<Target Name="Clean">
<Exec Command="echo Building solution with '$(MSBuildToolsPath)\msbuild'..." />
<!--<MSBuild Projects="build_setup.build" Targets="DeleteTmpFiles" Properties="" />-->
<Exec Command="call build_setup.cmd $(MSBuildToolsPath) DeleteTmpFiles" />
</Target>
From the build_setup.cmd I call MSBuild again:
if [%1] == [] (
echo "Please supply the msbuild directory as first argument!"
exit 10
) else (
set MSBUildDir=%1
)
if [%2] == [] (
echo "You have to supply at least one of the following arguments: Build, CreateInstaller, DeleteTmpFiles!"
exit 11
) else if [%3] == [] (
echo "%MSBUildDir%\msbuild /t:%2 setup.build"
call %MSBUildDir%\msbuild /t:%2 setup.build
exit 0
) else if [%4] == [] (
echo "%MSBUildDir%\msbuild /t:%2;%3 setup.build"
call %MSBUildDir%\msbuild /t:%2;%3 setup.build
exit 0
) else (
echo "%MSBUildDir%\msbuild /t:%2;%3;%4 setup.build"
call %MSBUildDir%\msbuild /t:%2;%3;%4 setup.build
exit 0
)
This seams kinda redundant and maybe somebody got a better suggestion.

specify ouput file name flash builder 4

This should be easy, but I can't find it. I want my .html and .swf files to be named something differently than the project name. Project name is foo, I want the outputs to be bar.html and bar.swf. Thanks.
Flextras was on the right track. You can't change the output filename (even using the "-output" compiler param) if you're compiling in Flash Builder. Not sure why.
The solution that has worked for me has been to use a bit of indirection:
use mxmlc to compile to ApplicationClass.swf
command line copy ApplicationClass.swf to YourCustomSwf.swf
command line run YourCustomSwf.swf
You can do this with either a simple (platform-dependent) build script, or with Flex Ant Tasks. I highly recommend the latter; it's easy to setup, integrates well with Flash Builder, and (as a mostly platform-independent solution) will work in a multi-team multi-OS environment. Here are the above steps as ant tasks that will perform the magic for you:
<project name="sample-build" default="run-your-swf">
<property file="${basedir}/your.properties.file"/>
<target name="compile-your-app">
<mxmlc file="${SOURCE_DIR}/ApplicationFile.mxml" compiler.debug="${IS_DEBUG}" incremental="true" failonerror="true">
<load-config filename="${DEFAULT_FLEX_CONFIG}"/>
<define name="CONFIG::DEBUG" value="${IS_DEBUG}"/>
<define name="CONFIG::FLASH_AUTHORING" value="${IS_FLASH_AUTHORING}"/>
<define name="CONFIG::IS_RELEASE" value="${IS_RELEASE}"/>
</mxmlc>
</target>
<target name="rename-your-swf" depends="compile-your-app">
<copy file="${OUTPUT_DIR}/feed/FeedComponent.swf" tofile="${OUTPUT_DIR}/YourNewSexyFilename.swf"/>
</target>
<target name="run-your-swf" depends="rename-your-swf">
<exec executable="${STANDALONE_FLASH_DEBUG_PLAYER}">
<arg line="${OUTPUT_DIR}/YourNewSexyFilename.swf"/>
</exec>
</target>
</project>
you need only define all ${VARIABLES} I've listed in "your.properties.file", like so:
FLASH_PLAYER_DEBUG=/Applications/Adobe Flash CS5/Players/Debug/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger
IS_DEBUG=true
(et cetera)
And anyway - what's in a name? A program by any other name, would be as awesome... B-)

Flex 3 css embed throws "Invalid Embed directive in stylesheet' error on linux

We have a flex application which compiles fine on windows box using mxmlc ant task but when we try to run the same build scripts on linux, it throws the 'Invalid Embed directive in stylesheet' error indicating it is not able to resolve the path to the image files.
Can someone pls. educate me on if there is a difference in the way the image files are looked up, in a CSS file, on windows vs linux.
Flex sdk version is 3.3. The same sdk is used on both windows and linux. Not sure if this has been fixed by any future 3.x sdks.
Thanks in advance.
We had similar problems preparing our project to build with ant task. We are developing under linux. In Flex builder there were no problems finding images - just added path. With ant task well had problems.
Solved problems by copying all needed images to temporary created src/images subdirectory. Then compiler was no more complaining. After build, ant is deleting my temporary directory.
I was running into this issue yesterday. The solution I used was to simply have ant temporarily copy the .css file to the root of the src directory so that the Embed path matches up during the compile process. Follow how the current .css file is copied to a "target.css" in the script below:
<target name="compile css">
<copy file="${css-dir}/${css}.css"
tofile="${resources}/target.css"/>
<java jar="${FLEX_HOME}/lib/mxmlc.jar"
fork="true"
failonerror="true"
>
<arg value="-debug=false"/>
<arg value="-optimize=true"/>
<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
<arg value="${resources}/target.css"/>
<arg value="-output=${css-output}/${css-swf}.swf"/>
<arg line="${libraryPathArgumentLine}"/>
<arg value="-static-link-runtime-shared-libraries=true"/>
</java>
<delete file="${resources}/target.css"/>
</target>

NAnt and ASP.NET Compiler

I have a build script running successfully, but I am having a hard time running anything after aspnet_compiler completes. I want to use robocopy to copy the project to another folder. If I put the copy task above the compile (as shown below) I get the message to the console, but if I place it after the compile it is not seen. Am I missing something? Do I need to check for a return code from the compiler to call tasks after its completion?
<target name="copy" depends="init">
<echo message="This is my message for robocopy..."/>
</target>
<target name="compile" depends="copy">
<exec program="${msbuild.exe}"
commandline='MySolution.sln /p:Configuration=${Configuration};OutDir="${build.dir}\\"' />
</target>
<target name="precompile-web" depends="compile">
<exec program="${aspnet_compiler.exe}"
commandline='-v /MyProj-p "${build.dir}"\_PublishedWebsites\MyProj.Web'
/>
And yes, when/if I move the copy task below precompile-web I change the depends="precompile-web" and the compile task depends to "init".
If I understand you correctly here, you want to:
Copy the files
Compile them using MSBuild
Precompile them for the web
Is that right? I would have thought you'd want to do it this way around:
Compile the files using MSBuild
Precompile them for the web
Copy the files somewhere else (for use by IIS, etc)
If my way is correct, then I'd guess you'd want your targets to reference each other like this?
<target name="compile-and-publish" depends="compile,precompile-web,copy" />
<target name="compile">
<exec program="${msbuild.exe}" commandline='MySolution.sln /p:Configuration=${Configuration};OutDir="${build.dir}\\"' />
</target>
<target name="precompile-web">
<exec program="${aspnet_compiler.exe}" commandline='-v /MyProj-p "${build.dir}"\_PublishedWebsites\MyProj.Web' />
</target>
<target name="copy" depends="init">
<echo message="This is my message for robocopy..."/>
</target>
This way, you're not pinning each of your targets down to relying upon other targets (for re-use) but you get the order that you need to achieve the job at hand.
Any good to you?

Custom Flex Ant build task

A beginner's question.
I'm building a .swf with Flex Ant.
To my .swf I link a file, target.as, which I generate from file source.txt with command
./tool.sh source.txt > target.as
How can I add what is described in the above sentence to my ant build process?
The exec task executes any external program:
<exec executable="${basedir}/tool.sh" dir="${basedir}" output="target.as">
<arg path="source.txt"/>
</exec>
So if you use the mxmlc ant task to compile your swf, you can define your build task like this:
<target name="build">
<exec executable="${basedir}/tool.sh" dir="${basedir}" output="target.as">
<arg path="source.txt"/>
</exec>
<mxmlc ....>
...
</mxmlc>
</target>
To run that command in Ant use the exec task.
<exec executable="tool.sh" dir="toolshdir" output="target.as">
<arg value="source.txt" />
</exec>
http://livedocs.adobe.com/flex/3/html/anttasks_1.html
You may also want to use the Flex "mxmlc" task instead of calling it with exec. You can do a lot of configuration right within the XML if you'd prefer not to have to maintain the shell script.

Resources