SixPairs

February 24, 2011

Assembly Reference Resolver

Filed under: MSBuild — Ceyhun Ciper @ 16:39

Programmatically Resolve Assembly Name to Full Path

Sometimes I need to turn an assembly name like “system.xml” or “system.xml,version=2.0” into a path to the actual file for that assembly. This is a tricky problem considering the assembly name might be for a product installed in Program Files or elsewhere. So I posted an “Assembly Reference Resolver” package to the Visual Studio Gallery.

image

image

February 7, 2011

Solution File Explorer

Filed under: DSL, MSBuild — Ceyhun Ciper @ 17:53

Any software house has dozens of Visual Studio solutions somewhere on the network. Some of them are quite old, but still in use. Some of them are not and they are not being used. Some of them need to be upgraded; you need to know which ones without opening them individually (which, by the way, will force you to upgrade them).

Here is an .sln file explorer that I uploaded to the Visual Studio Gallery:

Preview

September 10, 2010

MSBuild T4 Templates

Filed under: MSBuild — Ceyhun Ciper @ 20:42

 

Frequently I find myself copying and modifying MSBuild projects; a better approach is to create a T4 template for that so that the boilerplate code is generated as well as some standards are applied. One of the things that I need is the generation of some documentation files (one readme file and one todo list) and also the self-documentation of the project itself (that is, the project should document its structure while running so that I can audit and troubleshoot complex MSBuild files).

Here is one of the MSBuild templates that I built that creates startup documentation as well as self-documentation:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".proj" #>
<?xml version="1.0" encoding="utf-8"?>
<Project InitialTargets="Init" DefaultTargets="All" ToolsVersion="4.0"
         xmlns="
http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <_IncludeFile>Ciper.targets</_IncludeFile>
    <MSBUILDINCLUDE Condition="Exists($(_IncludeFile))">
       $(MSBuildThisFileDirectory)
   
</MSBUILDINCLUDE>
    <MSBUILDINCLUDE Condition=" ‘$(MSBUILDINCLUDE)’ == ” ">
$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), $(_IncludeFile)))
    </MSBUILDINCLUDE>
  </PropertyGroup>

  <Target Name="Init">
    <Error Text="MSBUILDINCLUDE environment variable is not set."
           Condition=" ‘$(MSBUILDINCLUDE)’ == ” " />
  </Target>

  <PropertyGroup>
    <ToDo>
      ref Edit($(msbuildprojectfile))
      ref Home(ReadMe.dgml)
    </ToDo>
    <ReadMe>
      <![CDATA[
        shape none{Edit;To Do}
        ref To Do(ToDo.dgml)
        ref Edit($(msbuildprojectfile))
      ]]>
    </ReadMe>
  </PropertyGroup>

  <Import Project="$(MSBUILDINCLUDE)$(_IncludeFile)"
          Condition="Exists(‘$(MSBUILDINCLUDE)$(_IncludeFile)’)"/>

  <ItemGroup>
    <Inputs Include="$(msbuildprojectfile)"/>
    <Outputs Include="ToDo.dgml;ReadMe.dgml" />
  </ItemGroup>

  <Target Name="All" Inputs="@(Inputs)" Outputs="@(Outputs)">
    <ToDo Data="$(ToDo)">
      <Output TaskParameter="DgmlPath" PropertyName="dgml" />
    </ToDo>
    <Move SourceFiles="$(dgml)" DestinationFiles="ToDo.dgml" />

    <Dgml Graph="$(ReadMe)">
      <Output TaskParameter="DgmlPath" PropertyName="dgml" />
    </Dgml>
    <Move SourceFiles="$(dgml)" DestinationFiles="ReadMe.dgml" />

    <CallTarget Targets="ProjectDgml" />
  </Target>
</Project>

In order to use it all I have to do is copy the Ciper.targets file and the Makefile.tt template to a work folder, call TextTransform on Makefile.tt, set the environment variable and invoke msbuild. I get 3 documentation files: ToDo.dgml, ReadMe.dgml and Makefile.dgml. Here is the Makefile.dgml that documents the project’s structure:

image

Notice that I can edit the ToDo list and the ReadMe document inside the project itself; so everything is in one place.

September 9, 2010

MSBuild & DGML: Two underused tools, let alone together

Filed under: MSBuild — Ceyhun Ciper @ 22:12

 

All developers use MSBuild, albeit without knowing.

Most developers use DGML, from the architecture menu.

