FSharp build fails in MSBuild, but works ok in Visual Studio - visual-studio

I have a number of projects in my solution, among which also a F# project. Everything builds fine in Visual Studio, but when I try to build it with MSBuild on my TeamCity server (which does not have VS installed) it throws the following build error:
C:\TeamCity\buildAgent\work\42c74d8b9d19a844\FSharpEngine\MY_FSHARP_PROJECT.fsproj : error MSB4057: The target "Clean" does not exist in the project.
[16:27:58]Done Building Project "C:\TeamCity\buildAgent\work\42c74d8b9d19a844\Folder0\MY_FSHARP_PROJECT.fsproj" (Clean target(s)) -- FAILED.
[16:27:58]Done Building Project "C:\TeamCity\buildAgent\work\42c74d8b9d19a844\Folder1\REFERENCING_FSHARP_PROJECT.csproj" (Clean target(s)) -- FAILED.
[16:27:58]Done Building Project "C:\TeamCity\buildAgent\work\42c74d8b9d19a844\Folder2\UPPER_REFERENCING_FSHARP_PROJECT.csproj" (Rebuild target(s)) -- FAILED.
[16:27:58]Done Building Project "C:\TeamCity\buildAgent\work\42c74d8b9d19a844\Folder4\UPPER_UPPER_REFERENCING_FSHARP_PROJECT.csproj.metaproj" (Rebuild target(s)) -- FAILED.
[16:27:58]Done Building Project "C:\TeamCity\buildAgent\work\42c74d8b9d19a844\MY_SOLUTION.sln" (Rebuild target(s)) -- FAILED.
[16:27:58]Done Building Project "C:\TeamCity\buildAgent\work\42c74d8b9d19a844\MY_SOLUTION.sln.teamcity" (TeamCity_Generated_Build target(s)) -- FAILED.
I have installed MSBuild Tools and F# framework on my TeamCity server, but I still don't know why this error is thrown.
Did someone came across this error and can give me some clues on how to fix it? (I've lost a day already and still no luck).

We had the same problem with AutoFixture.AutoFoq and ZeroToNine.
What we did was to modify the .fsproj files.
First, you have to add
<TargetFSharpCoreVersion>4.3.0.0</TargetFSharpCoreVersion>
to the first <PropertyGroup>.
Second, you replace
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')" />
with this:
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
Finally, replace
<Reference Include="FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
with
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
If you want to see this in context, you can review the ZeroToNine commit that does the above.

You can create the target "Clean" in your project:
<Target Name="Clean">
<MSBuild
Targets="Clean"
Projects=".\MySolutionDir\MySol.sln"
Properties="Configuration=$(Configuration)" />
</Target>
Or you can modify the command line to something like this:
MSBuild MyProj.proj /p:Configuration=Release;Targets=Clean

I had a problem today with the same symptoms on my build server. What fixed it for me was starting up VS on the build server and creating a F# project, which installed the F# tooling. It was not installed completely by default.

Related

Visual Studio 2017 extension - VSToolsPath not working

I'm updating an old Visual Studio extension for VS 2017. It compiles fine from Visual Studio and msbuild in debug and release on my local computer.
This is the msbuild command line I am using:
msbuild VxCop.sln /p:ToolsHome=C:\ProgramData\chocolatey\bin /p:Configuration=Release /p:Platform="Any CPU"
However, on the build machine (TFS Build 2010) calling msbuild.exe with the same command line it fails with this error
In order to fix this I am trying to specify VSToolsPath. I've tried various things such as altering the VSToolsPath entry in the .csproj (which seems to not be taken into account since doing this had no effect) and also passing it on the command line:
msbuild VxCop.sln /p:ToolsHome=C:\ProgramData\chocolatey\bin /p:Configuration=Release /p:Platform="Any CPU" /p:VSToolsPath=Packages\Microsoft.VSSDK.BuildTools.15.1.192\tools\
This causes a very strange error:
CopyFilesToOutputDirectory:
Copying file from "obj\Release\SymCop.dll" to "bin\Release\SymCop.dll".
SymCop -> H:\src\tools\VisualStudioExtensions\Main\VxCop\source\SymCop\bin\Release\SymCop.dll
Copying file from "obj\Release\SymCop.pdb" to "bin\Release\SymCop.pdb".
Done Building Project "H:\src\tools\VisualStudioExtensions\Main\VxCop\source\SymCop\SymCop.csproj" (default targets).
Done Building Project "H:\src\tools\VisualStudioExtensions\Main\VxCop\VxCop.sln" (Build target(s)) -- FAILED.
Done Building Project "H:\src\tools\VisualStudioExtensions\Main\VxCop\build.proj" (default targets) -- FAILED.
Build FAILED.
0 Warning(s)
0 Error(s)
The actual extension project isn't appearing in the log at all, and there's no, y'know, errors. But the build returns as failed, the return code is non-zero, and the vsix project seems to not be built (its output is missing)
Hopefully someone has some suggestions
Thanks
Edit:
For those reading this in the future, the problem seemed to be that there was an <Import> further down in the same file which didn't care about my update to $(VSToolsPath).
Changing that import fixed it:
<Import Project="$(SolutionDir)\packages\Microsoft.VSSDK.BuildTools.15.1.192\tools\VSSDK\Microsoft.VsSDK.targets"
/>
Visual Studio 2017 extension - VSToolsPath not working
I got the same result as you based on your scripts. After installed the NuGet package Microsoft.VSSDK.BuildTools to the project, the Microsoft.VSSDK.BuildTools.props will be imported in to project file, open the project file, you can find below Import:
<Import Project="..\packages\Microsoft.VSSDK.BuildTools.15.1.192\build\Microsoft.VSSDK.BuildTools.props" Condition="Exists('..\packages\Microsoft.VSSDK.BuildTools.15.1.192\build\Microsoft.VSSDK.BuildTools.props')" />
Then open this props file, you can notice below scripts snippet:
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="VSSDK_NuGet_Configuration">
<ThisPackageDirectory>$(MSBuildThisFileDirectory)..\</ThisPackageDirectory>
<VSToolsPath>$(ThisPackageDirectory)\tools</VSToolsPath>
<VsSDKInstall>$(VSToolsPath)\VSSDK</VsSDKInstall>
<VsSDKIncludes>$(VsSDKInstall)\inc</VsSDKIncludes>
<VsSDKToolsPath>$(VsSDKInstall)\bin</VsSDKToolsPath>
</PropertyGroup>
</Project>
In this case, NuGet package override the value VSToolsPath with $(ThisPackageDirectory)\tools. So MSBuild will skip set the value setting in the next step in the project file:
<PropertyGroup>
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
Because NuGet have already set the value $(VSToolsPath), the value of Condition="'$(VSToolsPath)' == ''" would be False. In addition, you can add a target to check if the value is set, like:
<Target Name="CheckVSToolsPath" BeforeTargets="Build">
<Message Text="$(VSToolsPath)"></Message>
</Target>
You will find this value is set to:
C:\Users\Admin\Documents\Visual Studio 2017\Projects\VSIXProject2\packages\Microsoft.VSSDK.BuildTools.15.1.192\build\..\\tools
Summary above, the value of VSToolsPath was imported correctly, we do not need to passing it on the command line.
After in-depth investigation, I found the reason for the previous error "MSB4226: The imported project "(...)\VSSDK\Microsoft.VsSDK.targets" was not found." is that the MSBuild property of "VisualStudioVersion" not be set on the build server.
See below link for detail info Building a VSIX extension with the Visual Studio 2017 Build Tools:
something that a machine with the full Visual Studio 2017 does and that a machine with the Build Tools 2017 does if you open a developer command prompt. Since I was not using it, I passed it as a parameter to the MSBuild script. It can be defined too inside the .csproj file, something that previous Visual Studio versions did automatically but recent versions don’t.
So to resolve the error "MSBuild4226", you should pass the visual studio version on command line:
msbuild VxCop.sln /p:ToolsHome=C:\ProgramData\chocolatey\bin /p:Configuration=Release /p:Platform="Any CPU" /p:VisualStudioVersion=15.0
After using this command line, the error MSBuild 4226 was resolved.
Hope this helps.
I resolved this problem in VS 2019 by https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#generatepathproperty
<ItemGroup>
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="16.10.1055">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<Import Project="$(PkgMicrosoft_VSSDK_BuildTools)\tools\vssdk\Microsoft.VsSDK.targets" />

ASP.NET Core (NET Framework) Teamcity build fails, VS builds properly

I have an ASP.NET Core project that builds properly with VS but fails with TeamCity.
It is a project that compiles to a library, but TeamCity tries to build it as an executable, and complains about the lack of 'main':
CSC error CS5001: Program does not contain a static 'Main' method suitable for an entry point
The content of the .csproj file are as follow:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<OutputTypeEx>library</OutputTypeEx>
<StartupObject />
<AssemblyName>Test</AssemblyName>
<RootNamespace>Test</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
</Project>
Visual studio has no problem building the dll file.
To reproduce:
Create an ASP.NET Core (.NET Framework) project
Change the output type to library
Remove the program.cs / startup.cs files
Compile with Visual Studio to confirm a library is being built
Build with Team City and an error will appear
To avoid that error, Please look into this SO post or this
You should be using the dotnet core plugin or you can easily
configure dotnet build command(if dotnet is present in your build
servers).
Or you can refer the MusicStore build.cmd file for reference. This basically downloads and installs the dotnet and all the dependencies and then builds the project.
Hope it helps!
I found a workaround; in the project file, VS puts this:
<OutputTypeEx>library</OutputTypeEx>
I need to add one line:
<OutputType>Library</OutputType>
<OutputTypeEx>library</OutputTypeEx>
So it looks like the build with TeamCity is not handling the OutputTypeEx propery but it handles the OutputType one.
I still see this as a bug, but at least there is a workaround.

TypeScript files compiling on save but not on build

Problem
I've found that my TypeScript files only compile when I save them. However, when I build or rebuild the project, they do not compile. I'm using TypeScript 0.9.1.1.
When I check the build output of a new TypeScript project, it includes the following entry:
CompileTypeScript:
C:\Program Files\Microsoft SDKs\TypeScript\tsc.exe --module AMD --sourcemap --target ES3 "app.ts"
But my project doesn't produce this in its build output.
Setup
Here are the relevant parts of the project file:
<ItemGroup>
<TypeScriptCompile Include="Scripts\app\example.ts" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>true</TypeScriptIncludeComments>
<TypeScriptSourceMap>true</TypeScriptSourceMap>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>false</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
</PropertyGroup>
<Import Project="$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
What I've checked
The files compile on build in new TypeScript projects, so it should be possible.
The targets file exists in the correct location
The project file configuration shown above appears to be correct when compared with a new TypeScript project
Compiling a new TypeScript project, which works fine
Cannot compile TypeScript files in Visual Studio 2012, but the symptoms of the problem are different to mine, and it's not clear if the author was using the same setup
Typescript will not properly compile in VS2012, but the symptoms of the problem are different to mine
The build action for each TypeScript file is set to TypeScriptCompile as shown above
After comparing the project file with a new TypeScript project file, I narrowed the problem down to the following:
The TypeScript targets file must be imported after the C# targets file.
In the code in the question, fix the problem by moving the following line up:
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

Building Visual Studio project with different platforms via MSBuild

I have 3 projects with configuration:
Project A: Debug|AnyCPU, Release|AnyCPU
Project B: Debug|AnyCPU, Release|AnyCPU
Project C: Debug|x86, Debug|x64, Release|x86, Release|x64
Project C have B in dependencies and B have A in dependencies. (A <- B <- C)
I use *.bat file to build its from command line:
msbuild A.csproj /target:Build /property:Configuration=Debug;Platform=AnyCPU /verbosity:minimal
msbuild A.csproj /target:Build /property:Configuration=Release;Platform=AnyCPU /verbosity:minimal<br/>
msbuild B.csproj /target:Build /property:Configuration=Debug;Platform=AnyCPU /verbosity:minimal
msbuild B.csproj /target:Build /property:Configuration=Release;Platform=AnyCPU /verbosity:minimal
msbuild C.csproj /target:Build /property:Configuration=Debug;Platform=x86 /verbosity:minimal
msbuild C.csproj /target:Build /property:Configuration=Release;Platform=x86 /verbosity:minimal
msbuild C.csproj /target:Build /property:Configuration=Debug;Platform=x64 /verbosity:minimal
msbuild C.csproj /target:Build /property:Configuration=Release;Platform=x64 /verbosity:minimal
And recieve error:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Common.targets(609,5): error : The OutputPath property is not set for project 'A.csproj'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Debug' Platform='x86'. You may be seeing this message because you are trying to build a project without a solution file, and have specified a non-default Configuration or Platform that doesn't exist for this project. [A.csproj]
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Common.targets(609,5): error : The OutputPath property is not set for project 'B.csproj'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Debug' Platform='x86'. You may be seeing this message because you are trying to build a project without a solution file, and have specified a non-default Configuration or Platform that doesn't exist for this project. [B.csproj]
I found the solution for my problem.
Use Choose element in *.csproj file for detect building via Visual Studio or via MSBuild and use Reference (instead of ProjectReference) for MSBuild.
<Choose>
<When Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<ItemGroup>
<ProjectReference Include="A.csproj">
<Project>{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}</Project>
<Name>A</Name>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="B.csproj">
<Project>{BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB}</Project>
<Name>B</Name>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx, processorArchitecture=MSIL">
<HintPath>A.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx, processorArchitecture=MSIL">
<HintPath>B.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
</Otherwise>
</Choose>
You can make this work if you define a custom build configurations in your solution file.
Open the solution in Visual Studio, then open Configuration Manager for the solution. In the Active solution platforms drop-down there will be <New...> option that would allow you to create x86 and x64 platforms for the solution. After you've created them select each one in that same drop-down and make sure that in the list you have Any CPU for your projects A and B and that the project C has correspondingly x86 or x64 selected. Also make sure that Build checkbox is checked.
Now switch the Active solution configuration to Release and define those extra platforms the same way.
After you do that you'll be able to build all 3 projects specifying just the solution file in the MSbuild command line:
msbuild ABC.sln /target:Build /property:Configuration=Debug;Platform=x86 /verbosity:minimal
msbuild ABC.sln /target:Build /property:Configuration=Release;Platform=x86 /verbosity:minimal
msbuild ABC.sln /target:Build /property:Configuration=Debug;Platform=x64 /verbosity:minimal
msbuild ABC.sln /target:Build /property:Configuration=Release;Platform=x64 /verbosity:minimal
You can try to build project with devenv.exe from command line. I think that this will not have problems you experienced but i remember something about this build option to be deprecated and it sometimes hanged for no reason. I wrote this as one option, just because other two are not good for me either.

TFS CI issue with a SSIS package

Build started 16/11/2011 9:24:11 AM.
Project "C:\Builds\1\NetTellerMigration\NetTellerMigrationBuild\Sources\blah.sln" on node 1 (default targets).
ValidateSolutionConfiguration:
Building solution configuration "Development|Default".
MSBUILD : warning MSB4078: The project file "blah\blah.dtproj" is not supported by MSBuild and cannot be built. [C:\Builds\1\NetTellerMigration\NetTellerMigrationBuild\Sources\blah.sln]
Done Building Project "C:\Builds\1\NetTellerMigration\NetTellerMigrationBuild\Sources\blah.sln" (default targets).
Build succeeded.
"C:\Builds\1\NetTellerMigration\blahBuild\Sources\blah.sln" (default target) (1) ->
(blah_b target) ->
MSBUILD : warning MSB4078: The project file "blah\blah.dtproj" is not supported by MSBuild and cannot be built. [C:\Builds\1\NetTellerMigration\NetTellerMigrationBuild\Sources\blah.sln]
1 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.42
I currently have tfs2010 installed with SqlExpress and im trying 'unsucessfully' to implement continuous-integration against a SSIS package. My aim is to create a build triggered by a code checkin. I have a build definition to doso but the warning shown above is displayed and no '.dtsx' files are copied to the build directory?
I believe its something to do with the build agent targeting v4 of the .net framework but I could be wrong. Anyway, any help would be much appreciated from anyone who has experience this problem before.
MSBuild can't build SSIS projects (.dtproj) because the format of these projects is pre-VS2010. The best thing to do here is to have MSBuild shell out to the SSIS project. You can create an empty C# project to do this. Then, open the .csproj file for the new project in a text editor and set the BeforeBuild target to the following:
<Target Name="BeforeBuild">
<!-- Build the analysis SSIS project -->
<Exec Command=""$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\#InstallDir)\devenv.exe" blah\blah.dtproj /Build" />
</Target>
Adjust the blah/blah.dtproj path for your project. This will run the VS2008 version of devenv to build the SSIS project.
Below is a sample of what the whole .csproj file might look like:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
<PropertyGroup>
<OutputPath>Bin</OutputPath>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="BeforeBuild">
<!-- Build the analysis SSIS project -->
<Exec Command=""$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\#InstallDir)\devenv.exe" blah\blah.dtproj /Build" />
</Target>
</Project>
I had to slightly tweek my target to get it working:
<Target Name="BeforeBuild">
<!-- Build the analysis SSIS project -->
<Exec Command=""$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\#InstallDir)devenv.exe" "$(SolutionPath)" /Build "Release|Any CPU" /project projectFileName.dtproj" />
</Target>

Resources