I have installed Visual Studio 2017 with F# support on my PC and I have MSBuild targets in C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\FSharp and F# 4.1 SDK in C:\Program Files (x86)\Microsoft SDKs\F#\4.1
I have installed Build Tools for Visual Studio 2017 (from https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=15 ) but there is no option to install F# SDK so building F# projects using MSBuild 15 fails.
How can I install F# 4.1 SDK without installing Visual Studio?
There is an MSI that can be installed, it's not yet been published on MSDN.
But it will be shortly.
You can track the issue here: on GitHub:
"Deploy FSharp Tools MSI to MSDN #2553"
https://github.com/Microsoft/visualfsharp/issues/2553
Kevin Ransom
A short term fix until the SDK can be installed separately is to add a directive to the project file to look in the NuGet packages folder for the Microsoft.FSharp.Targets file. Here are steps I took to fix this:
Ensure your using the new F# project from VS.NET 2017 as its has this directive:
<Import Project="..\packages\FSharp.Compiler.Tools.4.1.17\build\FSharp.Compiler.Tools.props" Condition="Exists('..\packages\FSharp.Compiler.Tools.4.1.17\build\FSharp.Compiler.Tools.props')" />
Replace this section of the project file:
<Choose>
<When Condition="$(TargetFSharpCoreVersion) >= 4.3.0.0 AND $(TargetFSharpCoreVersion) < 4.3.1.0 ">
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<When Condition="$(TargetFSharpCoreVersion) >= 4.3.1.0 AND $(TargetFSharpCoreVersion) < 4.4.0.0 ">
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<When Condition="$(TargetFSharpCoreVersion) >= 4.4.0.0 AND $(TargetFSharpCoreVersion) < 4.4.1.0 ">
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\4.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\4.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
With this XML:
<Choose>
<When Condition="$(TargetFSharpCoreVersion) >= 4.3.0.0 AND $(TargetFSharpCoreVersion) < 4.3.1.0 ">
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<When Condition="$(TargetFSharpCoreVersion) >= 4.3.1.0 AND $(TargetFSharpCoreVersion) < 4.4.0.0 ">
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<When Condition="$(TargetFSharpCoreVersion) >= 4.4.0.0 AND $(TargetFSharpCoreVersion) < 4.4.1.0 ">
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\4.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildProgramFiles32)\Microsoft SDKs\F#\4.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<!-- This is needed for TeamCity where F# SDK is only available via NuGet right now - hopefully can be removed at some point once the SDK is available for install -->
<PropertyGroup Condition="!Exists('$(FSharpTargetsPath)')">
<FSharpTargetsPath>$(FscToolPath)\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
Ensure you build server has a restore NuGet packages step prior to doing the build
Ensure you packages file includes: FSharp.Compiler.Tools and FSharp.Core
The reason this works is as follows:
This checks to see if the FSharpTargetsPath exists and if not use the packages folder as the source. You don't want to always use the packages folder otherwise on a fresh checkout on a users machine the packages aren't available and the build will fail. For this to work on the build server this assumes you have a step to restore the NuGet packages PRIOR to doing the build.
It seems it's so new things haven't been updated yet.
Four step process for installing for a build server (scroll down to Option 3)
http://fsharp.org/use/windows/
(4.0)
According to the MSDN blog...
https://blogs.msdn.microsoft.com/dotnet/2017/03/07/announcing-f-4-1-and-the-visual-f-tools-for-visual-studio-2017-2/
Seems you at least need .NET Core / CLI
Searching on Microsoft's site doesn't seem to find anything...
Closest thing would be the 4.0 tools:
https://www.microsoft.com/en-us/download/details.aspx?id=48179
There are alse the raw NuGet packages (4.1)
https://www.nuget.org/packages/FSharp.Compiler.Tools
https://www.nuget.org/packages/FSharp.Core
Bottom line: I think its so new it hasn't been released in a format similar to previous versions yet. I'll keep checking every 24 hours to see if they update it on their website.
Related
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.
I'm trying to build a F# project (console) on Ubuntu 17.10 (Mono 4.6.2) however I run into F# core .NET issues. For reference, I'm using Visual Studio Code 1.21.2 and ionide extensions (new project and FAKE build). Below is the output.
I've tried adding an explicit reference to different versions of Fsharp.core e.g. 4.2, 4.3.4 with no luck.
Where should I be looking at to sort this out?
Finished Target: InstallDotNetCLI
Starting Target: Restore (==> InstallDotNetCLI)
/home/lear/.local/share/dotnetcore/dotnet restore
Restoring packages for /home/lear/src/fsTest/fsTest/fsTest.fsproj...
/home/lear/src/fsTest/fsTest/fsTest.fsproj : error NU1100: Unable to resolve 'FSharp.Core (>= 4.3.4)' for '.NETFramework,Version=v4.6.1'.
Restore failed in 99.61 ms for /home/lear/src/fsTest/fsTest/fsTest.fsproj.
Running build failed.
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.3.4" />
</ItemGroup>
The project file looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net461</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="fsTest.fsproj">
<Name>fsTest.fsproj</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="fsTest.fs" />
<None Include="App.config" />
</ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>
I used this instructions as reference for my setup:
Four easy steps for installing F# on Ubuntu Linux (2017-07-03)
The project file specifies the wrong TargetFramework. Changing that to e.g. netcoreapp2.0 Target Framework Moniker should fix the build.
The project you are trying to build/restore is referencing itself. Just remove this portion from the fsproj file:
<ItemGroup>
<ProjectReference Include="fsTest.fsproj">
<Name>fsTest.fsproj</Name>
</ProjectReference>
</ItemGroup>
I have an web project Project A and a library Project B.
Project B is being built into Project A\Plugins.
The Problem is when Project A is being built via CI Project B isn't deployed with Project A. MSBuild params in CI are:
/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactstagingdirectory)\\" /t:ProjectA
I added the following piece of code into Project A.csproj to deploy Project B with A:
<ItemGroup>
<ProjectsToBuild Include="..\..\Plugins\**\*ProjectB*proj" />
</ItemGroup>
<Target Name="Plugin" AfterTargets="Build">
<Message Text="Building Plugins" Importance="High" />
<MSBuild Projects="#(ProjectsToBuild)" ContinueOnError="false" Properties="Configuration=$(Configuration)">
<Output ItemName="OutputFiles" TaskParameter="TargetOutputs" />
</MSBuild>
<CallTarget Targets="CopyPlugins"/>
</Target>
<PropertyGroup>
<PluginDirectory>Plugins</PluginDirectory>
</PropertyGroup>
<Target Name="CopyPlugins">
<Message Text="Copying plugins to $(_PackageTempDir)\Plugins\ ($(ProjectDir)$(PluginDirectory))" Importance="high" />
<CreateItem Include="$(ProjectDir)$(PluginDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="PluginFiles" />
</CreateItem>
<Copy DestinationFolder="$(_PackageTempDir)\Plugins\" SourceFiles="#(PluginFiles)" SkipUnchangedFiles="true" />
</Target>
In the log executing order seems fine (Copy after Build), but after being deployed the Plugin folder doesn't exist on the target server.
Am I missing anything?
The files need to be included in the project. Since the files are generated dynamically, you can add this code to project file (e.g. XX.csproj)
<Content Include="plugin\**\*.*" />
From your description, you would need to check in Project A\Plugins folder into TFS. But it's not suggested.
We suggest you make a project reference in the same solution or create NuGet for package management. It's recommended to build a nuget package for Project B, and publish this Nuget package, then restore the library to Project A when you build it.
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.
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.