views:

93

answers:

1

Hello,

I am coming up on the end stages of an Asp.Net MVC 1.0 project in VS2008 / Framework 3.5, and trying to do some performance optimizations. In my project, I have a few different "themes" that are used, depending on the role of the logged in user. My themes folder structure is like so...

\Themes
    \Theme1
        \Css
            \Folder1
                \CssFile1.css
                \CssFile2.css
            \Folder2
                \CssFile1.css
                \CssFile2.css
        \Images
            <Images go here>
     \Theme2
        \Css
            \Folder1
                \CssFile1.css
                \CssFile2.css
            \Folder2
                \CssFile1.css
                \CssFile2.css
        \Images
            <Images go here>

As new customers come on board, new themes will be added to this folder structure.

I am using the Yahoo! UI Library: YUI Compressor for .Net (which is really cool) to minify and merge my css (and js) files.

I followed the example at http://yuicompressor.codeplex.com/wikipage?title=Sample%20MSBuild.xml%20File&amp;ProjectName=yuicompressor to run an MSBuild script via a post-build event to do the minify/merge tasks.

Everything works great, except that when I use something like <CssFiles Include="..\Themes\**\*.css" /> in my ItemGroup to specify where to get the css files, all css files from every theme are merged into one file, like this...

\Themes
        \SylesSheetFinal.css

What I want instead is to merge only the css under the themes, creating one css file for each...

\Themes
        \Theme1
            \StyleSheetFinal1.css
         \Theme2
            \StyleSheetFinal2.css

I am really new to MSBuild. Does anyone know how I can modify the sample to automatically walk over each of the theme folders and create a minified/merged stylesheet for each? The themes can be added or removed quite often, so I don't want to have to manually include each theme path to my ItemGroup. Instead, I want the MSBuild script to walk the subfolders underneath the Themes root automatically, regardless of the number of folders.

Thanks!

+2  A: 

What you are trying to do can be accomplished with batching. Batching is the process of executing a specific task (or target) once for each unique batch. There are two types of batching; Task Batching and Target Batching. Task batching is the most common and what I think you need, based on the info provided here. Batching can be kind of confusing, but it is not too bad once you get a grasp on it.

Batching always involves the %() operator. Here is an example of Task Batching.

<Project ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;
  <!-- Batching01.proj -->
  <ItemGroup>
    <Files Include="src\Src01.cs"/>
    <Files Include="src\Src02.cs"/>
    <Files Include="src\Src03.cs"/>
    <Files Include="src\Src04.cs"/>
  </ItemGroup>

  <Target Name="Demo">
    <!-- Not batched, i.e. Files is flattened and sent to the Message task -->
    <Message Text="Files: @(Files)"/>

    <Message Text="================" Importance="high" />

    <Message Text="Filename: %(Files.Filename)" Importance="high" />
  </Target>
</Project>

The output would be:

  Files: src\Src01.cs;src\Src02.cs;src\Src03.cs;src\Src04.cs
  ================
  Filename: Src01
  Filename: Src02
  Filename: Src03
  Filename: Src04

It is too tough to fully describe batching in this post, but I've put together some really great resources available online at http://sedotech.com/Resources#Batching.

Sayed Ibrahim Hashimi
As I mentioned in the post, I need to loop over an arbitrary number of subfolders without knowing how many exist. Your sample (and afik batching in general) requires me to know the list of folders beforehand.
racingcow
From the link provided you'll find this blog post http://sedodream.com/2006/08/15/MSBuildBatching.aspx please read it.
Sayed Ibrahim Hashimi