How to derive a relative path using Ant - apache-flex

I'm using Ant and mxmlc to compile ActionScript classes and MXML into swfs, while maintaining the default organization of a Flex Builder (Flash Builder) project. Many of my ActionScript classes are in project subdirectories, so my project is organized like the following:
MyBigProject
-build-imports.xml
-build.xml
-bin-debug
--src
---flash
---app
----CoolWidget1.swf
---Main.swf
--test
-src
--flash
---app
----build-imports.xml
----build.xml
----CoolWidget1.as
--build-imports.xml
--build.xml
--Main.mxml
-test
This directory structure maintains the default directory structure of a Flash Builder project so I can perform push-button builds from the Flash Builder IDE. I've added the Ant build xml's to this project so I can also build from the command line. I'm trying to create portable ant build scripts that require the least changes to reuse in other projects. I have everything like I want except for deriving relative paths.
The build-imports.xml file at the root of the project contains the following:
<project name="project.root.imports">
<dirname property="project.root.dir" file="${ant.file.project.root.imports}"/>
</project>
While the sub project folders contain build-imports.xml with the following:
<project name="MyBigProject.src.flash.app.imports">
<import file="../build-imports.xml" />
</project>
Notice that sub project build-imports.xml walks up the directory hiearchy till it gets to the root build-imports.xml, and there I set the project.root.dir.
I can then use the ${project.root.dir}/bin-debug to specify where to place my binaries. The only problem I have, is I do not know how to create the same directory structure as what lies under my src folder. I need to be able to derive a relative path or perform some string manipulation to create new directorys.
Considering the above information, how do I take a known path like:
${project.root.dir}/src/app
and derive a directory path like:
${project.root.dir}/bin-debug/app
I've found some information about the Ant-contribu propertyregex task, which would allow some string manipulation, but I'm hoping there is an Ant guru out there that can point to a simple solution. I believe it's highly likely as an Ant novice, I'm simply overlooking the obvious.

My build files have evolved a bit since I posted, but I've resolved the problem. I believe the following would work correctly in the basic setup previously described:
Add this to the default target in the sub project's build.xml
<path id="build.path">
<pathelement location="." />
</path>
<pathconvert property="build.dir" refid="build.path">
<map from="${project.root.dir}" to="${project.root.dir}/bin-debug"/>
</pathconvert>

Related

VS2013 Publish using WebDeploy isn't transforming additional files

I've build simple WebAPI project and not i'm trying to publish it using Visual Studio 2013 build in Publish mechanism (BUILD>Publish)
I've pick Web Deploy as publish method, got everything working, except transform files.
I have Web.config and Settings.config and two transforms for each.
When I do standard build on my project inside bin folder I see single Web.config and Settings.config with transform applied, but when I do publish instead of transformed Settings.config file I see one without transforms applied.
I't looks like publish mechanism inside Visual Studio is only transforming Web.config and it skips additional files.
Below is part of my csproj that is responsible for applying transforms:
<Target Name="AfterBuild">
<TransformXml Condition="Exists('Settings.$(Configuration).config')" Source="Settings.config" Destination="$(OutputPath)Settings.config" Transform="Settings.$(Configuration).config" />
<TransformXml Condition="Exists('Web.$(Configuration).config')" Source="Web.config" Destination="$(OutputPath)Web.config" Transform="Web.$(Configuration).config" />
</Target>
My question is how should I setup my publish profile so instead of copying clean Settings.config it will apply correct transform and publish it.
EDIT:
I've managed to find one thing that might help solving this. If I add UseMsdeployExe to pubxml I can see in Output that my Settings.config is transformed and saved to bin folder, but then later is it overridden by original file.
my AfterBuild target is called correctly, but after it I can see in output those lines:
2> Copying all files to temporary location below for package/publish:
2>obj\Debug\Package\PackageTmp.
2> Copying bin\Api.dll to obj\Debug\Package\PackageTmp\bin\Api.dll.
2> Copying Settings.config to obj\Debug\Package\PackageTmp\Settings.config.
Use SlowCheetah to transform the files, it will handle the deployment for you.
https://www.nuget.org/packages/SlowCheetah

MSDeploy Package has Missing Files