Very few of them use MSBuild in its own right.

Almost none of them use DGML in its own right.

And none of them use both.

And they spend their life inside Visual Studio.

And both tools are available to them at all times.

Go figure.

Auditing MSBuild Projects with DGML

Filed under: MSBuild — Ceyhun Ciper @ 19:48
DGML ≡ Directed Graph Markup Language

 

In my previous post I had described a tool to visualize MSBuild projects with DGML and I had taken the following example:

<Project InitialTargets="Init" DefaultTargets="All" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="Init">
    <Error Text="MSBUILDINCLUDE environment variable is not set."
          
Condition=" ‘$(MSBUILDINCLUDE)’ == ” " />
  </Target>

  <Import Project="$(MSBUILDINCLUDE)Ciper.Targets"
          Condition="Exists(‘$(MSBUILDINCLUDE)Ciper.Targets’)"/>

  <PropertyGroup>
    <DestinationFolder>c:ceyhunbinscripts</DestinationFolder>
  </PropertyGroup>
  <ItemGroup>
    <SourceFiles Include="gawk.exe;dgml.bat;dgml.gawk;dgml_lowlevel.gawk;dgml_lib.gawk;dgml_print.gawk;tdl.gawk;tdl.bat" />
    <DgmlSources Include="ciper-family.txt;deployment.txt;design.txt;icons.txt;problems.txt;todo.txt;readme.txt" />
    <ToDoSources Include="requirements.txt;specifications.txt" />
    <GawkSources Include="datastructures.txt;dependencies.txt">
      <dgml>%(filename).dgml</dgml>
      <gawk>%(filename).gawk</gawk>
      <temp>%(filename).temp</temp>
    </GawkSources>
    <AllDependsOn Include="BuildGawk;BuildDgml;BuildToDo;CopyToBin;BuildDoc;BuildSyntax" />
  </ItemGroup>

  <Target Name="BuildGawk" Inputs="@(GawkSources)" Outputs="%(dgml)">
    <Exec Command="gawk.exe -f @(GawkSources->’%(gawk)’) @(GawkSources) > @(GawkSources->’%(temp)’)" />
    <Exec Command="dgml.bat @(GawkSources->’%(temp)’)" />
    <Delete Files="@(GawkSources->’%(temp)’)" />
  </Target>

  <Target Name="BuildDgml" Inputs="@(DgmlSources)" Outputs="%(filename).dgml">
    <Exec Command="dgml.bat @(DgmlSources)" />
  </Target>

  <Target Name="BuildToDo" Inputs="@(ToDoSources)" Outputs="%(filename).dgml" DependsOnTargets="BuildDgml">
    <Exec Command="tdl.bat @(ToDoSources)" />
  </Target>

  <Target Name="CopyToBin" Inputs="@(SourceFiles)" Outputs="$(DestinationFolder)%(filename)%(extension)" DependsOnTargets="BuildDgml;BuildToDo">
    <Message Text="@(SourceFiles) -> $(DestinationFolder)%(filename)%(extension)" />
    <Copy SourceFiles="@(SourceFiles)" DestinationFiles="$(DestinationFolder)%(filename)%(extension)" />
  </Target>

  <Target Name="BuildDoc" Inputs="dgml.txt" Outputs="dgml.pdf">
    <Exec Command="hlatex dgml.txt" />
  </Target>

  <Target Name="BuildSyntax" Inputs="dgmlsyntax.txt" Outputs="dgmlsyntax.dgml">
    <Exec Command="syntaxdiagrammer.bat dgmlsyntax.txt" />
  </Target>

  <Target Name="All" DependsOnTargets="@(AllDependsOn)">
    <CallTarget Targets="ProjectDgml" />
  </Target>
</Project>

Which is represented at a high-level as:

image

Now, I feel that something is not quite right with this build file, but I don’t know what; so I have to audit it, but I don’t want to go through the XML, even though it is quite small. I prefer to interpret the DGML output.

First off, the “BuildDoc” target builds the LaTex Developer documentation in LaTeX that is not even deployed, so I take it out:

image

In the same vein, the “BuildGawk” & “BuildSyntax” targets generate internal documentation graphs that are not deployed either, so I take them out:

image

I also know that all targets depend on “All” that does nothing but generate this DGML! So I take it out as well.

image

I am mainly interested in “CopyToBin” and I can see that none of the Text Files are among its inputs.

image

