Brian Ball
Brian Ball

Reputation: 12606

Missing dll when trying to compile in two different versions of the framework in one build command

I have the following proj file:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{4B942FFC-22E5-486B-A3D7-D5EDFFF016F8}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Args</RootNamespace>
    <AssemblyName>Args</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <SccProjectName>Svn</SccProjectName>
    <SccLocalPath>Svn</SccLocalPath>
    <SccAuxPath>Svn</SccAuxPath>
    <SccProvider>SubversionScc</SccProvider>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <Framework>NET40</Framework>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release35|AnyCPU'">
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release3.5\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Args.cs" />
    <Compile Include="ArgumentDefinition.cs" />
    <Compile Include="ArgumentParser.cs" />
    <Compile Include="DefaultModelBinder.cs" />
    <Compile Include="IArgumentParser.cs" />
    <Compile Include="IModelBinder.cs" />
    <Compile Include="InternalExtenstions.cs" />
    <Compile Include="ModelBinders.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>-->
  <Target Name="AfterBuild">
    <MSBuild Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'"
     Projects="$(MSBuildProjectFile)"    
     Properties="Configuration=Release35" />
  </Target>
</Project>

This is my expected result when I compile the project in Release|AnyCPU:

I get this result when I Build the project; however, when I Rebuild the project, the same is true with the exception that the dll in the bin\Release directory is missing. The other 3 files (pdb in Release and dll and pdb in Release3.5) are still there and have the correct modified date.

Any help would greatly appreciated.

Edit: After some help, it looks like it works fine when I run MSBuild from the command line, but when I am running the build through Visual Studio, that is when I get the problem I described above.

Edit2: Verbose output from Visual Studio with Rebuild command in release mode. I was only able to post "Normal" output, and not "Detailed" or "Diagnostics" due to the length. I did look through those, and I didn't see any steps for deleting Args.dll from the regular release directory AFTER it had been compiled and copied from obj to bin (there was a delete step before the compile, but I would expect that).

------ Rebuild All started: Project: Args, Configuration: Release Any CPU ------
Build started 2/15/2011 8:23:57 AM.
CoreClean:
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\bin\Release\Args.dll".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\bin\Release\Args.pdb".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release\Args.Properties.Resources.resources".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release\GenerateResource.read.1.tlog".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release\GenerateResource.write.1.tlog".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release\Args.dll".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release\Args.pdb".
CoreResGen:
  "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\resgen.exe" /useSourcePath /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" /compile Properties\Resources.resx,obj\Release\Args.Properties.Resources.resources
  Processing resource file "Properties\Resources.resx" into "obj\Release\Args.Properties.Resources.resources".
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
  C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" /debug:pdbonly /filealign:512 /optimize+ /out:obj\Release\Args.dll /resource:obj\Release\Args.Properties.Resources.resources /target:library Args.cs ArgumentDefinition.cs ArgumentParser.cs Configuration.cs IInitializeModelBindingStrategy.cs ModelBindingStrategy.cs DefaultModelBinder.cs IArgsTypeConverter.cs IArgumentParser.cs IModelBinder.cs InternalExtenstions.cs InvalidArgsFormatException.cs InvalidModelDefinitionException.cs LambdaArgsTypeConverter.cs ModelBinders.cs Properties\AssemblyInfo.cs Properties\Resources.Designer.cs "C:\Users\Brian\AppData\Local\Temp\.NETFramework,Version=v4.0.AssemblyAttributes.cs"
CopyFilesToOutputDirectory:
  Copying file from "obj\Release\Args.dll" to "bin\Release\Args.dll".
  Args -> C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\bin\Release\Args.dll
  Copying file from "obj\Release\Args.pdb" to "bin\Release\Args.pdb".
CoreClean:
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\bin\Release3.5\Args.dll".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\bin\Release3.5\Args.pdb".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release35\Args.Properties.Resources.resources".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release35\ResGen.read.1.tlog".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release35\ResGen.write.1.tlog".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release35\Args.dll".
  Deleting file "C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\obj\Release35\Args.pdb".
CoreResGen:
  C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\x64\Tracker.exe @"C:\Users\Brian\AppData\Local\Temp\e35fa3c4055b4fd18515148e01c79912.tmp"  /c "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\ResGen.exe" /useSourcePath /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /compile Properties\Resources.resx,obj\Release35\Args.Properties.Resources.resources 
CoreCompile:
  C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /debug:pdbonly /filealign:512 /optimize+ /out:obj\Release35\Args.dll /resource:obj\Release35\Args.Properties.Resources.resources /target:library Args.cs ArgumentDefinition.cs ArgumentParser.cs Configuration.cs IInitializeModelBindingStrategy.cs ModelBindingStrategy.cs DefaultModelBinder.cs IArgsTypeConverter.cs IArgumentParser.cs IModelBinder.cs InternalExtenstions.cs InvalidArgsFormatException.cs InvalidModelDefinitionException.cs LambdaArgsTypeConverter.cs ModelBinders.cs Properties\AssemblyInfo.cs Properties\Resources.Designer.cs
CopyFilesToOutputDirectory:
  Copying file from "obj\Release35\Args.dll" to "bin\Release3.5\Args.dll".
  Args -> C:\Users\Brian\Documents\Visual Studio 2010\Projects\Args\Args\bin\Release3.5\Args.dll
  Copying file from "obj\Release35\Args.pdb" to "bin\Release3.5\Args.pdb".

