0

I wrote a C# template for creating of the .Net extensions for AutoCAD. Before, for each AutoCAD version it is was necessary to point the individual referenses set, the output directory, the target .Net Framework Platform, etc. Exist many versions of AutoCAD: AutoCAD 2009, 2010, ..., 2015. Now my template do it instead of me. My csproj-file has the CAD_Year property:

<PropertyGroup>
  <CAD_Year>2013</CAD_Year>
  <Min_Year>2009</Min_Year>
  <Max_Year>2015</Max_Year>
</PropertyGroup>

When I change CAD_Year value (manually edit this option in the csproj-file) - all settings of my project do change too according target AutoCAD version. It works fine.

But I need to compile my code for all versions of AutoCAD always... It is inconvenient to change the CAD_Year every time for this... :(((

How can I create the cycle of compiling my project for the versions Min_Year, ..., Max_Year when I press the Rebuild Solution menu item?

Andrey Bushman
  • 11,712
  • 17
  • 87
  • 182
  • Which VS version shall it be? You're tagging multiple ones.. – stijn Mar 03 '15 at 08:23
  • Also you have two seperate requirements here: creating the 'cycle' and making it run. First is easy to do, second one is doable as well but are you sure you want to override standard behaviour? How will VS now know what the primary ouput file is? The project would be built multiple times, so an error would result in multiple duplicate error messages. Etc. Can't you not just build the cycle from the command line? – stijn Mar 03 '15 at 08:26
  • I use the VS 2013, but the `msbuild` works and into earlier versions too. I will test my template in the VS2005-2012 also after I solve this problem. – Andrey Bushman Mar 03 '15 at 08:26
  • That wont work since VS2005 does not use msbuild based project files – stijn Mar 03 '15 at 08:28
  • Primary output file is for version are pointed through the `CAD_Year` property. Error messages isn't a problem for me. I can find a problem source at this case. I didn't understand your last question. – Andrey Bushman Mar 03 '15 at 08:32
  • You are mistaken. VS 2005 uses the msbuild too (for C# as I see). – Andrey Bushman Mar 03 '15 at 08:36

2 Answers2

1

Thank you, @stijn. I will mark your answer as a solution. Here I create an "answer" for the code highlighting. My current code works:

  <!-- Redefine the CoreClean target, otherwise MSBuild will remove all results 
    of building except for the last. -->  
  <Target Name="CoreClean">
    <ItemGroup>
      <AllFiles Include="$(OutputPath)\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(AllFiles)" DestinationFolder="$(OutputPath)\temp" />
  </Target>

  <Target Name="BatchRebuild">
    <ItemGroup>
      <CADYearsItem Include="$(BuildFor)" />
    </ItemGroup>
    <Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year_Platform=%(CADYearsItem.Identity)" />

    <ItemGroup>
      <AllFilesBack Include="$(OutputPath)\temp\*.*" />
    </ItemGroup>
    <Move SourceFiles="@(AllFilesBack)" DestinationFolder="$(OutputPath)" />
    <!-- Doesn't work for Debug. The $(OutputPath)\temp\ will not removed. 
      But it work for Release.-->
    <RemoveDir Directories="$(OutputPath)\temp\" /> 
  </Target>

I see, the RemoveDir task doesn't work for the Debug for me, but it is not a big problem. Now my template is complete, and I will do refactoring of this. Thank you very much!

Andrey Bushman
  • 11,712
  • 17
  • 87
  • 182
0

If you add this to your project file:

<ItemGroup>
  <CADYears Include="2013;2014;2015"/>
</ItemGroup>

<Target Name="BatchRebuild">
  <Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year=%(CADYears.Identity)"/>
</Target>

and call

msbuild <path_to_projectfile> /t:BatchRebuild

on the commandline, it will build path_to_projectfile 3 times each with a different CAD_Year property.

To get this invoked by VS is trickier since you need to override the Rebuild target, but this for instance works for VS2013 (Actualrebuild target was copied from the Rebuild target in C:\Program Files (x86)\MSBuild\12.0\Bin\Microsoft.Common.CurrentVersion.targets):

<ItemGroup>
  <CADYears Include="2013;2014;2015"/>
</ItemGroup>

<Target Name="ActualRebuild"
        Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
        DependsOnTargets="$(RebuildDependsOn)"
        Returns="$(TargetPath)"/>

<Target Name="BatchRebuild">
  <Msbuild Projects="$(MsBuildThisFile)" Targets="ActualRebuild" Properties="CAD_Year=%(CADYears.Identity)"/>
</Target>

<Target Name="Rebuild">
  <Msbuild Projects="$(MsBuildThisFile)" Targets="BatchRebuild"/>
</Target>

Edit Since the template system in VS tries to copies ItemGroups it finds in the project root (which seems like a bug to me, or at the least a very annoying feature) you can work around that by using a property and converting it into an item when needed:

<PropertyGroup>
  <CADYears>2013;2014;2015<CADYears/>
</PropertyGroup>

<Target Name="BatchRebuild">
  <ItemGroup>
    <CADYearsItem Include="$(CADYears)"/>
  </ItemGroup>
  <Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year=%(CADYearsItem .Identity)"/>
</Target>

Note: in the project you posted in the link you are invoking the Rebuild target in the Afterbuild target. I didn't try it, but that will almost certainly lead to infinite recursion. So you should stick to a solution like posted above with a seperate target.

stijn
  • 34,664
  • 13
  • 111
  • 163
  • I get a problem for the ``. MSBuild interpret the 2013, 2014 and 2015 as the files names and try to find them. But their are not exist and I get an error when I try to create new project based on my template. – Andrey Bushman Mar 06 '15 at 08:16
  • What error? What template? The problem cannot just be MsBuild trying to find files named '2013' etc, else the above code wouldn't even run on my setup and it does just fine. Items can be files, but don't have to be. So the problem lies elsewhere, in code you haven't shown. Add it to your original question. – stijn Mar 06 '15 at 08:28
  • Thank you for answer. I will detailed describe on English my problem and put my commented settings files then. It will take some time. – Andrey Bushman Mar 06 '15 at 09:12
  • I wrote the description and attached the code here: https://yadi.sk/d/YNb6h5K5f5nHz . Read the Description.pdf, please. I appologize for my bad English, but I have a hope you will understand my ideas and text. Thank you, for your help, @stijn! – Andrey Bushman Mar 06 '15 at 14:11
  • Ok usually I don't do this (well I do, but I get paid for it:) but I respect the efort you put into it, so see updated answer. But note that normally you should post different questions for different issues: the problem with the template is only slightly related to this question. Oh and your English is more than adequate to make yourself understandable. – stijn Mar 07 '15 at 08:11
  • Thanks. I will be able to check it only on Tuesday. – Andrey Bushman Mar 07 '15 at 20:28
  • Oops, I see a problem... MSBuild delete some assemblyes after their compilation. It does this operation in the **CoreClean**. My Property: `2009x86;2009x64;2013;2015`. But compilation result for *2013* was removed by MS VS after its compilation (I read its log). How can I fix it? – Andrey Bushman Mar 10 '15 at 10:25
  • Similar way: you'll have to Override the `Clean` target (simliar to shown, to split in ActualClean etc) to only clean the output depending on the current value of CAD_Year. – stijn Mar 10 '15 at 15:20
  • I tried to locate the `` and `` before the `BatchRebuild` task definition in my `csproj`-file, but it doesn't help me. – Andrey Bushman Mar 10 '15 at 15:29
  • MSBuild removes previous results of batch compilation. :(((( – Andrey Bushman Mar 10 '15 at 15:30
  • `` should definitely work. At least it does here. But another, probably better possibility is making OutputPath dependent on the version you are building so that for each build the output dll/exe/whatever goes to seperate directories with the name of the build. Put this in a PropertyGroup somewhere before importing Microsoft.CSharp.targets: `bin\$(Configuration)$(CAD_Year)\` . Now Clean also still works properly (it only deletes for current CAD_Year. – stijn Mar 10 '15 at 16:21