VCTargetsPath is wrong when building with MSBuild on build server - tfs

In my C++ project, Test.wcxproj, I have the following configurations defined:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
Then I have the problematic import of the default C++ properties:
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
When my build server builds my MSBuild project file (configuration is Release and platform is Any CPU), I get this error:
error MSB4019: The imported project "C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.Cpp.Default.props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
The relevant parts of my MSBuild project file look like this:
<ItemGroup>
<ProjectFiles Include="$(MSBuildProjectDirectory)\**\*.csproj" />
<ProjectFiles Include="$(MSBuildProjectDirectory)\**\*.vcxproj" />
</ItemGroup>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>x64</Platform>
<OutputFolder>$(MSBuildProjectDirectory)\BuildOutput\$(Configuration)</OutputFolder>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)</SolutionDir>
</PropertyGroup>
...
<Target Name="Compile">
<MSBuild Projects="#(ProjectFiles)" Targets="Build" Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(OutputFolder)\$(MSBuildProjectName);SolutionDir=$(SolutionDir)\" />
</Target>
The problem
In my MSBuild project file, I am using ToolsVersion="12.0". Visual Studio 2013 is indeed installed, so I don't understand why it chooses to use v4.0\v110. Are my project configurations for some reason skipped by MSBuild? I guess I could somehow override this folder using the /p switch, but I want my .proj file to be self-contained.

Try to set up environment variable
VisualStudioVersion=12.0
or pass it explicitly as property to msbuild on commandline
msbuild.exe <project or solution to build> /p:VisualStudioVersion=12.0
I think it is because Microsoft tries to keep compatibility with older Visual Studios.
see Visual Studio project compatibility and VisualStudioVersion

In my case, my build definition was configured to build my .sln file instead of my .proj file. I remember configuring it to build the MSBuild project, but somehow it seems to have reverted to the Solution.
Anyway, I found two solutions to the problem:
Make sure to build the .proj file (where the tools version is indeed set to 12.0).
Explicitly set the VCTargetsPath.

Related

Project SDK (.Net Standard): Official way to create a nuget package that includes msbuild targets

Visual Studio 2019, .Net Standard 2.0
How do I include a custom msbuild targets file for the consuming project?
What is the official supported way of doing this?
I've already tried:
modifying the csproj file as per (Setting Nuget package target path for item in MSBuild project)
trying to specify a nuspec file as per (https://natemcmaster.com/blog/2017/11/11/build-tools-in-nuget/)
Nuspec:
<?xml version="1.0"?>
<package >
<metadata>
<id>TestingNugetContent</id>
<version>1.0.10</version>
<title>Blah</title>
<authors>Me</authors>
<owners>Me</owners>
<licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
<projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
<iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Blah</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2019</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="Immutable\*.*" target="content/Immutable/" />
<file src="Build\*.*" target="build/netstandard2.0/" />
</files>
</package>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<NoPackageAnalysis>true</NoPackageAnalysis>
<NuspecFile>TestingNugetContent.nuspec</NuspecFile>
<IntermediatePackDir>$(MSBuildProjectDirectory)/bin/$(Configuration)/publish/</IntermediatePackDir>
<PublishDir>$(IntermediatePackDir)$(TargetFramework)/</PublishDir>
<NuspecProperties>publishDir=$([MSBuild]::NormalizeDirectory($(IntermediatePackDir)))</NuspecProperties>
<Version>1.0.10</Version>
</PropertyGroup>
<ItemGroup>
<Compile Remove="build\**" />
<EmbeddedResource Remove="build\**" />
<None Remove="build\**" />
</ItemGroup>
<ItemGroup>
<None Include="build\netstandard2.0\TestingNugetContent.targets" />
</ItemGroup>
<Target Name="PublishAll" BeforeTargets="GenerateNuspec">
<ItemGroup>
<_TargetFramework Include="$(TargetFrameworks)" />
</ItemGroup>
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Publish" Properties="TargetFramework=%(_TargetFramework.Identity)" />
</Target>
</Project>
Checking the consumer's <***>.csproj.nuget.g.targets file the import project tag for this custom target is missing after installing the Nuget package
As per the docs, the props and targets file names must match the package id exactly. Your nuspec lists the <id> as TestingNugetContent, so the files must be TestingNugetContent.props and TestingNugetContent.targets. They should be either directly in the build/ folder in the package, or the build/<tfm>/ folder (I prefer to be more explicit, so I appriciate you used the netstandard2.0 TFM). Now, your csproj appears to specify a build\netstandard2.0\TestingNugetContent.targets, which looks correct, so I can only guess that it wasn't packed into the correct location somehow.
I don't currently have time to show an example on how to pack it, but you can inspect the contents of your nupkg using NuGet package explorer, or just opening it up as a zip file, see what's "wrong", then adjust your project and try again.
FYI, you shouldn't need to use a nuspec at all, you can use the MSBuild PackagePath metadata on items to specify where MSBuild items are packed. It's unclear to me what the purpose of your PublishAll target is supposed to be. If you added it as part of trying to get your targets file included, you can remove it.

Deploying native libraries with TFS deploy agent

I'm using libgit2sharp in my project which uses Git2 library to work. Now, the last version used project properties files instead of custom build action. While this work fine when building or using the Publish action in Visual Studio 2013, it won't work at all using TFS build server.
Here are the imports instruction in the csproj file.
<Import Project="..\packages\LibGit2Sharp.0.20.0.0\build\net40\LibGit2Sharp.props" Condition="Exists('..\packages\LibGit2Sharp.0.20.0.0\build\net40\LibGit2Sharp.props')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\LibGit2Sharp.0.20.0.0\build\net40\LibGit2Sharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\LibGit2Sharp.0.20.0.0\build\net40\LibGit2Sharp.props'))" />
</Target>
And here is the props file in question:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)\..\..\lib\net40\NativeBinaries\amd64\git2-3f8d005.dll">
<Link>NativeBinaries\amd64\git2-3f8d005.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)\..\..\lib\net40\NativeBinaries\amd64\git2-3f8d005.pdb">
<Link>NativeBinaries\amd64\git2-3f8d005.pdb</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)\..\..\lib\net40\NativeBinaries\x86\git2-3f8d005.dll">
<Link>NativeBinaries\x86\git2-3f8d005.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)\..\..\lib\net40\NativeBinaries\x86\git2-3f8d005.pdb">
<Link>NativeBinaries\x86\git2-3f8d005.pdb</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
So, again, publishing or building the project with Visual Studio will copy the NativeBinaries folder to the bin folder which is perfectly fine. But, using a TFS build deployment setup, the folder is never transfered over the server using the RemoteAgent.
MSBuild arguments:
/p:DeployTarget=MsDeployPublish /p:Configuration=MEP-DEV /p:DeployOnBuild=True /p:CreatePackageOnPublish=False /p:MsDeployPublishMethod=RemoteAgent /p:AllowUntrustedCertificate=True
In the build log file, I can see that the Libgit2sharp NuGet package is being installed, but the libraries are not mentioned anywhere as if they are just ignored by the deployment process.

