cognitedata / oryx

.NET Cross platform and highly composable middleware for building web request handlers in F#
Apache License 2.0
202 stars 10 forks source link

TypeInitializationException when creating SelfContained SingleFile executable #67

Closed kaeedo closed 3 years ago

kaeedo commented 3 years ago

Hello. I'm trying to use Oryx in a project that I want to distribute as a self contained single file executable. The project runs no problem when using normal dotnet build, but when I build a self contained exe, it throws a TypeInitializationException. Full message:

Unhandled exception. System.TypeInitializationException: The type initializer for '<StartupCode$Oryx>.$Context' threw an exception.
 ---> System.ArgumentException: The path is empty. (Parameter 'path')
   at System.IO.Path.GetFullPath(String path)
   at System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName)
   at <StartupCode$Oryx>.$Context..cctor()
   --- End of inner exception stack trace ---
   at Oryx.Context.get_defaultContext()
   at Program.main(String[] argv)

Command I used to build self contained exe: dotnet publish -r win-x64 -c Release -p:PublishSingleFile=true --self-contained true -o "./output" .\MyProj.fsproj

And here a minimal project to reproduce:

Program.fs:

open Oryx
open System.Net.Http
open Oryx.ThothJsonNet.ResponseReader
open Thoth.Json.Net
open FSharp.Control.Tasks.ContextInsensitive

[<EntryPoint>]
let main argv =
    use client = new HttpClient()
    let context =
        Context.defaultContext
        |> Context.withHttpClient client

    let response =
        GET
        >=> withUrl "https://api.github.com/repos/cognitedata/oryx/releases/latest"
        >=> fetch
        >=> json (Decode.field "tag_name" Decode.string)

    let _ =
        (task {
            let! tag = (response |> runAsync context)

            printfn "%A" tag

            return 0
        }).GetAwaiter().GetResult()

    0 // return an integer exit code

with following dependencies:

<PackageReference Include="Oryx" Version="2.0.0" />
<PackageReference Include="Oryx.ThothJsonNet" Version="2.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Ply" Version="0.3.1" />

Thank you for this project, and any help you may be able to provide

dbrattli commented 3 years ago

Hi, I think there must be something with your dotnet installation. I have no problems running your example

➜  minimal git:(master) ✗ dotnet publish -r win-x64 -c Release -p:PublishSingleFile=true --self-contained true -o "./output" ./minimal.fsproj
Microsoft (R) Build Engine version 16.8.0+126527ff1 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Restored /Users/dbrattli/Developer/Github/oryx/examples/minimal/minimal.fsproj (in 333 ms).
  minimal -> /Users/dbrattli/Developer/Github/oryx/examples/minimal/bin/Release/net5/win-x64/minimal.dll
  minimal -> /Users/dbrattli/Developer/Github/oryx/examples/minimal/output/
➜  minimal git:(master) ✗ dotnet run output/minimal.exe
Ok "v3.0.0-alpha-001"

Here is the project file I used:

<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Oryx" Version="2.0.0" />
        <PackageReference Include="Oryx.ThothJsonNet" Version="2.0.0" />
        <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
        <PackageReference Include="Ply" Version="0.3.1" />
    </ItemGroup>
    <ItemGroup>
        <Compile Include="Program.fs" />
    </ItemGroup>
</Project>
kaeedo commented 3 years ago

I think you're right. I managed to get it working when targeting netcoreapp3.1, but still building using the net 5 SDK. I'll play around with my dotnet installation.

Thanks