Resolving another project's renamed assembly dependency - msbuild

I have a solution in which I needed to brand an assembly for a third-party client. This resulted in a class structure as follows:
Project1
References
MyBrandedAssembly.dll (namespace: MyAssembly)
Project2
References
Project1
When MsBuild built Project1, it could resolve the MyAssembly namespace to MyBrandedAssembly.dll:
Primary reference "MyAssembly".
Resolved file path is "SolutionPath\Binaries\MyBrandedAssembly.dll".
Reference found at search path location "{HintPathFromItem}".
But when building Project2, it could not resolve the second-order reference:
Dependency "MyAssembly".
Could not resolve this reference. Could not locate the assembly "MyAssembly".
Check to make sure the assembly exists on disk. If this reference is required by your
code, you may get compilation errors.
For SearchPath "SolutionPath\Project1\bin\Debug".
Considered "SolutionPath\Project1\bin\Debug\MyAssembly", but it didn't exist.
Why not? And how can I force it to?

You can add a pre-build event to your project csproj file to copy the dlls from the Project 1 output bin folder to the Project 2 bin folder. This will allow the assembly to be found by the assembly resolver.
Add this to your project2.csproj
<Target Name="BeforeBuild">
<Delete Files="$(ProjectDir)bin\$(Configuration)\MyBrandedAssembly.dll" />
<Copy SourceFiles="$(ProjectDir)..\<Project1>\bin\$(Configuration)\MyBrandedAssembly.dll" DestinationFolder="$(ProjectDir)bin\$(Configuration)\" />
</Target>

Related

Using ProjectReference for .vcxproj in .csproj failing the build with msbuild

I have c# project with .csproj extension, in this file I am referring a .vcxproj (C++). When I try to build the project with msbuild, the build fails with following error:
Program.cs(13,25): error CS0246: The type or namespace name 'CppLibrary' could not be found (are you missing a using di
rective or an assembly reference?) [C:\Work\CppTest\CSharp\CSharp.csproj]
Done Building Project "C:\Work\CppTest\CSharp\CSharp.csproj" (default targets) -- FAILED.
Done Building Project "C:\Work\CppTest\CppTest.sln" (default targets) -- FAILED.
How can we use .vcxproj in .csproj?

Does CMake offer a method to set the working directory for a given build system to use when running/debugging the project?