Build succeeded.

Time Elapsed 00:00:00.98
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

Upvotes: 2

Views: 4551

Answers (3)

Tuomas Hietanen
Tuomas Hietanen

Reputation: 5321

Why

<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> 

is under main PropertyGroup and not just under conditions <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> and <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> ?

Hmmm... What happens if you add a command like

<Exec Command="attrib +r $(TargetPath)"/>

to AfterBuild, PreBuildEvent or BeforeBuild ? (Where TargetPath should be the dll file...)

Upvotes: 3

Sergio Rykov
Sergio Rykov

Reputation: 4286

Couldn't reproduce your issue. I used both MSbuild.exe from framework 3.5 and 4.0 in mode

MSbuild.exe yourproject.csproj /p:Configuration=Release /t:Build
MSbuild.exe yourproject.csproj /p:Configuration=Release /t:Rebuild

The only thing I can recommend is to call in verbose mode with flag /v:diag.

And try disable calling AfterBuild target.

EDIT: Do you really need to compile both versions in IDE?

If not I can recommend to disable building inside IDE and leave it to the build script:

  <Target Name="AfterBuild"
          Condition="'$(BuildingInsideVisualStudio)'!='true'" >
    <MSBuild Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'"
     Projects="$(MSBuildProjectFile)"    
     Targets="Clean;Build"
     Properties="Configuration=Release35" />
  </Target>

EDIT: Try ProcMon with filter "Process Name is devenv.exe" and see file IO activity for bin\Release\Args.dll during Rebuild.

Try search diagnostic output in VS for bin\Release\Args.dll. You will see every move/rename/delete action with that file.

Diagnostic log shows that everything should be OK:

Task "Copy"
  Copying file from "obj\Release\Args.dll" to "bin\Release\Args.dll".
Done executing task "Copy".
Task "Message"
  Args -> C:\Users\Brian\Documents\Visual Studio     2010\Projects\Args\Args\bin\Release\Args.dll
Done executing task "Message".

The log shows that there is no external interference from other tools. Even with full data I couldn't reproduce your issue.

To build both configurations from VS I can suggest to create additional Targets file in the Args directory named BuildArgs.csproj and add it to VS sln:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"     xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <BuildingProject>$(MSBuildProjectDirectory)\Args.csproj</BuildingProject>
  </PropertyGroup>
  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
     <BuildConfigurations Include="Release">
        <Visible>False</Visible>
     </BuildConfigurations>    
     <BuildConfigurations Include="Release35">
        <Visible>False</Visible>
     </BuildConfigurations>
  </ItemGroup>
  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release35|AnyCPU'">
     <BuildConfigurations Include="Release35">
        <Visible>False</Visible>
     </BuildConfigurations>
  </ItemGroup>
  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
     <BuildConfigurations Include="Debug">
        <Visible>False</Visible>
     </BuildConfigurations>    
  </ItemGroup>

  <Target Name="Build"
          Condition="'@(BuildConfigurations)'!=''"
          Inputs="%(BuildConfigurations.Identity)"
          Outputs="_Non_Existent_Item_To_Batch_">
    <Message Text="Building Configuration %(BuildConfigurations.Identity)" Importance="high" />
    <MSBuild 
        Targets="Build" 
        Projects="$(BuildingProject)" 
        Properties="Configuration=%(BuildConfigurations.Identity)" />
  </Target>

  <Target Name="Rebuild"
          Condition="'@(BuildConfigurations)'!=''"
          Inputs="%(BuildConfigurations.Identity)"
          Outputs="_Non_Existent_Item_To_Batch_">
    <Message Text="Rebuilding Configuration %(BuildConfigurations.Identity)" Importance="high" />
    <MSBuild 
        Targets="Rebuild" 
        Projects="$(BuildingProject)" 
        Properties="Configuration=%(BuildConfigurations.Identity)" />
  </Target>

  <Target Name="Clean"
          Condition="'@(BuildConfigurations)'!=''"
          Inputs="%(BuildConfigurations.Identity)"
          Outputs="_Non_Existent_Item_To_Batch_">
    <Message Text="Cleaning Configuration %(BuildConfigurations.Identity)"     Importance="high" />
    <MSBuild 
        Targets="Clean" 
        Projects="$(BuildingProject)" 
        Properties="Configuration=%(BuildConfigurations.Identity)" />
  </Target>
</Project>

It will responce on every VS build command. You can reduce it just to build only Release35 configuration when building Configuration=Release in VS. That kind of script is absolutely universal for building any project.

Upvotes: 1

Benjamin Baumann
Benjamin Baumann

Reputation: 4065

I'm pretty sure it's because you don't pass your target property to your AfterBuild call i.e. when you rebuild your solution in Release it does the following :

  1. Rebuild - Release (BeforeClean, Clean, AfterClean,BeforeBuild,Build,AfterBuild)
  2. Build - Release35

Unfortunately it's hard to get the target requested (by command line or VS). If your build does not take too much time I would recommend to always pass the target Rebuild (or Clean;Build) :

<Target Name="AfterBuild">
  <MSBuild Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'"
   Projects="$(MSBuildProjectFile)"
   Targets="Clean;Build"
   Properties="Configuration=Release35" />
</Target>

Upvotes: 1

Related Questions