I'm using MSBuild to build a web application project and adding parameters to create the package file. All of that is good. I get two folders in the _PublishedWebSites output:
AppName
AppName_Package
In the ApplicationName folder, the entire site is there and I can simply copy this folder over to the website and it will run.
In the Package folder I've got the expected 5 files:
AppName.deploy.cmd
AppName.-readme.txt
AppName.SetParameters.xml
AppName.SourceManifest.xml
AppName.zip
When deploying the package however, the web application dll (AppName.dll) is missing, as are a few other important referenced dependencies.
Inspecting the package itself does reveal that the files are in fact missing from the web applications bin directory.
This is very odd, considering the files are all in the root AppName folder, but not in the package found in AppName_Package folder.
The only MSDeploy related modification I've made is that I am overriding the CopyAllFilesToSingleFolderForPackageDependsOn target to copy in some handlers from a library project, and this all works nicely.
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="..\Libraries\CodeLibrary1\**\*.ashx" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>$(ProjectDir)%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
So, I'm not able to determine why the web application's DLL, and only a few other (referenced)DLLs are removed from the bin directory during the package creation process (but not all - maybe 3%).
Any ideas what I should be looking for in the log file?
EDIT: (Response to Sayed):
I truly appreciate you answering my post. Unfortunately I’m not sure we are on the same page. Like I said, I might not have explained my problem well enough to actually clue others in on exactly what my issue is. Let me try once more to clarify
Getting external files copied into my web application was not the problem. I understand that scanning over my post and seeing the all too common “CopyAllFilesToSingleFolderForPackageDependsOn” element set off a few red flags, alarms, bells and whisles. . It seems to be a common thing people are struggling with, and as you point out, there have been some issues with it being executed. That worked OK for me.
My problem has more to do with project referenced DLLs, AND most importantly the application DLL itself not being copied.
More tweaking around today has revealed something I was not aware of. For instance:
Kicking off a Build on TFS outputs a couple things:
The source from TFS is output to the Source Directory (SourceDir)
This only contains the output what is checked into TFS
This does not include project or file references, only what is committed in TFS
The output of the build is into two folders
Binaries (includes project and file references)
Sources (only what is included/committed in TFS)
Inside Binaries I find the _publishedWebsites folder, as well as all project and file references, while inside Sources there are just the files that are checked into TFS.
My problem, or confusion, was thinking that when I pass in the following parameters to MSBuild Arguments, it would take the output from the build (_PublishedWebsites) and use those files to create the package. It does not do that.
The actual process builds a package based on the files in the SOURCES folder. So, here is my dilemma/confusion, because I did not commit my application dll into source, it was not being included in the package, and therefore was not being sent off to the test site on the test server.
/p:DeployOnBuild=True /p:DeployTarget=MsDeployPublish /p:CreatePackageOnPublish=True /p:MSDeployPublishMethod=RemoteAgent /p:MSDeployServiceUrl=http://<mytestsite> /p:DeployIisAppPath="<AppName>" /p:UserName=<domain\user> /p:Password=<mypassword> /p:SkipExtraFilesOnServer=false /p:AllowUntrustedCertificate=True
To wrap this up, once I “checkout for edit” my application DLL on my dev machine, and them compile the solution, and finally commit the application DLL to source control, then it is included in the package because it is included as just another source item.
So, I guess this becomes my fault for not understanding how to get the output of the TFS BUILD into the sources folder, and get that included into the package used by msdeploy.
There is probably something very fundamental that I missed or just skimmed over - and not understood, that the package creation is from the Sources folder and not the _PublishedWebsites folder. Nor do I understand how to get the MSBuild compiled application dll, and project referenced dlls, into my package – replacing the committed source items in source control.
I hope this isn’t a complete waste of your time because I missed a
source=<some-parameter>
somewhere.
I appreciate it you can direct me to any existing sources out that already explain this to where I should be able to get my head around it and get this working. Or if it’s so easy to just tell me here.
The issue here is that the CopyAllFilesToSingleFolderForPackage target itself is not getting called from the VS2012 targets. We made a lot of changes and this may be a regression on our side. I will look into this to see if there is anything that we can do. Fortunately it should be pretty straight forward to update this to get the behavior that you are looking for. Instead of using CopyAllFilesToSingleFolderForPackageDependsOn you should be able to use PipelineCollectFilesPhaseDependsOn as an alternative. You should be able to change what you have above to
<PropertyGroup>
<PipelineCollectFilesPhaseDependsOn>
CustomCollectFiles;
$(PipelineCollectFilesPhaseDependsOn);
</PipelineCollectFilesPhaseDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<Message Text="Inside of CustomCollectFiles" Importance="high"/>
<ItemGroup>
<_CustomFiles Include="C:\Temp\_NET\WAP-AfterPublish\MvcApplication1\additional files\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>additional files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
I just tried this for both VS2012 as well as VS2010 so this seems like a better to solution then the CopyAllFilesToSingleFolderForPackageDependsOn approach. Can you try that out and let me know what you find out?