I have a project with the following structure:
project_name/CMakeLists.txt
project_name/src
project_name/resources
...
project_name-build/configuration_name/project_name.exe
I want my application to be run in the root project directory project_name so it can directly access resources.
Does CMake provide a method to specify this property, or will I have to manually set it in each build environment I use?
I've looked around in the documentation and haven't found anything other than the possibility of setting up a post-build event to run my project from the desired directory which is less than desirable. I also found that the working directory setting for Visual Studio is saved in a per-user file (.vcxproj.user) which I don't believe CMake generates (which points to the answer being probably no).
Since CMake 3.8, there is the VS_DEBUGGER_WORKING_DIRECTORY target property, which allows you to set the debugger working directory for a target in Visual Studio.
Usage example:
set_property(TARGET MyTarget PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
As drescherjm pointed out (in his comment on the question) CMake doesn't provide a method to directly set a working directory. However, CMake does provide indirect methods of doing so.
The path I think I'll take is to use the configure_file command to fill in a template .user file.
Here is an easier solution.
Paste this at the end of your cmake:
file( WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?> \
<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>")
It overwrites the default vcxproj.user file for the current project and specifies $(OutDir) for the Working Directory as desired for debugging. Make sure that $PROJECT_NAME is your project name.

How does the MSBuild CoreCompile Target Identify Reference Assemblies

Can anyone shed any light on how the CoreCompile task in TFS2010 (RC) Microsoft.TeamFoundation.Build targets generates the assembly references that are passed to csc.exe?
We are seeing references to both version 2.0 and 4.0 of System.Xml.dll (shown in bold below), however we are using the 'Specific Version: true' flag on the project assembly reference and there are no references to the 4.0 assembly in the btproj file:
C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /platform:x86 /errorreport:prompt /warn:4 /define:TRACE
/reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Configuration.dll
/reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
**/reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll**
/reference:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll
**/reference:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Xml.dll**
/reference:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll
/reference:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Web.Services.dll
Update: I've checked the output of the ResolveAssemblyReferences target (from Microsoft.Common.targets) and can see that only the assemblies referenced in the project (i.e. the 2.0 framework assemblies) are included in the item list '_ResolveAssemblyReferenceResolvedFiles':
ResolveAssemblyReferenceResolvedFiles:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Configuration.dll;
C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll;
C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll
However, the CoreCompile target still includes the 4.0 assemblies as detailed above.
Update 2: Ok, I've tracked this down to an obscure bug in the AddBizTalkHiddenReferences target in the BizTalk build scripts. This particular target attempts to add additional assemblies, including the ones that are duplicated above.
However, it uses the GetCORSystemDirectory from 'mscoree.dll' which returns the installation directory of the common language runtime (CLR) that is loaded into the process, in this case the 4.0 framework loaded into MSBuild; as a result, the helper doesn't think it has the System.Xml assembly referenced and adds it, hence the duplicate.
Reference assemblies are resolved by ResolveAssemblyReferences target in the file Windows\Microsoft.NET\Framework\$(Version)\Microsoft.Common.targets based on the Reference items defined in your project file.

MSBuild: Problems specifying platform for child builds

Is it possible to specify the target platform (x64, x86) when building a project?
I have a build task that looks as follows:
<MSBuild Projects="%(AgentProjectFiles.FullPath)" Properties="Architecture=x86;Configuration=$(Configuration);Optimize=$(Optimize);Platform=$(Platform);OutputPath=$(OutputDirectory)\Agent\;ReferencePath=$(ReferencePath);DebugSymbols=$(DebugSymbols);DebugType=none;" />
As you can probably tell, I've thrown everything possible I have seen online into the Properties attribute in the hope that it will work. You will notice that for the Architecture property I've set it to be x86 explicitly. the $(Platform) is also set to x86. I've tried a number of permutations, without success.
Unfortunately, it seems that no matter what gets put into these properties, my class libraries are x86, but my executables are x64.
I thought perhaps the problem could be that the build properties specified in the project file itself were causing MSBuild to ignore the ones I pass through from MSBuild, but after changing these to x86, I still have the same problem.
Any ideas?
In the declaration of the AgentProjectFiles item are you defining the Properties metadata. So does it look like:
<ItemGroup>
<AgentProjectFiles Include="something.proj">
<Properties>SOME VALUES HERE</Properties>
</AgentProjectFiles>
</ItemGroup>
If you have defined that then the properties passed into the Properties attribute of the MSBuild task are ignored. I've bloged about this MSBuild: Properties and AdditionalProperties Known Metadata.
Sayed Ibrahim Hashimi
My Book: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build

How do I set the Output directory for a C++ project built by msbuild?

I have a MSBuild .proj file that is compiling a mixture of C# and C++ projects.
The C# projects compile output (.exe/.dlls) to the OutputPath I specify, but when I specify OutputPath for the C++ projects (which calls vcbuild.exe), the OutputPath is ignored and instead goes into the directory specified in the Property Pages for the .vcproj.
Here's my MSBuild task:
<MSBuild Projects="$(SourceFolder)\$(NativeSolutionName)"
Targets="$(BuildTargets)"
Properties="Configuration=$(Configuration);PlatformName=Win32;OutputPath=$(ToolsOutputDir)">
</MSBuild>
How can I specify that the C++ output files should go to the same directory as the C# output files $(ToolsOutputDir)?
I was able to make this work by doing the following:
1) Installing the Microsoft SDC MSBuild Tasks Library
2) In the property pages for the C++ projects, setting the output directory to $(OutputPath).
3) Adding a SDC task to set the environment variable OutputPath before building the C++ projects via VCBuild:
<Microsoft.Sdc.Tasks.SetEnvironmentVariable Variable="OutputPath" Value="$(ToolsOutputDir)" Target="Process"/>
<!-- Build any CPP code x86 -->
<MSBuild Projects="$(SourceFolder)\$(NativeSolutionName)"
Targets="$(BuildTargets)"
Properties="Configuration=$(Configuration);PlatformName=Win32;OutputPath=$(ToolsOutputDir)">
</MSBuild>