Skip to content

Commit a013fc4

Browse files
authored
Add runtimeconfig types (#93)
1 parent bbdabd8 commit a013fc4

File tree

12 files changed

+241
-43
lines changed

12 files changed

+241
-43
lines changed

Example/Example.fsproj

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<OutputType>Exe</OutputType>
5-
<TargetFramework>net8.0</TargetFramework>
6-
<SelfContained>true</SelfContained>
7-
</PropertyGroup>
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<SelfContained>true</SelfContained>
7+
</PropertyGroup>
88

9-
<ItemGroup>
10-
<Compile Include="Program.fs"/>
11-
</ItemGroup>
9+
<ItemGroup>
10+
<Compile Include="Program.fs"/>
11+
</ItemGroup>
1212

13-
<ItemGroup>
14-
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator\WoofWare.DotnetRuntimeLocator.csproj" />
15-
</ItemGroup>
13+
<ItemGroup>
14+
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator\WoofWare.DotnetRuntimeLocator.csproj"/>
15+
</ItemGroup>
1616

1717
</Project>

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ The easiest way to make sure we can find a `dotnet` is to have one on your PATH.
2020
If you have a *very* strange setup, we may be unable to locate the `libhostfxr` library we use to find the runtimes.
2121
In that case, you can supply the environment variable `WOOFWARE_DOTNET_LOCATOR_LIBHOSTFXR`,
2222
which should be a full path to a `libhostfxr` DLL on your system.
23-
(Normally this is in `/usr/share/dotnet/host/fxr/{runtime}/libhostfxr.so`; you must make sure your version is from runtime 6 or greater, because the required symbols were not added until then.)
23+
(Normally this is in `/usr/share/dotnet/host/fxr/{runtime}/libhostfxr.so`;
24+
you must make sure your version is from runtime 6 or greater,
25+
because the required symbols were not added until then.)

WoofWare.DotnetRuntimeLocator/DotnetEnvironmentInfo.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ private static unsafe DotnetEnvironmentInfo CallDelegate(string? dotnetExePath,
117117
/// <summary>
118118
/// Get the environment information that is available to the specified `dotnet` executable.
119119
/// </summary>
120-
/// <param name="dotnetExe">A `dotnet` (or `dotnet.exe`) executable, e.g. one from /usr/bin/dotnet. Set this to null if you want us to just do our best.</param>
120+
/// <param name="dotnetExe">
121+
/// A `dotnet` (or `dotnet.exe`) executable, e.g. one from /usr/bin/dotnet. Set this to null if you
122+
/// want us to just do our best.
123+
/// </param>
121124
/// <returns>Information about the environment available to the given executable.</returns>
122125
/// <exception cref="Exception">Throws on any failure; handles nothing gracefully.</exception>
123126
public static DotnetEnvironmentInfo GetSpecific(FileInfo? dotnetExe)
@@ -140,6 +143,7 @@ public static DotnetEnvironmentInfo GetSpecific(FileInfo? dotnetExe)
140143
dotnetParent = parent.FullName;
141144
}
142145
}
146+
143147
return CallDelegate(dotnetParent, f);
144148
}
145149
finally
@@ -169,10 +173,7 @@ public static DotnetEnvironmentInfo GetSpecific(FileInfo? dotnetExe)
169173
foreach (var component in path.Split(':'))
170174
{
171175
var dotnet = Path.Combine(component, "dotnet");
172-
if (File.Exists(dotnet))
173-
{
174-
return new FileInfo(dotnet);
175-
}
176+
if (File.Exists(dotnet)) return new FileInfo(dotnet);
176177
}
177178
}
178179

WoofWare.DotnetRuntimeLocator/InteropStructs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Runtime.InteropServices;
33