msbuild custom compiler/build script

I'm attempting to use TFS and MSBuild as a build and source control for a non-.NET project. This project contains a series of individual called .skbsrc files, that each compile into a .skb file. I'm trying to figure out if it's possible to use MSBuild in a way to build these files.
Say I'm using the example on the msdn website:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Include="testfile.skbsrc" />
</ItemGroup>
<Target Name="Build">
<Csc Sources="#(Compile)"/>
</Target>
</Project>
Csc is clearly used for C# code, and runs the csc.exe program. Is there a way I can make a block like this for my own compiler (skbuilder) so I could run like:
<Skbuilder Sources="#(Compile)" />
which in turn would run
>skbuilder testfile.skbsrc
If this is possible with msbuild, could anyone post an example? I've been unable to find anything in my searches.
Thank you so much.
You can create a customized task in msbuild to do it. "CSC" is a default task in C#, so what you need is to implement a similar task for your exe.
This MSDN article explains how to write a task for msbuild.
Take a look at the Exec Task.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<SourceFiles Include="*.skbsrc"/>
</ItemGroup>
<Target Name="Build">
<Exec Command="skbuilder "%(SourceFiles.Identity)""/>
</Target>
</Project>
You'll also need to pass an argument to your skbuilder program telling it to output it's files to the $(OutDir) directory or use Copy Task to pick up *.skb to $(OutDir). Use quotes around the argument incase the TFS workspace path has spaces in it.
Finally you can test this on your own machine without using TFS by creating a simple .BAT file:
set PATH=%CD%;C:\Windows\Microsoft.NET\Framework\v4.0.30319
msbuild build.proj > build.log

MSBuild: Do not generate class library config files

I've created a custom workflow for my build process in TFS that is using the MSBuild activity.
For some reason in the output folder I'm getting config files for all of my class library projects. Since I only need the app config file for project I'm actually building, is there a command line argument to prevent MSBuild from creating the [library].dll.config files in the output directory?
I wasn't able to find any msbuild arguments that caused this behavior, so I just gave up and added this to the end of the csproj file:
<Target Name="AfterBuild">
<ItemGroup>
<DeleteAfterBuild Include="$(OutDir)*.dll.config" />
</ItemGroup>
<Delete Files="#(DeleteAfterBuild)" />
</Target>

How can we include the files created by ajaxmin in the msdeploy package created by MSBuild

We use ajaxmin to create .min.js files from all our .js files. We have edited the .csproj file of the project and added following:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="AfterBuild">
<ItemGroup>
<JS Include="**\*.js" Exclude="**\*.min.js" />
</ItemGroup>
<AjaxMin JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" />
</Target>
This works great when we build the site on our workstation and the .min.js files can be used in the site. When we check this project in this task runs also on the msbuild server but the .min.js files generated by ajaxmin are not copied to the drop location of the tfs2010 Rolling Build we use. These .min.js files are also not included into the package we create during this rolling build and which is also copied to the drop location. Only the files included into the project are used for the package and copied to the drop location.
The MSBuild Arguments we use to create the package are the following:
/p:DeployOnBuild=True /p:DeployTarget=MsDeployPublish /p:MSDeployPublishMethod=InProc /p:CreatePackageOnPublish=True /p:MSDeployServiceURL=localhost
I've tried several things as adding an extra build task to copy all the .min.js files to the location where the package is created. I tried also the following url http://sedodream.com/2010/05/01/WebDeploymentToolMSDeployBuildPackageIncludingExtraFilesOrExcludingSpecificFiles.aspx to include this files with the following in my .csproj file:
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="**\*.min.js" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
Has anyone else also this problem or does anyone have an idea how to include the *.min.js files in the msdeploy package and make the files copy to the drop location?
You missed the destination directory so all you have to do is creating pair folders for each script in your script folder, source and destination to make sure you didn't copy all the min files to each folder in your project according to the script folder structure of your project, any way I write an article and who how to do that, you can also download project that do that, http://mohamedradwan.wordpress.com/2010/11/12/how-to-include-minify-files-or-custome-files-with-web-pagckage-or-ms-deploy-package/
Thanks

Resources