Compiling flex modules into swf with other mxml files in ant

I have a huge project with many mxml and as files and am trying to compile them all into one working swf file using ant. However, I'm having trouble compiling main.swf correctly in ant.
It doesn't seem to be pulling in the necessary modules, all of which are located in separate folders within the main src folder.
It will compile without error, but when I open the swf file, there is no content -- just a shell. However, if I compile using flex builder 3's compile button, it will create the swf correctly -- content and all.
Even when using a simple mxmlc command, it throws an error for any file associated with the modules saying there is an unknown type (meaning it's not pulling in the modules).
Is there a special way that modules should be dealt with when trying to compile them into a main.swf file using ant?
Did you include a library-path element in your Ant build file?
e.g.
<target ...>
<mxmlc output="...../file.swf"
....
file=".../main.mxml">
<library-path dir="..../" append="true">
<include name="...../someModule.swc"/>

How to execute an Ant task only when source files have been modified?

There must be an easy way to do this. I build a Flex app using ant that depends on a SWC library, which works fine except that it rebuilds the library whether it needs to or not. How do I tell ant to only run the task if any of the sources files of the library (*.as, *.mxml) are newer than the SWC?
I've looked at <dependset> but it only seems to delete files, not determine whether a task should be run or not. <depend> seems to expect a one-to-one relationship between the source and target files rather than a one-to-many relationship -- I have many input files and one output file, but no intermediate object files.
Thanks a lot,
Alex
You may use the Ant uptodate task to create a property, and execute your other target only if that property is set.
I don't know much about flex, but you probably want something like this:
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" default="compile">
<target name="checkforchanges">
<uptodate property="nochanges">
<srcfiles dir="." includes="**/*.as"/>
<srcfiles dir="." includes="**/*.mxml"/>
<mapper to="applicaton.flex"/>
</uptodate>
</target>
<target name="compile" depends="checkforchanges" unless="nochanges">
...
</target>
</project>
The OutOfDate task from the ant contrib library is IMO much cleaner than the Ant uptodate option. The reason is that you have to define additional targets just to set the property.
The solution with Ant contrib (from their example page):
<outofdate>
<sourcefiles>
<pathelement path="build.xml"/>
<fileset dir="${lib.dir}"/>
</sourcefiles>
<targetfiles path="${jrun.file}"/>
<sequential>
<mkdir dir="${build.bin.dir}"/>
<echo file="${jrun.file}" message="java -cp ${jrun.path} $*"/>
<chmod file="${jrun.file}" perm="ugo+rx"/>
</sequential>
</outofdate>
Everything is kept nicely inside one single target.

How do I create a jar file, which includes xml and html files?

I am trying to create a jar file which includes some class and java files needed, but I also would like to include some extra xml, xsl, html, txt (README) files.
I am using Eclipse on Windows XP.
Is there an easy way for me to set up a directory structure and package all my files into a jar?
Add the files to a source folder and they can be included in the jar.
One common way is to have, at the root of your project, a src folder. Within that, folders for java files, and others. something like:
src/
css/
java/
html/
images/
Then you can make each of those subfolders a source folder (Right click, Use as Source Folder) and they should be available to add to the jar.
A .jar is nothing but a ZIP archive, so you can use any program capable of creating ZIPs. Just make sure that you include the manifest and all the class files.
I just added all the files into my Eclipse project (including the txt, html, xml, etc files).
Then I used Eclipse to File->Export->Jar File->Next
Check the "Export Java source files and resources" box.
Done.
If you're using Ant, you can use the jar task (see the examples section for how to include/exclude certain files, etc.)
If you move to an ANT (or Maven, for you Maven fans) then you can automate the Jar building very nicely, and also use it outside of Eclipse (e.g., in an automated build environment). All you need to do is copy the files from your src, jsp, foobar and resources locations into a build staging folder, then Jar the resulting files using ANT's Jar task.
<target name="makejar" depends="compile, copyfiles">
<jar destfile="${jars.dir}/myjarfile.jar" index="true" basedir="${build.dir}" />
</target>
One thing I look down on is including non-source (except package.html files for Javadoc) within the src folder. If you feel you have to do this to achieve something, then you are doing it wrong.

Resources