This feedback is on the experience of using MSBuild, not just on msbuild.exe
Not in any order, I may sort them later.
Today creating and maintaining MSBuild scripts is challenging. Some of the challenges for the user include.
Creating an MSBuild file itself is challenging. Compare the hello world in MSBuild versus Gulp.
MSBuild
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Demo">
<Message Text="Hello world"/>
</Target>
</Project>
Gulp
var gulp = require('gulp');
gulp.task('default', function() {
console.log('Hello world.');
});
psake
task default {
write-host 'hello world'
}
In the Gulp case once you spend some time with it you could easily type that in notepad. Since it's JavaScript there is good support for it in Visual Studio.
In the psake case, that one is easy to learn as well. There are good tools for PowerShell as well.
Being declarative has advantages, but it's also difficult for users to understand. When editing an MSBuild file you basically have to be aware of the world around you to correctly add functionality to an existing build. For example you may need to know; names of dependson properties, target names, property names, items names, etc.
In the imperative case you could just find the part of the script that you need to modify and party on it. Or add a call to your new method.
- Release
- bitness
- help users pick the correct version of msbuild.exe
- configuration
- visualstudioversion
- log to a file by default, for the case where users see an error scroll by with details but don't have it in the buffer after the build completes.
MSBuild tasks are typically shipped in .dll files which users download from some website. It would be better if it was simpler to get 3rd party msbuild tasks or other tools. For example here is how you can create a self-bootstrapping msbuild script that calls nuget.exe.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="GetNuget">
<!--
This is an MSBuild snippet that can be used to download nuget to the path
in the property NuGetExePath property.
Usage:
1. Import this file or copy and paste this into your build script
2. Call the GetNuGet target before you use nuget.exe from $(NuGetExePath)
-->
<PropertyGroup>
<NuGetExePath Condition=" '$(NuGetExePath)'=='' ">$(localappdata)\LigerShark\AzureJobs\tools\nuget.exe</NuGetExePath>
<NuGetDownloadUrl Condition=" '$(NuGetDownloadUrl)'=='' ">http://nuget.org/nuget.exe</NuGetDownloadUrl>
</PropertyGroup>
<Target Name="GetNuget" Condition="!Exists('$(NuGetExePath)')">
<Message Text="Downloading nuget from [$(NuGetDownloadUrl)] to [$(NuGetExePath)]" Importance="high"/>
<ItemGroup>
<_nugetexeitem Include="$(NuGetExePath)" />
</ItemGroup>
<MakeDir Directories="@(_nugetexeitem->'%(RootDir)%(Directory)')"/>
<DownloadFile
Address="$(NuGetDownloadUrl)"
FileName="$(NuGetExePath)" />
</Target>
<PropertyGroup Condition=" '$(ls-msbuildtasks-path)'=='' ">
<ls-msbuildtasks-path>$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll</ls-msbuildtasks-path>
<ls-msbuildtasks-path Condition=" !Exists('$(ls-msbuildtasks-path)')">$(MSBuildFrameworkToolsPath)\Microsoft.Build.Tasks.v4.0.dll</ls-msbuildtasks-path>
<ls-msbuildtasks-path Condition=" !Exists('$(ls-msbuildtasks-path)')">$(windir)\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll</ls-msbuildtasks-path>
</PropertyGroup>
<UsingTask TaskName="DownloadFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(ls-msbuildtasks-path)">
<!-- http://stackoverflow.com/a/12739168/105999 -->
<ParameterGroup>
<Address ParameterType="System.String" Required="true"/>
<FileName ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
new System.Net.WebClient().DownloadFile(Address, FileName);
]]>
</Code>
</Task>
</UsingTask>
</Project>
Latest at: https://gist.github.com/sayedihashimi/64736331b273162a1e76
It would be good if you could do this more easily for both taks and tools.
A lot of people have asked me questions like "how do I keep my passwords secure on a CI server". I'm not a security expert so I never have a really good answer for them. It would be nice for MSBuild to help here. Also sharing an MSBuild log with someone is a liability, you need to make sure there are no secrets in the log file before sharing. If MSBuild had a concept of secrets it could also ensure they were not printed in the logs.
Having a good debugging story if really needed when things go wrong. Being declarative makes this more difficult though IMO.
Make testing easy so that people can create reliable scripts, especially for cases where targets will be shared publically or with many people.
- Evaluate properties
- Evaluate items
- Run targets