Why does “CopyToBin” depend on the “BuildToDo” & BuildDgml” targets? It shouldn’t:

image

So we discover that “CopyToBin” should not depend on any other target and also what its relevant inputs are:

image

And we fix the makefile accordingly…

image

Visualizing MSBuild projects with DGML

Filed under: MSBuild — Ceyhun Ciper @ 15:41
DGML ≡ Directed Graph Markup Language

 

In order to better understand what I am doing when I hand-craft my MSBuild projects, I have developed  a tool to automatically visualize them in DGML.

Here is a project that I am working on (actually it is a DGML generator written in Awk):

<Project InitialTargets="Init" DefaultTargets="All" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="Init">
    <Error Text="MSBUILDINCLUDE environment variable is not set." Condition=" ‘$(MSBUILDINCLUDE)’ == ” " />
  </Target>

  <Import Project="$(MSBUILDINCLUDE)Ciper.Targets" Condition="Exists(‘$(MSBUILDINCLUDE)Ciper.Targets’)"/>

  <PropertyGroup>
    <DestinationFolder>c:ceyhunbinscripts</DestinationFolder>
  </PropertyGroup>
  <ItemGroup>
    <SourceFiles Include="gawk.exe;dgml.bat;dgml.gawk;dgml_lowlevel.gawk;dgml_lib.gawk;dgml_print.gawk;tdl.gawk;tdl.bat" />
    <DgmlSources Include="ciper-family.txt;deployment.txt;design.txt;icons.txt;problems.txt;todo.txt;readme.txt" />
    <ToDoSources Include="requirements.txt;specifications.txt" />
    <GawkSources Include="datastructures.txt;dependencies.txt">
      <dgml>%(filename).dgml</dgml>
      <gawk>%(filename).gawk</gawk>
      <temp>%(filename).temp</temp>
    </GawkSources>
    <AllDependsOn Include="BuildGawk;BuildDgml;BuildToDo;CopyToBin;BuildDoc;BuildSyntax" />
  </ItemGroup>

  <Target Name="BuildGawk" Inputs="@(GawkSources)" Outputs="%(dgml)">
    <Exec Command="gawk.exe -f @(GawkSources->’%(gawk)’) @(GawkSources) > @(GawkSources->’%(temp)’)" />
    <Exec Command="dgml.bat @(GawkSources->’%(temp)’)" />
    <Delete Files="@(GawkSources->’%(temp)’)" />
  </Target>

  <Target Name="BuildDgml" Inputs="@(DgmlSources)" Outputs="%(filename).dgml">
    <Exec Command="dgml.bat @(DgmlSources)" />
  </Target>

  <Target Name="BuildToDo" Inputs="@(ToDoSources)" Outputs="%(filename).dgml" DependsOnTargets="BuildDgml">
    <Exec Command="tdl.bat @(ToDoSources)" />
  </Target>

  <Target Name="CopyToBin" Inputs="@(SourceFiles)" Outputs="$(DestinationFolder)%(filename)%(extension)" DependsOnTargets="BuildDgml;BuildToDo">
    <Message Text="@(SourceFiles) -> $(DestinationFolder)%(filename)%(extension)" />
    <Copy SourceFiles="@(SourceFiles)" DestinationFiles="$(DestinationFolder)%(filename)%(extension)" />
  </Target>

  <Target Name="BuildDoc" Inputs="dgml.txt" Outputs="dgml.pdf">
    <Exec Command="hlatex dgml.txt" />
  </Target>

  <Target Name="BuildSyntax" Inputs="dgmlsyntax.txt" Outputs="dgmlsyntax.dgml">
    <Exec Command="syntaxdiagrammer.bat dgmlsyntax.txt" />
  </Target>

  <Target Name="All" DependsOnTargets="@(AllDependsOn)">
    <CallTarget Targets="ProjectDgml" />
  </Target>
</Project>

I can see it more clearly in DGML:

image

 

Legend:

image Target

image Input

image Output

image Dynamic items

I can also expand and collapse groups to have a more or less detailed view of the project items:

image

 

image

I can change the orientation:

image

or the layout:

image

I can select just the targets to see the dependencies between them:

image

I can focus on a single target (CopyToBin) to see its inputs, outputs and dependencies:

image

image

I can filter out indirectly related nodes:

image

 

image

 

image

I can even view the dependency matrix:

image

image

Maybe only between targets?

image

Legend:

image Target

image Input

image Output

image Dynamic items

Create a free website or blog at WordPress.com.