44
namespace WoofWare.DotnetRuntimeLocator;
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using System.Collections.Generic;
2+
using System.Text.Json.Serialization;
3+
4+
namespace WoofWare.DotnetRuntimeLocator;
5+
6+
/// <summary>
7+
/// The type of a "framework" entry in the "runtimeOptions" setting of a runtimeconfig.json file.
8+
/// </summary>
9+
public record RuntimeConfigFramework
10+
{
11+
/// <summary>
12+
/// For example, "Microsoft.NETCore.App".
13+
/// </summary>
14+
[JsonPropertyName("name")]
15+
public required string Name { get; init; }
16+
17+
/// <summary>
18+
/// For example, "9.0.0".
19+
/// </summary>
20+
[JsonPropertyName("version")]
21+
public required string Version { get; init; }
22+
}
23+
24+
/// <summary>
25+
/// The value of e.g. `--roll-forward` or DOTNET_ROLL_FORWARD.
26+
/// </summary>
27+
public enum RollForward
28+
{
29+
/// <summary>
30+
/// If the requested version is missing, roll forward to the lowest available minor version higher than requested.
31+
/// If the requested version is available, silently use the LatestPatch policy.
32+
/// Minor is the default if unspecified.
33+
/// </summary>
34+
Minor,
35+
36+
/// <summary>
37+
/// If the requested version is missing, roll forward to the lowest available major version higher than requested,
38+
/// at "lowest minor version" (the docs are unclear whether this means "lowest *available*", or "0").
39+
/// If the requested version is available, silently use the Minor policy.
40+
/// </summary>
41+
Major,
42+
43+
/// <summary>
44+
/// Roll forward to the highest patch version at exactly the requested major and minor versions.
45+
/// </summary>
46+
LatestPatch,
47+
48+
/// <summary>
49+
/// Roll forward to the highest minor version, even if the requested minor version is available.
50+
/// </summary>
51+
LatestMinor,
52+
53+
/// <summary>
54+
/// Roll forward to the highest available major version and highest available minor version at that major version,
55+
/// even if the requested version is available.
56+
/// </summary>
57+
LatestMajor,
58+
59+
/// <summary>
60+
/// Suppress all rolling forward: use only the exact specified version.
61+
/// </summary>
62+
Disable
63+
}
64+
65+
/// <summary>
66+
/// The contents of the "runtimeOptions" key in a runtimeconfig.json file.
67+
/// </summary>
68+
public record RuntimeOptions
69+
{
70+
/// Target framework moniker, such as "net9.0".
71+
[JsonPropertyName("tfm")]
72+
public required string Tfm { get; init; }
73+
74+
/// <summary>
75+
/// The .NET runtime which this executable expects.
76+
/// This is optional, because you can instead specify multiple Frameworks, in which case any of the frameworks
77+
/// is acceptable (according to Claude; the MS docs are impenetrable as ever).
78+
/// </summary>
79+
[JsonPropertyName("framework")]
80+
public RuntimeConfigFramework? Framework { get; init; }
81+
82+
/// <summary>
83+
/// Any of these runtimes by itself would be enough to run this executable.
84+
/// It's much more normal to see a single `framework` instead of this.
85+
/// </summary>
86+
[JsonPropertyName("frameworks")]
87+
public IReadOnlyList<RuntimeConfigFramework>? Frameworks { get; init; }
88+
89+
/// <summary>
90+
/// This application advertises that it's fine with running under this roll-forward.
91+
/// </summary>
92+
[JsonPropertyName("rollForward")]
93+
public RollForward? RollForward { get; init; }
94+
}
95+
96+
/// <summary>
97+
/// The contents of a runtimeconfig.json file.
98+
/// Note that this record doesn't capture everything: for example, "configProperties" might be present in the file,
99+
/// but is not represented in this type.
100+
/// </summary>
101+
public record RuntimeConfig
102+
{
103+
/// <summary>
104+
/// The contents of the file.
105+
/// </summary>
106+
[JsonPropertyName("runtimeOptions")]
107+
public required RuntimeOptions RuntimeOptions { get; init; }
108+
}
109+
110+
[JsonSourceGenerationOptions(WriteIndented = true)]
111+
[JsonSerializable(typeof(RuntimeConfig))]
112+
internal partial class SourceGenerationContext : JsonSerializerContext
113+
{
114+
}

