How to build an F# project via a .fsproj file? - f#

I have a single F# file which I build so far via
fsc --standalone Foo.fs
into a single executable file which I can distribute to others who have not installed the F# toolchain.
Now I thought I move to a .fsproj file which scales better the more files I add to my project. Consider the following .fsproj file:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="FSharp.NET.Sdk;Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FSharp.NET.Sdk" Version="1.0.*" PrivateAssets="All" />
<PackageReference Include="FSharp.Core" Version="4.5.*" />
<Compile Include="Foo.fsx" />
</ItemGroup>
</Project>
If I run dotnet build in a directory which contains both files, then I get the following output:
C:\Users\BillGates\.nuget\packages\fsharp.net.sdk\1.0.5\build\FSharp.NET.Core.Sdk.targets(170,9): error MSB6006: "dotnet.exe" exited with code -2147450730. [C:\temp\Foo.fsproj]
Searching for the error code -2147450730 did not help me. Any idea what is wrong with my setup? Any hints how to build a stand alone executable file from a F# file?
I'm using the following .NET versions:
dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 2.1.401
Commit: 91b1c13032
Runtime Environment:
OS Name: Windows
OS Version: 10.0.15063
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\2.1.401\
Host (useful for support):
Version: 2.1.3
Commit: 124038c13e
.NET Core SDKs installed:
2.1.401 [C:\Program Files\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
To install additional .NET Core runtimes or SDKs:
https://aka.ms/dotnet-download

DO not use FSharp.NET.Sdk with any recent tooling. It was an intermediate package as long as F# was not in the box. Nowadays F# is in the box and the following should give you a working version:
dotnet new -lang f#
dotnet build

Related

docker build fails to load .net image

I have a docker file which has following line of code. It works on an old Linux build machine but doesn't work on a new ubuntu build machine. On new machine it fails with error "net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)".
FROM microsoft/aspnetcore-build:2.0
RUN dotnet restore -s <url> <project path>
RUN dotnet publish <project path> -c Release -o <path>
.NET 2.0 is not available anymore because the EOL is reached.
Try to migrate your application to at least .NET Core 3.1 or even .NET 6.0 (LTS) / 7.0
/// To .NET Core 3.1
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>
/// To .NET 7
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
</Project>
Docker images can be found here for example:
mcr.microsoft.com/dotnet/aspnet:7.0

Migrations EF Core 3.1

I'm getting the following error trying to create a migration using EF Core 3.1.
PM> add-migration InitialDB
Unable to resolve startup project ''.
Using project 'UI\UI.Web' as the startup project.
Build started...
Build succeeded.
System.IO.FileLoadException: Could not load file or assembly 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Could not load file or assembly 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Is there any thing I need to do to get my project to get migrations to support .NET Core 3.0/3.1?
Any help would be greatly appreciated.
I recently ran into the same issue for myself after upgrading my EF Core from 2.2 to 3.1.6, and after some investigating into the issue, it looks like if you try and bump up your RuntimeFrameworkVersion in your .csproj file it may fix the issue. This seemed to fix it for me, remember that there are only certain compatible .NET Core frameworks available based on your configuration. If you incorrectly set it to a version that does not exist, you will see this
It was not possible to find any compatible framework version
The framework 'Microsoft.NETCore.App', version '3.1.0' was not found.
- The following frameworks were found:
2.0.9 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
2.1.0 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
2.1.7 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
2.1.11 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
2.1.20 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
3.1.6 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
After updating the RuntimeFrameworkVersion that you have supported on your development environment, your .csproj may look something like this
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PublishWithAspNetCoreTargetManifest>false</PublishWithAspNetCoreTargetManifest>
<GenerateRuntimeConfigurationFiles> true</GenerateRuntimeConfigurationFiles>
<RuntimeFrameworkVersion>3.1.6</RuntimeFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
Hope this assists you as it assisted me. But if it does not, you may also edit the .csproj file to enable all private and entity assets to be included
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
P.S. First time posting an answer on stack overflow, so I apologize in advance if this does not assist you and I hope it helps you.

InvalidProjectFileException: "The SDK 'Microsoft.NET.Sdk.Web' not found" from Microsoft.Build.Evaluation.Project after upgrading to VS2019

We have a tool that loads a csproj file with Microsoft.Build.Evaluation.Project. It's been working fine for about a year, until we tried running it on a machine with VS2019 installed (and no copy of VS2017). Interestingly enough, it does build just fine with dotnet build -- it's only the Build Evaluation that complains about it.
I did see some suggestions to install the 32-bit version of some packages. I didn't try that, but I did try running my executable in 64-bit mode, and it still threw the InvalidProjectFileException.
I suspect that I may need to make a small update to point to a different toolset, but since I'm not the author of the code, I'm not entirely sure where to make that change. Any suggestions?
Thanks!
The exception that's thrown:
Unhandled Exception: Microsoft.Build.Exceptions.InvalidProjectFileException: The SDK 'Microsoft.NET.Sdk.Web' specified could not be found. c:\foo\bar\baz.csproj
at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject[T1](IElementLocation elementLocation, String resourceName, T1 arg0)
at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImportsFromUnescapedImportExpressionConditioned(String directoryOfImportingFile, ProjectImportElement importElement, List`1& projects, SdkResult& sdkResult, Boolean throwOnFileNotExistsError)
at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImports(String directoryOfImportingFile, ProjectImportElement importElement, SdkResult& sdkResult)
at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(ILoggingService loggingService, BuildEventContext buildEventContext)
at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(IEvaluatorData`4 data, ProjectRootElement root, ProjectLoadSettings loadSettings, Int32 maxNodeCount, PropertyDictionary`1 environmentProperties, ILoggingService loggingService, IItemFactory`2 itemFactory, IToolsetProvider toolsetProvider, ProjectRootElementCache projectRootElementCache, BuildEventContext buildEventContext, ISdkResolverService sdkResolverService, Int32 submissionId, EvaluationContext evaluationContext)
at Microsoft.Build.Evaluation.Project.Reevaluate(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
at Microsoft.Build.Evaluation.Project.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
at Microsoft.Build.Evaluation.Project..ctor(String projectFile)
The .csproj in question looks like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphQL" Version="2.4.0" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="3.4.0" />
<PackageReference Include="GraphQL.Server.Transports.WebSockets" Version="3.4.0" />
<PackageReference Include="GraphQL.Server.Ui.GraphiQL" Version="3.4.0" />
<PackageReference Include="GraphQL.Server.Ui.Playground" Version="3.4.0" />
<PackageReference Include="GraphQL.Server.Ui.Voyager" Version="3.4.0" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<!-- About a dozen references to other .csproj files -->
</ItemGroup>
<ItemGroup>
<Content Update="config\FooBar.Config.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
Here's some information from dotnet.exe:
$ dotnet --list-sdks
2.1.302 [C:\Program Files\dotnet\sdk]
2.1.400 [C:\Program Files\dotnet\sdk]
2.1.503 [C:\Program Files\dotnet\sdk]
2.1.508 [C:\Program Files\dotnet\sdk]
2.1.802 [C:\Program Files\dotnet\sdk]
3.0.100 [C:\Program Files\dotnet\sdk]
$ dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 2.1.508
Commit: 9ba8583e91
Runtime Environment:
OS Name: Windows
OS Version: 6.3.9600
OS Platform: Windows
RID: win81-x64
Base Path: C:\Program Files\dotnet\sdk\2.1.508\
Host (useful for support):
Version: 3.0.0
Commit: 7d57652f33
.NET Core SDKs installed:
2.1.302 [C:\Program Files\dotnet\sdk]
2.1.400 [C:\Program Files\dotnet\sdk]
2.1.503 [C:\Program Files\dotnet\sdk]
2.1.508 [C:\Program Files\dotnet\sdk]
2.1.802 [C:\Program Files\dotnet\sdk]
3.0.100 [C:\Program Files\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
To install additional .NET Core runtimes or SDKs:
https://aka.ms/dotnet-download
$ type ..\..\..\global.json
{
"sdk": {
"version": "2.1.508"
}
}
VS 2019. I had the same problem. I was able to fix it via setting the MSBUILD_EXE_PATH environment variable.
Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", sdkPath);
The trick is that you have to specify the actual MSBuild.exe path (if you have different VSs versions installed, that could be a task to find out the right one).
Here is the code snippet. From the https://github.com/RicoSuter/DNT guys.
private static void SetMsBuildExePath()
{
try
{
var startInfo = new ProcessStartInfo("dotnet", "--list-sdks")
{
RedirectStandardOutput = true,
UseShellExecute = false
};
var process = Process.Start(startInfo);
process.WaitForExit(1000);
var output = process.StandardOutput.ReadToEnd();
var sdkPaths = Regex.Matches(output, "([0-9]+.[0-9]+.[0-9]+) \\[(.*)\\]")
.OfType<Match>()
.Select(m => System.IO.Path.Combine(m.Groups[2].Value, m.Groups[1].Value, "MSBuild.dll"));
var sdkPath = sdkPaths.Last();
Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", sdkPath);
}
catch (Exception exception)
{
}
}
Just use that method before the building process, I assume that will fix the described problem.

Where does Ionide + Fake put the output executable?

I am trying to use .NET Core + Ionide + VS Code + Fake + Paket on macOS High Sierra.
Using the project generator, I have created a Suave application called Test. Ionide seems to have generated the appropriate files. After tweaking the TargetFramework to .NET Core, I can build successfully:
$ ./build.sh
...
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.72
Finished Target: Build
---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target Duration
------ --------
Clean 00:00:00.0026904
InstallDotNetCLI 00:00:01.2292511
Restore 00:00:04.2731055
Build 00:00:07.1234434
Total: 00:00:12.7035334
---------------------------------------------------------------------
Status: Ok
---------------------------------------------------------------------
There are now some files in Test/bin, but none of them are .exe, which is what I would expect as output from fsharpc.
Where does Ionide + Fake put the output executable?
My project has OutputType executable:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Test.fs" />
</ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>
.Net Core compiles all projects (even executable applications) to .dll not .exe that can be run with dotnet PATH_TO_DLL. In the bin folder, in the subfolder for given framework target there should be file YOUR_PROJECT_NAME.dll that can be run with dotnet CLI.
To generate an exe you need to supply a run-time identifier. You can include this in the fsproj with
<PropertyGroup>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
</PropertyGroup>
but you don't need to do that. You can use VSCode's tasks.json file to set up a build task.
My suggestion is just to run the dotnet CLI:
dotnet build -c Release -r win10-x64
This will create an exe in the bin\release\netcoreapp2.0\win10-x64 folder. You can also dotnet publish if you want a self-contained directory to deploy (this can get large). The id for OSX will be something like osx-x64.
By default ionide generates an fsproj file that is targetting net461, and you might also need Fake 5 for dotnetcore. I also suggest you use paket in magic-mode, and commit the .exe to github (if you use git).

fsharp compilation fails under Mono with an NuGet error

Update. With Matt Ward's help I traced this to a bad config file. The following ~/.config/NuGet/NuGet.Config works for me
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" protocolVersion="2" />
</packageSources>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
I can do the following without any problems:
/opt/mono/mono-5.2.0.196-tarball/bin/mono ~/nuget.exe install -version 2.6.4 nunit
However, when I try to compile fsharp under the same installation of Mono, I get the following error. This is in the fsharp4 branch. What might I be doing wrong, please? Many thanks.
Project "/dir/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj"
(default target(s)): Target CallFsSrGen: Created directory
"obj/proto/./" Tool
/dir/src/fsharp/FSharp.Build-proto/../../../lib/bootstrap/4.0/fssrgen.exe
execution started with arguments:
/dir/src/fsharp/FSharp.Build/FSBuild.txt obj/proto/./FSBuild.fs
FSBuild.resx Target BeforeBuild: Executing: mono
--runtime=v4.0.30319 /dir/src/fsharp/FSharp.Build-proto/../../../.nuget/NuGet.exe restore
packages.config -PackagesDirectory packages Unable to find version
'2.6.4' of package 'NUnit'. Unable to find version '2.6.4' of
package 'NUnit.Runners'. /dir/src/FSharpSource.targets: error :
Command 'mono --runtime=v4.0.30319
/dir/src/fsharp/FSharp.Build-proto/../../../.nuget/NuGet.exe restore
packages.config -PackagesDirectory packages' exited with code: 1.
Task "Exec" execution -- FAILED Done building target "BeforeBuild"
in project
Check what version of NuGet you are using and what NuGet package sources are enabled. Either there no NuGet package sources enabled or you are using a NuGet v2 .exe with a NuGet v3 package source.
If there is no NuGet.Config file that is provided with the FSharp build source code you are using then check the package sources listed in the file ~/.config/NuGet/NuGet.config. I suspect that it only has the v3 package source https://api.nuget.org/v3/index.json which cannot be used with a NuGet.exe (v2). So you would either need to update the nuget.exe to a later version or add the NuGet v2 package source into your NuGet.Config file: https://www.nuget.org/api/v2/

Resources