How do I do a deterministic build locally (ContinuousIntegrationBuild flag)? - visual-studio

When I attempt to publish my package using NuGet Package Explorer, I see the following warning:
Deterministic (dll/exe): Non deterministic
Ensure that the following property is enabled for CI builds
and you're using at least the 2.1.300 SDK:
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
However, when I add that property to the PropertyGroup (as described here), VS 2019 freaks out so badly I literally need to ctrl+alt+delete to close it.
According to this page the property name is <Deterministic>, but that doesn't seem to do anything at all.
So how do I get deterministic builds to work?
Visual Studio 2019, v16.7.1
.Net SDK 3.1.401 (LTS)

An easier answer is to not mess with .csproj files (urgh!) and do this via the command line, in your CI script.
add the /p:ContinuousIntegrationBuild=true argument to the dotnet pack command.
dotnet pack
-c $env:CONFIGURATION
/p:ContinuousIntegrationBuild=true
-p:PackageVersion=$env:APPVEYOR_BUILD_VERSION
(make this all one line. I've multi-lined it, for readability)
NOTE: the --no-build argument is NOT here. We need to build this again. Or you add that param to the build step, before this.
This is taken from an example CI file I use. So when I'm in release mode, I pack the library into a nuget and publish it.
Keeps things clean and out of your .csproj file (which is very hard to grok and maintain).

I basically just found the answer in this blogpost:
While deterministic builds are enabled by default in .NET SDK projects, there is an extra property, ContinuousIntegrationBuild, to set on the build server to normalize stored file paths. These should not be enabled during local dev or the debugger won’t be able to find the local source files.
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>

Related

Strip debug information from libgrpc_csharp_ext.x64.so on Windows

My team has recently started using gRPC in our product built on .Net Framework. Due to the high volume of debug symbols in mainly libgrpc_csharp_ext.x64.so our build artifact has exploded from 50 MB to 400 MB. This introduced some problems in our CI/CD environment and also in our delivery chain due to low Internet bandwidth.
I would like to reduce the size of our build artifact.
I know that debug symbols can be stripped from libgrpc_csharp_ext.x64.so using binutils/strip command.
Is that the best way? Or are there some settings in Visual Studio (csproj, sln), Nuget or MSBuild that can be applied to remove debug information from the inherited gRPC so files?
What is the easiest way to use binutils/strip on Windows?
I am afraid that msbuild cannot get that. so file is bases on linux and VS IDE is based on Windows and cannot handle the so file. And it is not generated by MSBuild, VS IDE and is copied from nuget package into your output files based on the RuntimeIdentifier.
But the file is generated by other tool rather VS IDE and VS IDE and MSBuild cannot handle it and it is just copied from the third tool into your VS IDE.
In fact, if it is dll type(Windows) and you have the open source code of the libgrpc_csharp_ext.x64 project.
Note: you have to modify the open source code by MSBuild at the very beginning and then you could generate the file without dll info. And there is no other option to remove the debug info after the re-generate process.
And then you could add these at the bottom of the csproj file:
<PropertyGroup>
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
</PropertyGroup>
And then rebuild the source code to generate the dll without debug info. That is MSBuild function.
But that is for Windows. And it is not suitable for your linux file. And there is no option about it on MSBuild, Nuget, csproj file.
So the best function is use your method, third party stripping tool that uses binutils/strip command. And it is more easier and suitable.

Visual Studio update (16.8.1) lead to CI build failures

We recently updated our build servers to using Visual Studio 16.8.1 and Xamarin.iOS 14.4.1.3 and have hit an issue with the previous MSBuild command that used to run.
For the record we are build a Xamarin Forms solution and targeting iOS here.
The command is:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\msbuild" MySolution.sln /p:Configuration="AppStore" /p:Platform="iPhone" /p:ServerAddress="" /p:ServerUser=""
I have tried searching for the specific error message that it is reporting (below) however I haven't been able to find anything useful so far.
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Xamarin\iOS\Xamarin.Shared.targets(230,3): error MSB4044: The "GetMinimumOSVersion" task was not given a value for the required parameter "SdkVersion".
Update
Upon further digging I believe I have traced the source of the error back to these lines not being set in Xamarin.Shared.props.
<!-- SdkVersion -->
<_SdkVersion Condition="'$(_PlatformName)' == 'macOS'">$(MacOSXSdkVersion)</_SdkVersion>
<_SdkVersion Condition="'$(_PlatformName)' != 'macOS'">$(MtouchSdkVersion)</_SdkVersion>
I haven't been able to find out what sets MtouchSdkVersion and therefore why it isn't being set. A comment from just above the quoted section above states:
Sometimes we've used different variable names for the same thing for Xamarin.iOS and Xamarin.Mac projects. Here we try to unify those variables
Could it be that this unification has changed the behaviour of something that used to work?
This has reared it's head again in Visual Studio 2019 version 16.8.3. Looks like they've moved the problem to:
<VS Install path>\MSBuild\Xamarin\iOS\Xamarin.Messaging.targets I was able to get my builds running again by removing the _SayGoodbye dependency on line 52 for the _DisconnectAfterClean target.
<Target Name="_DisconnectAfterClean" Condition="'$(IsRebuild)' != 'true'" DependsOnTargets="" />
This is certainly not a permanent solution to the problem but a workaround has been supplied by the Xamarin team. For reference the response is on GitHub
we're investigating it, but it looks like the build process is getting disconnected after running the clean targets, so if you run Build instead of Rebuild you shouldn't face this.
In the meantime, a potential workaround to unblock Rebuilds would be to edit <VS Install path>\MSBuild\Xamarin\iOS\Xamarin.iOS.Windows.After.targets and remove the _SayGoodbye entry from the CleanDependsOn property group.
I can confirm that this has allowed our CI builds to operate again.
It should go without saying but I want to make it clear you should backup a copy of the Xamarin.iOS.Windows.After.targets file before doing this.

Add command-line arguments to visual Studio Project in TeamCity

If I run a c++ project/solution, in Visual Studio, with a command line option "--xx", how can I do the exact same thing from TeamCity ?
I have searched and have been unable to find any option.
The one thing that looks like "Command line parameters" is actually designated for MSBuild.
I have to run the solution - and not just the executable generated by the solution.
Thank you.
Your Visual Studio build is executed using MSBuild on the server, the name may be a little confusing, but the parameters should function in the same way using that MSBuild parameter box as passing them to visual studio would be.
if there are issues getting this to work using that parameters box, we will need some more information about the commands you need to run and the behaviour you need.
Edit following questioner's comment
The problem in actuality here is that Visual Studio builds don't really exist in TeamCity, visual studio build is actually just going to run MsBuild against your visual studio solution, which, in terms of Google Test, is sufficiently different to cause your problems.
To resolve this, you are probably going to have to change your build runner to just be an MsBuild script which builds your solution and runs the Google tests. thankfully, the internet provides:
http://code.google.com/p/msbuildteamcitytasks/wiki/RunGoogleTests
The above is some MsBuild tasks which claim to integrate GoogleTest results completely with TeamCity, doing all the leg work for you in that regard. The result of this is that you only need a very brief build script calling MsBuild on your solution, followed by calling that MsBuild Task as required. I cant confirm how well they work or how easy they are to set up as I haven't used them, but the documentation on the page implies it should be reasonably easy to put together.
below is a snippet of MsBuild that will build your solution(s)
<MSBuild Projects="#(BuildProjects)" Targets="Rebuild" BuildInParallel="true" Properties="Configuration=Debug;Platform=$(Platform)">
<Output ItemName="DebugOutputs" TaskParameter="TargetOutputs"/>
</MSBuild>
where each $() variable is a system property in your TeamCity configuration #(BuildProjects) is a list of solutions generated using this:
<ItemGroup>
<BuildProjects Include="$(WorkingArea)\**\*.sln" />
</ItemGroup>
you can of course hard code any and all of these variables, or change parameters as required, but this example will give you some freedom to reuse the script on other projects (its not a full script, there's some extra structure stuff to go around the outside).
you can of course build in further functionality to the script as required, or leave it as simple as possible to make it easy to understand.
there is further documentation on MsBuild scripts are available from these locations:
http://www.universalthread.com/ViewPageArticle.aspx?ID=61
http://codingcockerel.co.uk/2008/04/15/automating-the-build-with-msbuild/
http://www.codeproject.com/Articles/12985/Practical-NET2-and-C-2-An-introduction-to-MSBuild
I'm sure there's plenty more out there if you need it.
Well, In TeamCity (I am using version 6.5.x), When you add a new Build Step, select the Build runner as Visual Studio (sln) or Visual Studio 2003 as per your requirement and there you'll get the option to pass command line parameters.
What Version of TeamCity do you use?

Building MSI from TFS Build

I am trying to build MSIs in a TFS Build by shelling out to DEVENV.exe (since MSBUILD does not support VSPROJs). In any case, my first installer project builds fine, the second one fails. If I reverse the order, same thing happends (i.e. the error does not follow the project). Looking at the output, I get the following errors:
Deserializing the project state for project '[MyProject].dbproj'
[MyProject].dbproj : error : Error HRESULT E_FAIL has been returned from a call to a COM component.
Also, I get:
Package 'Microsoft.VisualStudio.TestTools.TestCaseManagement.QualityToolsPackage, Microsoft.VisualStudio.QualityTools.TestCaseManagement, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' failed to load
It looks as though the first build tries to serialize the DB project (and it says it succeeds, but there is no DBML file anywhere). Then the second build tries to deserialize the DB project and fails.
I've tried resetting env settings (using the /resetusersettings flag) as well as using the /resetskippkgs flag. Nothing works.
Any ideas?
When you shell out to DevEnv, are you building that specific project (.vdproj file), or are you building the solution? It sounds like VS is trying to open the solution on the build machine and the database and test project systems aren't present.
Have you considered porting your setup project to WiX?
Start simple. Unless you're well versed in the problem you're trying to solve it's usually best to try it "by hand" before getting it running as part of a TFS build. RDP into the build server and try running the necessary commands at the command line and see what happens. You can even go simpler than that and RDP into the build machine and load Visual Studio and build it.
Bottom line is that if you can't get it to build within Visual Studio or at the command line by calling devenv.exe it won't work as part of the team build.
I am using the below Exec task to do precisely what you are doing as part of a TFS build. So I know this works. Your platform and configuration may vary depending on what you're building. The nice thing about this is that you'll have a log file at C:\Temp\MSIBuildOutputLog.txt that you can analyze for additional errors and information.
<Exec Command=""C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe" "$(PathToSolution)\solution.sln" /Build "Release|Mixed Platforms" /out "C:\Temp\MSIBuildOutputLog.txt"" />
One important thing to note... There is a bug in VS2010 which causes MSI generation to fail when you try to run it at the command line using devenv.exe. This took me days to find and figure out, but you need this hotfix. Worked like a charm...
http://archive.msdn.microsoft.com/KB2286556
Actually it's the deployment projects that don't support msbuild. FWIW, this is all deprecated in the next release of Visual Studio so you might want to start looking at InstallShield Limited Edition and/or Windows Installer XML now before spending too much time on dead end, broken technology. Both of these alternatives have proper MSBuild support aswell as many other improvements.
It would be perhaps better and quicker to adopt WIX (Windows Installer XML) which is the technology MS now recommends to use within VS/MSBuild/TFSBuild environment to crate MSIs.
It is relatively easy to setup and integrate within your VS Solutions. It uses XML based files to describe your MSIs and uses these files to create your MSIs when you compile.
I would start by downloading Wix from http://wix.codeplex.com/
Once installed you would be able to use the VS2010 integration of Wix based projects to create MSIs. To get started quickly simply add a new Wix project to your solution and reference the projects whose output you wish to combine into an MSI. Next you can run a tool called "Heat" which is included with Wix toolkit to generate the XML files by scanning your projects.
Once you have these XML files, add them to your Wix project and compile.

Where can I see the build script used by Visual Studio?

Where can I find the build script -all the list of tools used to build and link the assemlies like al.exe etc.-that BUILDS, REBUILDS the visual-Studio solutions?
MSBuild (the build engine for Visual Studio) uses a model where the tool(s) used for an action are dictated by the project file being built. Thus your list of tools will vary based on the types of projects you are building. The easiest way to find out the list of tools being used for a build of any given solution would be to turn on a more detailed logging level (detailed or diag) for MSBuild via Tools->Options->Projects & Solutions->Build & Run in Visual Studio and then parse/investigate the build output for an indication of the tools currently invoked by the Build Targets.
As Nick Nieslanik has said in his answer, the actual toolset will vary based on the project type (and target programming language), maybe even the selected .NET framework version.
To have single view on all definitions, properties, targets, etc. used by MSBuild, you could generate and review a fully preprocessed project file (only available with MSBuild 4.0 or newer).
From msbuild.exe /? output:
/preprocess[:file]
Creates a single, aggregated project file by
inlining all the files that would be imported during a
build, with their boundaries marked. This can be
useful for figuring out what files are being imported
and from where, and what they will contribute to
the build. By default the output is written to
the console window. If the path to an output file
is provided that will be used instead.
(Short form: /pp)
Example:
/pp:out.txt
Example:
msbuild.exe myproj.csproj /pp:out.xml
In this case out.xml is basically a self-contained file that has all the Import-ed project files inline so you can easily search and browse them.
In each project (in this case a c# csproj) file is a link to the msbuild used by msbuild/visual studio to build.
e.g. <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
This target links to the internal files used.

Resources