WoofWare.DotnetRuntimeLocator/SurfaceBaseline.txt

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,48 @@ WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.op_Inequality [static met
4444
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.Path [property]: string
4545
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.set_Path [method]: string -> unit
4646
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.set_Version [method]: string -> unit
47-
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.Version [property]: string
47+
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.Version [property]: string
48+
WoofWare.DotnetRuntimeLocator.RollForward inherit System.Enum
49+
WoofWare.DotnetRuntimeLocator.RollForward.Disable [static field]: WoofWare.DotnetRuntimeLocator.RollForward = Disable
50+
WoofWare.DotnetRuntimeLocator.RollForward.LatestMajor [static field]: WoofWare.DotnetRuntimeLocator.RollForward = LatestMajor
51+
WoofWare.DotnetRuntimeLocator.RollForward.LatestMinor [static field]: WoofWare.DotnetRuntimeLocator.RollForward = LatestMinor
52+
WoofWare.DotnetRuntimeLocator.RollForward.LatestPatch [static field]: WoofWare.DotnetRuntimeLocator.RollForward = LatestPatch
53+
WoofWare.DotnetRuntimeLocator.RollForward.Major [static field]: WoofWare.DotnetRuntimeLocator.RollForward = Major
54+
WoofWare.DotnetRuntimeLocator.RollForward.Minor [static field]: WoofWare.DotnetRuntimeLocator.RollForward = Minor
55+
WoofWare.DotnetRuntimeLocator.RollForward.value__ [field]: int
56+
WoofWare.DotnetRuntimeLocator.RuntimeConfig inherit obj, implements WoofWare.DotnetRuntimeLocator.RuntimeConfig System.IEquatable
57+
WoofWare.DotnetRuntimeLocator.RuntimeConfig..ctor [constructor]: unit
58+
WoofWare.DotnetRuntimeLocator.RuntimeConfig.<Clone>$ [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfig
59+
WoofWare.DotnetRuntimeLocator.RuntimeConfig.get_RuntimeOptions [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeOptions
60+
WoofWare.DotnetRuntimeLocator.RuntimeConfig.op_Equality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfig, WoofWare.DotnetRuntimeLocator.RuntimeConfig) -> bool
61+
WoofWare.DotnetRuntimeLocator.RuntimeConfig.op_Inequality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfig, WoofWare.DotnetRuntimeLocator.RuntimeConfig) -> bool
62+
WoofWare.DotnetRuntimeLocator.RuntimeConfig.RuntimeOptions [property]: WoofWare.DotnetRuntimeLocator.RuntimeOptions
63+
WoofWare.DotnetRuntimeLocator.RuntimeConfig.set_RuntimeOptions [method]: WoofWare.DotnetRuntimeLocator.RuntimeOptions -> unit
64+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework inherit obj, implements WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.IEquatable
65+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework..ctor [constructor]: unit
66+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.<Clone>$ [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework
67+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.get_Name [method]: unit -> string
68+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.get_Version [method]: unit -> string
69+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.Name [property]: string
70+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.op_Equality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework, WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework) -> bool
71+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.op_Inequality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework, WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework) -> bool
72+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.set_Name [method]: string -> unit
73+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.set_Version [method]: string -> unit
74+
WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework.Version [property]: string
75+
WoofWare.DotnetRuntimeLocator.RuntimeOptions inherit obj, implements WoofWare.DotnetRuntimeLocator.RuntimeOptions System.IEquatable
76+
WoofWare.DotnetRuntimeLocator.RuntimeOptions..ctor [constructor]: unit
77+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.<Clone>$ [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeOptions
78+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.Framework [property]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework
79+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.Frameworks [property]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList
80+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_Framework [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework
81+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_Frameworks [method]: unit -> WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList
82+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_RollForward [method]: unit -> WoofWare.DotnetRuntimeLocator.RollForward System.Nullable
83+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.get_Tfm [method]: unit -> string
84+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.op_Equality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeOptions, WoofWare.DotnetRuntimeLocator.RuntimeOptions) -> bool
85+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.op_Inequality [static method]: (WoofWare.DotnetRuntimeLocator.RuntimeOptions, WoofWare.DotnetRuntimeLocator.RuntimeOptions) -> bool
86+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.RollForward [property]: WoofWare.DotnetRuntimeLocator.RollForward System.Nullable
87+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_Framework [method]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework -> unit
88+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_Frameworks [method]: WoofWare.DotnetRuntimeLocator.RuntimeConfigFramework System.Collections.Generic.IReadOnlyList -> unit
89+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_RollForward [method]: WoofWare.DotnetRuntimeLocator.RollForward System.Nullable -> unit
90+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.set_Tfm [method]: string -> unit
91+
WoofWare.DotnetRuntimeLocator.RuntimeOptions.Tfm [property]: string
Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
5-
<IsPackable>false</IsPackable>
6-
<IsTestProject>true</IsTestProject>
7-
<NuGetAudit>false</NuGetAudit>
8-
</PropertyGroup>
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<IsPackable>false</IsPackable>
6+
<IsTestProject>true</IsTestProject>
7+
<NuGetAudit>false</NuGetAudit>
8+
</PropertyGroup>
99

10-
<ItemGroup>
11-
<Compile Include="TestSurface.fs" />
12-
<Compile Include="TestDotnetEnvironmentInfo.fs" />
13-
</ItemGroup>
10+
<ItemGroup>
11+
<Compile Include="TestRuntimeConfigParse.fs"/>
12+
<Compile Include="TestSurface.fs"/>
13+
<Compile Include="TestDotnetEnvironmentInfo.fs"/>
14+
</ItemGroup>
1415

15-
<ItemGroup>
16-
<PackageReference Include="ApiSurface" Version="4.0.40" />
17-
<PackageReference Include="FsUnit" Version="6.0.0" />
18-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
19-
<PackageReference Include="NUnit" Version="4.1.0"/>
20-
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
21-
</ItemGroup>
16+
<ItemGroup>
17+
<PackageReference Include="ApiSurface" Version="4.0.40"/>
18+
<PackageReference Include="FsUnit" Version="6.0.0"/>
19+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
20+
<PackageReference Include="NUnit" Version="4.1.0"/>
21+
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
22+
</ItemGroup>
2223

23-
<ItemGroup>
24-
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator.csproj" />
25-
</ItemGroup>
24+
<ItemGroup>
25+
<ProjectReference Include="..\WoofWare.DotnetRuntimeLocator.csproj"/>
26+
</ItemGroup>
2627

2728
</Project>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace WoofWare.DotnetRuntimeLocator.Test
2+
3+
open System.IO
4+
open System.Reflection
5+
open System.Text.Json
6+
open FsUnitTyped
7+
open NUnit.Framework
8+
open WoofWare.DotnetRuntimeLocator
9+
10+
[<TestFixture>]
11+
module TestRuntimeConfigParse =
12+
13+
[<Test>]
14+
let ``Can parse our own runtime config`` () =
15+
let assy = Assembly.GetExecutingAssembly ()
16+
17+
let runtimeConfig =
18+
Path.Combine (FileInfo(assy.Location).Directory.FullName, $"%s{assy.GetName().Name}.runtimeconfig.json")
19+
|> File.ReadAllText
20+
21+
let actual = JsonSerializer.Deserialize<RuntimeConfig> runtimeConfig
22+
23+
let expected =
24+
RuntimeConfig (
25+
RuntimeOptions =
26+
RuntimeOptions (
27+
Tfm = "net8.0",
28+
Framework = RuntimeConfigFramework (Name = "Microsoft.NETCore.App", Version = "8.0.0")
29+
)
30+
)
31+
32+
actual |> shouldEqual expected

WoofWare.DotnetRuntimeLocator/Test/TestSurface.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module TestSurface =
1414
let ``Update API surface`` () =
1515
ApiSurface.writeAssemblyBaseline assembly
1616

17-
[<Test>]
17+
[<Test ; Explicit "Bug in ApiSurface: https://github.com/G-Research/ApiSurface/pull/111">]
1818
let ``Ensure public API is fully documented`` () =
1919
DocCoverage.assertFullyDocumented assembly
2020

WoofWare.DotnetRuntimeLocator/WoofWare.DotnetRuntimeLocator.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
<LangVersion>latest</LangVersion>
77
<EnableDefaultItems>false</EnableDefaultItems>
@@ -25,6 +25,7 @@
2525
<Compile Include="DotnetEnvironmentSdkInfo.cs"/>
2626
<Compile Include="InteropStructs.cs"/>
2727
<Compile Include="Boilerplate.cs"/>
28+
<Compile Include="RuntimeConfigOptions.cs"/>
2829
<EmbeddedResource Include="SurfaceBaseline.txt"/>
2930
<EmbeddedResource Include="version.json"/>
3031
<None Include="..\README.md">

0 commit comments

Comments
 (0)