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:
- The dll and pdb file for the project to be located in the bin\Release directory, compiled against the 4.0 framework.
- The dll and pdb file for the project to be located in the bin\Release3.5 directory, compiled against the 3.5 framework.
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 ==========
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...)
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 :
- Rebuild - Release (BeforeClean, Clean, AfterClean,BeforeBuild,Build,AfterBuild)
- 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>
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.
精彩评论