MS Build dual assemblies for x86 and x64 builds and TeamCity - msbuild

I've recently had a few issues when trying to run SQLLite powered in-memory repository mock (Repository pattern) with Fluent Nhibernate. When I ran the tests against a (TeamCity) build agent on Windows Server 2008 the tests were failing with unable to load System.Data.SQLite exceptions.
After some fiddling I remembered there was a x64 version of System.Data.SQLite in the downloaded SqlLite binaries. Dropping that next to unit tested assembly and running tests through NUnit UI worked and no longer threw any exceptions.
My question is: is it possible to tell the build something like: when compiling on x64 system, reference the binary from folder B and when on x86 system, from folder A? So a conditional reference include?
The only other option I can think of right now is to limit TeamCity build agents to be x64 and use a command line script build step to overwrite assembly in bin\Release folder in between build finishing ant unit tests running. Development environments are all x86 so that's the root of the issue.
Writing this there is one other option - but a messy one - modify the project file after svn build source is downloaded and before the build runs using a script.

References can be made conditional in your project file (I'm making up the details of the references below).
<Reference
Include="SQLLite"
Condition="'$(Platform)' == 'x64'">
<HintPath>PathTo/x64/SqlLite.dll"</HintPath>
</Reference>
<Reference
Include="SQLLite"
Condition="'$(Platform)' == 'Win32'">
<HintPath>PathTo/Win32/SqlLite.dll"</HintPath>
</Reference>

Related

Why does NuGet pack break with VS2019 build tools?

We have a number of .NET Framework projects with a "nuget pack MyProject.csproj" command in the post-build step. We have been using VS2010 (:O I know) until now, and it has been happily spitting out nupkg files.
We recently updated our build tools to the 2019 version (running the new version of varsall.bat before calling msbuild), and the "nuget pack" command now fails:
Error NU5012: Unable to find 'MyProject.dll'. Make sure the project has been built.
What I've tried:
Adding a "nuget spec" step before packing
Upgrading the nuget CLI executable to the latest version
Updating from packages.config to PackageReferences
This allows you to use MSBuild -t:pack. However, two issues:
When running this in the post-build step on my machine, it starts dozens of cmd & MSBuild processes and pegs my CPU.
Our developers are stuck on VS2017 for now, but the 2017 build tools are no longer available for our build server (so we use 2019). The 2017 & 2019 installs put MSBuild in different locations. We could set path variables for all the machines, but that seems brittle.
I'm playing with upgrading one of the projects to the new csproj format, but it is rather involved. Upgrading all of our projects will be an effort all its own, and I'm still exploring the ramifications.
Is there something simple I'm missing which will allow this to work without large modifications?
Error NU5012: Unable to find 'MyProject.dll'. Make sure the project
has been built.
This message indicates that the nuget.exe can't find the output assembly. So you must make sure the assembly is created successfully.
And one point you need to take care, normally we use command like nuget pack foo.csproj -Properties Configuration=Release to pack the assembly built in release mode. If you use command like nuget pack xx.csproj in post-build-event, no matter which configuration you use msbuild to build the project, nuget will always try to find the assembly in ProjectDir/bin/debug.
So when you deploy the project to remote server without bin and obj folders, if you try to use command like msbuild xx.csproj /p:Configuration=Release, the build is in release mode while nuget.exe will search the bin\debug instead of expected bin\release. You should check if you're in same situation.
Why does NuGet pack break with VS2019 build tools?
This issue is not about the build tools package. Since the error message you got came from nuget. Msbuild just help call the nuget.exe, and the cause of the issue is nuget.exe can't find the needed assembly by one specific path. Please check if the path in the error message is right, and then check if the assembly is in that path.
I also ran into the same issue during our TFS upgrade to Azure Devops. The new Nuget task doesn't have the switch for -Build. The fields in the Nuget task screen for Pack also doesn't allow you to add this switch, that's why it's complaining about not finding the dll or the output of the build. I modified the nugetpack.js file on the agent's task folder to test the theory and now the pack options build successfully.
This is the line I added to the js file (towards the bottom of the page):
nugetTool.arg("-Build");
what would be nice is to have this option represented as check box to cover if there is use case to call Nuget pack without -Build switch

Visual Studio 2017 MSBuild Task Development

With developing an custom MSBuild Task with Visual Studio 2017 RC, I have the following problem: As soon as I add other dependencies than just Microsoft.Build.Utilities.Core (using v15.1.0-preview-000458-02 for .NET Core Support), I cannot load the task into another .csproj MSBuild project as the dependencies are not found.
Is there a way to automatically copy all dependencies to the Debug folder?
Or do I have to publish it every time I want to test it?
Update1:
The problem with publish was something local to my environment and has been fixed.
Update2:
It seems that as soon as I change the TargetFramework from netstandard1.4 to netstandard1.6 it isn't even able to load the task at all. As soon as I use netstandard 1.6 it throws a an exception:
The task could not be loaded from the assembly.
Could not load file or assembly 'System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its
dependencies.
Is there a way to automatically copy all dependencies to the Debug folder? Or do
I have to publish it every time I want to test it?
By default and for good reasons, .NET Core and .NET Standard projects do not copy referenced assemblies into the build folder. Instead, they are resolved them from the NuGet cache.
But if you really need it, this behavior can be changed by overriding the default with the CopyLocalLockFileAssemblies setting.
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
Cref: https://github.com/dotnet/sdk/blob/d20405f91a2959fa91fea6285d9a896286727f2a/src/Tasks/Microsoft.NET.Build.Tasks/build/Microsoft.NET.Sdk.BeforeCommon.targets#L55-L56
Second question
It seems that as soon as I change the TargetFramework from netstandard1.4 to netstandard1.6
To build a task assembly that works on both "MSBuild.exe" and "dotnet.exe msbuild", you should target netstandard1.4 or lower. netstandard1.6 is not compatible with .NET Framework 4.6.1 (which MSBuild.exe runs on.)
If you need API not available in netstandard1.4, you will need to cross-compile your task for .NET Framework and .NET Standard, which is considerably more complex but can be done.

monodevelop won't compile VB code

I wanted to have a look at monodevelop, thinking about possible moving in-house projects written in .Net from Windows to Linux.
I installed mono-complete 4.0.2 and monodevelop 5.9.4 on a clean Ubuntu 14.04 VM, I assume those are the latest/current versions.
Now C# works, but I can't get it to compile any VB code.
Any new VB project I create first refuses to load.
Quickly found (Google) that the mono VB compiler doesn't support framework 4 or higher yet, but the project template generates projects targeted at 4.5.
After I manually edit the project file to target 3.5, 3.0 or 2.0, the projects load (this works for console as well as GTK projects).
But when I try to compile it then, no own code added yet, just the auto-generated base code, it just fails without any error messages.
Build output:
Building: VbHelloConsoleWorld (Debug|x86)
Build started 7/3/2015 10:42:20 AM.
__________________________________________________
Project "/home/luc/projects/VbHelloConsoleWorld/VbHelloConsoleWorld.vbproj" (Build target(s)):
Target PrepareForBuild:
Configuration: Debug Platform: x86
Target GenerateSatelliteAssemblies:
No input files were specified for target GenerateSatelliteAssemblies, skipping.
Done building project "/home/luc/projects/VbHelloConsoleWorld/VbHelloConsoleWorld.vbproj".-- FAILED
Build FAILED.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.0438100
---------------------- Done ----------------------
Build successful.
Am I still missing some dependencies? Other stuff that must be fixed before a VB project will work?
For some reason building VB.NET with MSBuild does not work.
To workaround this you can disable the use of the MSBuild build engine. Go into project options, Build - General and uncheck Use MSBuild build engine. Then the project should compile and generate an output assembly.

xUnit Runner for Visual Studio 2012 and native .dlls

Context
I am an application with C# and C++/CLI dlls. The C++/CLI dlls reference pure C++ .dlls, e.g. the boost libraries.
Tests are compiled into Tests.dll, which is placed with all the other binaries in $(SolutionDir)\bin\Debug.
Problem
Trying to run the xunit tests using Visual Studio 2012 fails, with the following error:
xUnit.net: Exception discovering tests from C:\Dev\xu-tests\bin\Debug\Tests.dll:
> System.IO.FileNotFoundException: Could not load file or assembly 'ManagedCpp.DLL'
> or one of its dependencies. The specified module could not be found.
> File name: 'ManagedCpp.DLL'
I can reproduce the problem in two ways outside of visual studio:
When trying to run the console runner from outside this directory
..(longpath)..\xunit.console.clr4.exe Debug\Tests.dll
When trying to run the GUI runner from its installed directory.
I can get it to work however when I use the console to get to the bin\Debug directory, then start the console or GUI runner from there.
This makes me believe that the problem is that VS2012 tries to run the unit tests not using the bin\Debug directory as working directory.
Question
How can I set the working directory in which xunit is run to $(OutDir) (or any specific directory)?

How to run .NET 4 code analysis on build server

On a Windows Server 2003 R2 with .NET 4 SDK but without Visual Studio 2010, I have tried building a Visual Studio 2010 solution with
msbuild MySolution.sln /p:RunCodeAnalysis=true
but that fails.
What is required to run code analysis on such an environment?
I get this error message:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\CodeAnalysis\Microsoft.CodeAnalysis.targets(129,9): error MSB6003:
The specified task executable "FxCopCmd.exe" could not be run.
Could not load file or assembly
'Microsoft.VisualStudio.CodeAnalysis.Sdk, Version=10.0.0.0, Culture=neutral, PublicKeyToken= b03f5f7f11d50a3a'
or one of its dependencies.
The system cannot find the file specified.
I have installed FxCop from the SDK and without luck pointed the variable FxCopDir to the installed location of FxCopCmd.exe, and also setting this registry entry to that location:
HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0\Setup\EDev#FxCopDir
I had the same problem on my MSBuild server and fixed it by:
Installing Windows SDK 7.1
Setting up the registry keys FxCopDir and StanDir in HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0\Setup\EDev (in Win32).
I then copied over from the dev PC, to the FxCop folder on the build server, the following:
The folder Rule Sets (default installation target is here: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\FxCop)
Microsoft.VisualStudio.CodeAnalysis.Sdk.dll
Microsoft.VisualStudio.CodeAnalysis.Phoenix.dll
phx.dll
Do a search for them on your dev PC with Visual Studio installed to locate them.
Then use the .NET 4.0 version of gacutil.exe to install Microsoft.VisualStudio.CodeAnalysis.Sdk.dll to the GAC.
You should then be able to run code analysis as part of an MSBuild build and have it work properly.
An alternative to FxCop would be to use the tool NDepend that lets write Code Rules over C# LINQ Queries (namely CQLinq). Disclaimer: I am one of the developers of the tool
More than 200 code rules are proposed by default. Customizing existing rules or creating your own rules is straightforward thanks to the well-known C# LINQ syntax.
Rules can be verified live in Visual Studio and at Build Process time, in a generated HTML+javascript report.
Another option might be calling FxCop executable as a build task (from msbuildtasks), saving the result as an XML file that can be parsed within most of the CI tools (like Hudson and CC.NET)