Proof of concept (#1)

This commit is contained in:
Patrick Stevens
2022-07-30 09:12:08 +01:00
committed by GitHub
parent 6aa93093da
commit e79c93f5e1
15 changed files with 4214 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
.idea/
*.user
*.DotSettings
/result
/.profile*

10
MauiDotnetFlake/Async.fs Normal file
View File

@@ -0,0 +1,10 @@
namespace MauiDotnetFlake
[<RequireQualifiedAccess>]
module Async =
let map<'a, 'b> (f : 'a -> 'b) (x : Async<'a>) : Async<'b> =
async {
let! x = x
return f x
}

159
MauiDotnetFlake/Domain.fs Normal file
View File

@@ -0,0 +1,159 @@
namespace MauiDotnetFlake
open System
open System.Collections.Immutable
open System.ComponentModel
open Newtonsoft.Json
type [<JsonConverter (typeof<PackKeyJsonConverter>) ; TypeConverter (typeof<PackKeyTypeConverter>)>] PackKey =
| PackKey of string
/// Human-readable round-trip representation
override this.ToString () =
match this with
| PackKey p -> p
and PackKeyJsonConverter () =
inherit JsonConverter<PackKey> ()
override _.ReadJson (reader : JsonReader, objectType : Type, _existingValue : PackKey, _ : bool, _ : JsonSerializer) =
if objectType <> typeof<PackKey> then
failwith $"Unexpected object type for pack key: {objectType}"
let value = reader.Value |> unbox<string>
PackKey value
override _.WriteJson (writer : JsonWriter, PackKey key, _ : JsonSerializer) : unit =
writer.WriteValue key
and PackKeyTypeConverter () =
inherit TypeConverter ()
override _.CanConvertFrom (_, t : Type) : bool =
t = typeof<string>
override _.ConvertFrom (_, _, v : obj) : obj =
v |> unbox<string> |> PackKey |> box
type [<JsonConverter (typeof<WorkloadKeyJsonConverter>) ; TypeConverter (typeof<WorkloadKeyTypeConverter>)>] WorkloadKey =
| WorkloadKey of string
and WorkloadKeyJsonConverter () =
inherit JsonConverter<WorkloadKey> ()
override _.ReadJson (reader : JsonReader, objectType : Type, _existingValue : _, _ : bool, _ : JsonSerializer) : WorkloadKey =
if objectType <> typeof<WorkloadKey> then
failwith $"Unexpected object type for workload key: {objectType}"
let value = reader.Value |> unbox<string> |> WorkloadKey
value
override _.WriteJson (_ : JsonWriter, _ : WorkloadKey, _ : JsonSerializer) : unit =
failwith "do not call"
and WorkloadKeyTypeConverter () =
inherit TypeConverter ()
override _.CanConvertFrom (_, t : Type) : bool =
t = typeof<string>
override _.ConvertFrom (_, _, v : obj) : obj =
v |> unbox<string> |> WorkloadKey |> box
type WorkloadManifest =
{
/// e.g. ".NET MAUI SDK for all platforms"
Description : string
/// e.g. ["maui-blazor"]
Extends : WorkloadKey list
/// e.g. ["Microsoft.MAUI.Dependencies"]
Packs : PackKey list
}
type [<JsonConverter (typeof<PackManifestKindJsonConverter>) ; TypeConverter (typeof<PackManifestKindTypeConverter>)>] PackManifestKind =
| Library
| Framework
| Sdk
| Template
static member Parse (value : string) =
match value.ToLowerInvariant () with
| "library" -> PackManifestKind.Library
| "sdk" -> PackManifestKind.Sdk
| "framework" -> PackManifestKind.Framework
| "template" -> PackManifestKind.Template
| _ -> failwith $"Unexpected value in pack manifest kind: {value}"
member this.ToInt =
match this with
| Library -> 2
| Framework -> 1
| Sdk -> 0
| Template -> 3
override this.ToString () =
match this with
| Library -> "library"
| Framework -> "framework"
| Sdk -> "sdk"
| Template -> "template"
and PackManifestKindJsonConverter () =
inherit JsonConverter<PackManifestKind> ()
override _.ReadJson (reader : JsonReader, objectType : Type, _existingValue : PackManifestKind, _ : bool, _ : JsonSerializer) : PackManifestKind =
if objectType <> typeof<PackManifestKind> then
failwith $"Unexpected object type for pack manifest kind: {objectType}"
PackManifestKind.Parse (reader.Value |> unbox<string>)
override _.WriteJson (w : JsonWriter, v : PackManifestKind, _ : JsonSerializer) : unit =
w.WriteValue v.ToInt
and PackManifestKindTypeConverter () =
inherit TypeConverter ()
override _.CanConvertFrom (_, t : Type) : bool =
t = typeof<string>
override _.CanConvertTo (_, t : Type) : bool =
t = typeof<int>
override _.ConvertFrom (_, _, v : obj) : obj =
v |> unbox<string> |> PackManifestKind.Parse |> box
override _.ConvertTo (_, _, v : obj, _destType : Type) : obj =
(v |> unbox<PackManifestKind>).ToInt
type PackManifest =
{
Kind : PackManifestKind
Version : Version
/// Map of "win-x64": "nuget-package-name", for example
[<JsonProperty "alias-to">]
AliasTo : ImmutableDictionary<string, string>
}
type Manifest =
{
Version : Version
Workloads : Map<WorkloadKey, WorkloadManifest>
Packs : Map<PackKey, PackManifest>
}
type Registration =
{
Id : PackKey
Version : Version
Kind : PackManifestKind
ResolvedPackageId : PackKey
Path : string
IsStillPacked : bool
}
type HashString =
| HashString of string
override this.ToString () =
match this with
| HashString s -> s
/// A NuGet package such as "Microsoft.Maui.Controls.Ref.android".
type Pack =
{
Name : PackKey
Version : Version
Hash : HashString
Type : PackManifestKind
}
type WorkloadCollation =
{
/// The NuGet package that defines the manifest for this workload.
Package : string
/// The version of the NuGet package that defines the manifest for this workload.
Version : string
/// The SHA256 of the NuGet package that defines the manifest for this workload.
Hash : HashString
/// The rendered manifest of this workload.
Manifest : Manifest
}
type Platform =
| Platform of string
override this.ToString () =
match this with
| Platform p -> p

19
MauiDotnetFlake/Hash.fs Normal file
View File

@@ -0,0 +1,19 @@
namespace MauiDotnetFlake
open System
open System.IO
open System.Security.Cryptography
[<RequireQualifiedAccess>]
module Hash =
let getAsync (stream : Stream) =
async {
use c = SHA256.Create ()
let! ct = Async.CancellationToken
stream.Seek (0, SeekOrigin.Begin) |> ignore
let! hash = c.ComputeHashAsync (stream, ct) |> Async.AwaitTask
return
hash
|> Convert.ToBase64String
|> HashString
}

15
MauiDotnetFlake/Map.fs Normal file
View File

@@ -0,0 +1,15 @@
namespace MauiDotnetFlake
[<RequireQualifiedAccess>]
module Map =
let union<'k, 'v when 'k : comparison> (merge : 'v -> 'v -> 'v) (m1 : Map<'k, 'v>) (m2 : Map<'k, 'v>) =
(m1, m2)
||> Map.fold (fun acc k v ->
acc
|> Map.change k (function
| None -> Some v
| Some v2 -> Some (merge v v2)
)
)

16
MauiDotnetFlake/Maui.sln Normal file
View File

@@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "maui-dotnet-flake", "maui-dotnet-flake.fsproj", "{5BE1A4A9-5DB9-4D3D-AC4D-EEBC0009257F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5BE1A4A9-5DB9-4D3D-AC4D-EEBC0009257F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BE1A4A9-5DB9-4D3D-AC4D-EEBC0009257F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BE1A4A9-5DB9-4D3D-AC4D-EEBC0009257F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BE1A4A9-5DB9-4D3D-AC4D-EEBC0009257F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

355
MauiDotnetFlake/Program.fs Normal file
View File

@@ -0,0 +1,355 @@
namespace MauiDotnetFlake
open System
open System.Collections.Generic
open System.IO
open System.IO.Compression
open System.Net.Http
open Newtonsoft.Json
module Program =
[<Literal>]
let LOCAL_CACHE = true
let source =
if LOCAL_CACHE then
let dir = DirectoryInfo "/tmp/pkgs/"
if not dir.Exists then dir.Create ()
dir.EnumerateFiles ("*.nupkg", SearchOption.AllDirectories)
|> Seq.map (fun fi -> fi.Name.Substring(0, fi.Name.Length - ".nupkg".Length).ToLowerInvariant(), fi)
|> readOnlyDict
else
Dictionary ()
:> IReadOnlyDictionary<_, _>
let fetchZip (client : HttpClient) (uri : Uri) : Stream Async =
async {
let! ct = Async.CancellationToken
try
let! s = Async.AwaitTask (client.GetStreamAsync (uri, ct))
return s
with
| e ->
return raise (AggregateException(uri.ToString (), e))
}
let rec waitForReady (file : FileInfo) : Async<Stream> =
async {
try
return file.OpenRead () :> Stream
with
| e ->
if e.Message.Contains "is being used by another process" then
do! Async.Sleep (TimeSpan.FromSeconds 5.0)
return! waitForReady file
else
return raise e
}
let fetchPackageStream (client : HttpClient) (PackKey packKey) (version : Version) : Async<Stream> =
let download =
lazy
let uri = Uri $"https://www.nuget.org/api/v2/package/{packKey}/{version}"
async {
try
use! zip = fetchZip client uri
let destFile = $"/tmp/pkgs/{packKey.ToLowerInvariant()}.{version}.nupkg"
try
do
use dest = File.OpenWrite destFile
zip.CopyTo dest
return File.OpenRead destFile :> Stream
with
| e ->
if e.Message.Contains "is being used by another process" then
return! waitForReady (FileInfo destFile)
else
return raise e
with
| e ->
return raise (AggregateException(uri.ToString (), e))
}
match source.TryGetValue $"{packKey.ToLowerInvariant()}.{version}" with
| true, v ->
async {
let s = v.OpenRead ()
return s
}
| false, _ ->
match source.TryGetValue $"{packKey.ToLowerInvariant()}" with
| true, v ->
if v.Directory.Name = version.ToString () then
async {
let s = v.OpenRead ()
return s
}
else
//failwith $"Unexpected version, wanted {version.ToString()} but cached {v.Directory.Name}"
download.Force ()
| false, _ ->
download.Force ()
let fetchPackageHash (client : HttpClient) =
// Not necessary, but speeds it up a fair bit
let memo = System.Collections.Concurrent.ConcurrentDictionary<PackKey * Version, HashString> ()
fun (packKey : PackKey) (version : Version) ->
async {
match memo.TryGetValue ((packKey, version)) with
| true, v -> return v
| false, _ ->
use! stream = fetchPackageStream client packKey version
let! answer = Hash.getAsync stream
memo.TryAdd ((packKey, version), answer) |> ignore
return answer
}
let fetchManifest' (contents : Stream) : Manifest Async =
async {
use arch = new ZipArchive (contents)
let deps = arch.GetEntry "data/WorkloadManifest.json"
let! entry =
async {
use entry = new StreamReader (deps.Open ())
return! entry.ReadToEndAsync () |> Async.AwaitTask
}
return JsonConvert.DeserializeObject<Manifest> entry
}
/// Download the specified nupkg and parse out the dependencies it implies.
let fetchManifest (manifest : FileInfo) : Manifest Async =
async {
use s = manifest.OpenRead ()
return! fetchManifest' s
}
let flatten (client : HttpClient) (workloadName : WorkloadKey option) (manifest : Manifest) : State Async =
manifest.Packs
|> Map.toSeq
|> Seq.collect (fun (packKey, packManifest) ->
match packManifest.AliasTo with
| null ->
Seq.singleton None
| map ->
map
|> Seq.map (fun (KeyValue(platform, pack)) -> Some (Platform platform, PackKey pack))
|> Seq.map (fun platform ->
match platform with
| None ->
async {
let! packageHash = fetchPackageHash client packKey packManifest.Version
return
None,
{
Name = packKey
Hash = packageHash
Version = packManifest.Version
Type = packManifest.Kind
}
}
| Some (platform, resolvedPack) ->
async {
let! packageHash = fetchPackageHash client resolvedPack packManifest.Version
return
Some (platform, packKey),
{
Name = resolvedPack
Hash = packageHash
Version = packManifest.Version
Type = packManifest.Kind
}
}
)
)
|> Async.Parallel
|> Async.map (Array.fold (fun state (platform, pack)->
match platform with
| None ->
State.addPack pack state
| Some (platform, beforeResolution) ->
State.addAlias platform beforeResolution pack state
) (State.Empty workloadName))
let dotnet =
Path.Combine (typeof<int>.Assembly.Location, "..", "..", "..", "..", "bin", "dotnet")
|> FileInfo
let allAvailableWorkloads (sdkVersion : string) : Async<_> =
async {
let psi = System.Diagnostics.ProcessStartInfo (dotnet.FullName, Arguments = $"workload update --print-download-link-only --sdk-version {sdkVersion}")
psi.RedirectStandardError <- true
psi.RedirectStandardOutput <- true
use pr = new System.Diagnostics.Process()
pr.StartInfo <- psi
if not (pr.Start ()) then
failwith $"failed to start {dotnet}"
let! ct = Async.CancellationToken
do! Async.AwaitTask (pr.WaitForExitAsync ct)
let output = pr.StandardOutput.ReadToEnd ()
match output.Split("==") with
| [| _ ; "allPackageLinksJsonOutputStart" ; desired ; "allPackageLinksJsonOutputEnd" ; "\n" |] ->
return
System.Text.Json.JsonSerializer.Deserialize<string list> desired
|> List.map (fun uri ->
match uri.Split "/" with
| [| "https:" ; "" ; "api.nuget.org" ; "v3-flatcontainer" ; package ; version ; _path |] ->
{| Package = package ; Version = version |}, Uri uri
| _ -> failwith $"Unrecognised URL format: {uri}"
)
|> Map.ofList
| _ ->
return failwith $"Unexpected formatting: {output}"
}
let requiredWorkloads (w : WorkloadKey) (m : Manifest) : WorkloadKey Set =
let rec go (toAcc : WorkloadKey list) (results : WorkloadKey Set) =
match toAcc with
| [] -> results
| x :: toAcc ->
match Map.tryFind x m.Workloads with
| None ->
go toAcc (Set.add x results)
| Some found ->
if Object.ReferenceEquals (null, found.Extends) then
go toAcc results
else
go (found.Extends @ toAcc) results
go [w] Set.empty
/// Find the manifests which define a given WorkloadKey.
let collate
(manifests : seq<WorkloadCollation>)
: Map<WorkloadKey, WorkloadCollation>
=
manifests
|> Seq.collect (fun collation ->
collation.Manifest.Workloads
|> Map.toSeq
|> Seq.map (fun (workload, _manifest) ->
workload, collation
)
)
|> Seq.groupBy fst
|> Seq.map (fun (key, values) ->
// Here is the assertion that each WorkloadKey is defined in exactly one workload
key, Seq.map snd values |> Seq.exactlyOne
)
|> Map.ofSeq
/// Render this workload as Nix, and also return our dependency workloads
let renderWorkload
(client : HttpClient)
(allAvailableWorkloads : Map<WorkloadKey, WorkloadCollation>)
(desiredWorkload : WorkloadKey)
: Async<NixInfo * WorkloadKey Set>
=
let collation =
match Map.tryFind desiredWorkload allAvailableWorkloads with
| None -> failwith $"You gave us {desiredWorkload} but there's no workload with that name"
| Some collation -> collation
let requiredWorkloads = requiredWorkloads desiredWorkload collation.Manifest
async {
let! flattened = flatten client (Some desiredWorkload) collation.Manifest
return State.toNix collation flattened, requiredWorkloads
}
let collectAllRequiredWorkloads
(client : HttpClient)
(allAvailableWorkloads : Map<WorkloadKey, WorkloadCollation>)
: Async<NixInfo>
=
let rec go (required : Set<WorkloadKey>) (state : _) =
async {
if required.IsEmpty then
return state
else
let desiredWorkload, rest = required.MaximumElement, Set.remove required.MaximumElement required
// TODO - record the _required dependencies between workloads somehow, so that we can
// consume them in Nix space
let! thisTop, _required = renderWorkload client allAvailableWorkloads desiredWorkload
return! go rest (NixInfo.merge state thisTop)
}
go (Map.keys allAvailableWorkloads |> Set.ofSeq) NixInfo.empty
[<EntryPoint>]
let main argv =
// e.g. "6.0.301", "/Users/patrick/Documents/GitHub/maui-dotnet-flake"
let sdkVersion, outputDir =
match argv with
| [| ver; outputDir |] -> ver, DirectoryInfo outputDir
| _ ->
argv
|> String.concat " "
|> failwithf "bad args: %s"
use client = new HttpClient ()
async {
let! allAvailableWorkloads = allAvailableWorkloads sdkVersion
let! allAvailableWorkloads =
allAvailableWorkloads
|> Map.toSeq
|> Seq.map (fun (ident, uri) ->
async {
let! ct = Async.CancellationToken
use! s = Async.AwaitTask (client.GetStreamAsync uri)
use ms = new MemoryStream ()
do! Async.AwaitTask (s.CopyToAsync (ms, ct))
let! hash = Hash.getAsync ms
ms.Seek (0, SeekOrigin.Begin) |> ignore
let! manifest = fetchManifest' ms
return
{
Package = ident.Package
Version = ident.Version
Hash = hash
Manifest = manifest
}
}
)
|> Async.Parallel
let allAvailableWorkloads = collate allAvailableWorkloads
let! nixInfo = collectAllRequiredWorkloads client allAvailableWorkloads
let writeContents = File.WriteAllTextAsync (Path.Combine (outputDir.FullName, "workload-manifest-contents.nix"), nixInfo |> NixInfo.toString)
let stripVersion (s : string) =
s.Substring (0, s.LastIndexOf '-')
let stripManifest (s : string) =
if s.EndsWith (".Manifest", StringComparison.InvariantCultureIgnoreCase) then
s.Substring (0, s.Length - ".Manifest".Length)
else
failwith $"{s} didn't end with .Manifest"
let allManifests =
allAvailableWorkloads
|> Map.values
|> Seq.distinctBy (fun collation -> collation.Package, collation.Version)
|> Seq.map (fun collation ->
$"""{{
pname = "{collation.Package |> stripVersion |> stripManifest}";
version = "{collation.Version}";
src = fetchNuGet {{
version = "{collation.Version}";
hash = "sha256-{collation.Hash}";
pname = "{collation.Package}";
}};
workloadPacks = [];
}}"""
)
|> String.concat "\n"
|> sprintf "fetchNuGet: [\n%s\n]"
let writeManifestList = File.WriteAllTextAsync (Path.Combine (outputDir.FullName, "workload-manifest-list.nix"), allManifests)
do! Async.AwaitTask writeContents
do! Async.AwaitTask writeManifestList
return 0
}
|> Async.RunSynchronously

192
MauiDotnetFlake/State.fs Normal file
View File

@@ -0,0 +1,192 @@
namespace MauiDotnetFlake
type State =
{
Packs : Map<PackKey, Pack>
WorkloadName : WorkloadKey option
/// A map of before-alias-resolution to the available resolutions.
Aliases : Map<PackKey, Map<Platform, Pack>>
}
static member Empty (workloadName : WorkloadKey option) : State =
{
Packs = Map.empty
WorkloadName = workloadName
Aliases = Map.empty
}
type NixName =
private
| NixName of string
override this.ToString () =
match this with
| NixName s -> s
static member Make (s : string) =
s.Replace(".", "")
|> NixName
static member Make (PackKey s) =
s.Replace(".", "")
|> NixName
type NixExpression =
| NixExpression of string
override this.ToString () =
match this with
| NixExpression s -> s
type NixInfo =
{
Workloads : Map<NixName, NixExpression>
Packs : Map<NixName, NixExpression>
Aliases : Map<PackKey, Map<Platform, PackKey>>
}
override this.ToString () =
let workloads =
this.Workloads
|> Map.toSeq
|> Seq.map (fun (nixName, body) -> $"{nixName} = {body}")
|> String.concat "\n"
let packs =
this.Packs
|> Map.toSeq
|> Seq.map (fun (nixName, body) -> $"{nixName} = {body}")
|> String.concat "\n"
let aliases =
this.Aliases
|> Map.toSeq
|> Seq.map (fun (unAliased, resolutions) ->
let resolveMap =
resolutions
|> Map.toSeq
|> Seq.map (fun (platform, resolved) ->
$"\"{platform}\" = {NixName.Make resolved};"
)
|> String.concat "\n"
|> sprintf "{%s}"
$"{NixName.Make unAliased} = {resolveMap};"
)
|> String.concat "\n"
$"{workloads}\n{packs}\n{aliases}"
[<RequireQualifiedAccess>]
module NixInfo =
let empty =
{
Aliases = Map.empty
Workloads = Map.empty
Packs = Map.empty
}
let private assertEqual<'a when 'a : equality> (x : 'a) (y : 'a) : 'a =
if x = y then x else failwith $"duplicate found: {x}\n{y}\n-----\n"
let merge (n1 : NixInfo) (n2 : NixInfo) : NixInfo =
let workloads = Map.union assertEqual n1.Workloads n2.Workloads
let packs = Map.union assertEqual n1.Packs n2.Packs
let aliases = Map.union (Map.union assertEqual) n1.Aliases n2.Aliases
{
Workloads = workloads
Packs = packs
Aliases = aliases
}
let toString (n : NixInfo) : string =
$"""{{ buildDotnetWorkload, fetchNuGet, buildDotnetPack }}: rec {{
{n}
}}"""
[<RequireQualifiedAccess>]
module State =
let addPack (f : Pack) (s : State) =
{ s with
Packs = s.Packs |> Map.add f.Name f
}
let addAlias (platform : Platform) (beforeAliasResolution : PackKey) (resolved : Pack) (s : State) =
{ s with
Aliases =
s.Aliases
|> Map.change
beforeAliasResolution
(function
| None -> Map.ofList [platform, resolved] |> Some
| Some existing -> existing |> Map.add platform resolved |> Some
)
}
let chopEnd (chop : string) (s : string) =
if s.EndsWith chop then
s.Substring (0, s.Length - chop.Length)
else
failwith "chop failed to chop"
let toNix
(collation : WorkloadCollation)
(state : State)
: NixInfo
=
// TODO fix domain
let workloadName =
Option.get state.WorkloadName
|> fun (WorkloadKey s) -> s
|> NixName.Make
let spaces = " "
let workloadPacks =
state.Packs.Values
|> Seq.map (fun f -> f.Name)
|> Seq.map NixName.Make
|> Seq.map string<NixName>
|> Seq.sort
|> String.concat $"\n{spaces}"
let aliases =
state.Aliases.Keys
|> Seq.map NixName.Make
|> Seq.map string<NixName>
|> Seq.sort
|> String.concat $"\n{spaces}"
let primary =
//$"""buildDotnetWorkload (sdkVersion: rec {{
$"""rec {{
pname = "{workloadName}";
version = "{collation.Manifest.Version}";
src = fetchNuGet {{
pname = "{collation.Package}";
inherit version;
hash = "sha256-{collation.Hash}";
}};
workloadName = "{workloadName}";
workloadPacks = [
{spaces}{workloadPacks}
{spaces}{aliases}
];
}};"""
let primary = NixExpression primary
let secondaries =
state.Packs.Values
|> Seq.append (state.Aliases.Values |> Seq.collect (fun p -> p.Values))
|> Seq.sortBy (fun p -> p.Name)
|> Seq.map (fun l ->
let (PackKey name) = l.Name
let nixName = NixName.Make name
let output = $"""buildDotnetPack rec {{
pname = "{name}";
version = "{l.Version}";
kind = "{l.Type.ToString ()}";
src = fetchNuGet {{
inherit pname version;
hash = "sha256-{l.Hash}";
}};
}};"""
nixName, NixExpression output
)
|> Map.ofSeq
{
Workloads = Map.ofList [workloadName, primary]
Packs = secondaries
Aliases =
state.Aliases
|> Map.map (fun _ -> Map.map (fun _ v -> v.Name))
}

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>maui_dotnet_flake</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="Domain.fs" />
<Compile Include="Async.fs" />
<Compile Include="Hash.fs" />
<Compile Include="Map.fs" />
<Compile Include="State.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FSharp.Collections.ParallelSeq" Version="1.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

38
README.md Normal file
View File

@@ -0,0 +1,38 @@
# MAUI and Nix
This is a cobbled-together and barely-working Nix flake in which it is possible to create and build a MAUI project.
## Steps to demonstrate the proof of concept
1. `nix develop`
1. `dotnet new maui --name MauiTest && cd MauiTest`
1. Since I haven't included the Android dependencies (they are currently commented in, but the `darwin-aarch64` architecture lacks an Android SDK in nixpkgs), I have to `rm -r Platforms/Android && sed -i 's/net6.0-android//g' MauiTest.csproj`. You may need to do some work to get the Android SDK.
1. `dotnet build`.
## How to generate the manifest files
The accompanying F# project is used to generate the `workload-manifest-list.nix` and `workload-manifest-contents.nix` files.
You call it with:
```
dotnet run --project maui-dotnet-flake.fsproj 6.0.301 /Users/patrick/Documents/GitHub/maui-dotnet-flake
```
Here the `6.0.301` is the SDK version for which we are requesting a complete manifest of available SDK workloads, and the output path is the path where we write the manifest `.nix` files.
Note that this will download a lot of NuGet packages.
By default it will do so into `/tmp/pkgs` (see the start of `Program.fs` for the local cache logic), but this was only so that my local development loop was shortened; there is no consistency checking of any kind (so e.g. if you change SDK versions, the cache is not invalidated), so you may wish to flip `LOCAL_CACHE` to `false`.
### `workload-manifest-contents.nix`
This is a complete listing of each .NET workload you can install, the dependent NuGet packages for each workload, and the alias resolutions for per-platform packages.
### `workload-manifest-list.nix`
This is a complete listing of each NuGet package that defines an SDK manifest, but with no dependencies.
This is required because if .NET somehow knows which manifests are *meant* to be there, even if you're never going to use them, and it complains unless all these packages are present in its `sdk-manifests` folder (which they are by default, except that we're upgrading them from the default in the course of installing a workload).
## Known bugs
* There is likely something wrong with the composition of SDK workloads. I've seen the current setup stop working entirely if I remove the `android` manifest, although oddly enough my most recent attempt Just Worked.
* You have to just magically know which workloads you need to install. In fact the dependency information is encoded in the NuGet packages, but I have not done anything to help you there; you simply have to try it with `[manifest.maui]` and see it fail so that you know you also need e.g. `[manifest.maui manifest.microsoft-net-runtime-android]`.

View File

@@ -0,0 +1,253 @@
Welcome to .NET 6.0!
---------------------
SDK Version: 6.0.301
Telemetry
---------
The .NET tools collect usage data in order to help us improve your experience. It is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.
Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry
----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate run 'dotnet dev-certs https --trust' (Windows and macOS only).
Learn about HTTPS: https://aka.ms/dotnet-https
----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
Skipping NuGet package signature verification.
Skipping NuGet package signature verification.
Skipping NuGet package signature verification.
Installing workload manifest microsoft.net.sdk.tvos version 15.4.315…
Installing workload manifest microsoft.net.sdk.android version 32.0.440…
Installing workload manifest microsoft.net.sdk.maui version 6.0.419…
Installing workload manifest microsoft.net.sdk.macos version 12.3.315…
Installing workload manifest microsoft.net.sdk.maccatalyst version 15.4.315…
Installing workload manifest microsoft.net.sdk.ios version 15.4.315…
Installing workload manifest microsoft.net.workload.mono.toolchain version 6.0.7…
Installing pack Microsoft.Maui.Core.Ref.android version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Ref.android version 6.0.419...
Installing pack Microsoft.Maui.Core.Runtime.android version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Runtime.android version 6.0.419...
Installing pack Microsoft.Maui.Controls.Ref.android version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Ref.android version 6.0.419...
Installing pack Microsoft.Maui.Controls.Runtime.android version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Runtime.android version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Ref.android version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Ref.android version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Runtime.android version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Runtime.android version 6.0.419...
Installing pack Microsoft.AspNetCore.Components.WebView.Maui version 6.0.419...
Writing workload pack installation record for Microsoft.AspNetCore.Components.WebView.Maui version 6.0.419...
Installing pack Microsoft.Maui.Dependencies version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Dependencies version 6.0.419...
Installing pack Microsoft.Maui.Sdk version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Sdk version 6.0.419...
Installing pack Microsoft.Maui.Extensions version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Extensions version 6.0.419...
Installing pack Microsoft.Maui.Graphics version 6.0.403...
Writing workload pack installation record for Microsoft.Maui.Graphics version 6.0.403...
Installing pack Microsoft.Maui.Resizetizer.Sdk version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Resizetizer.Sdk version 6.0.419...
Installing pack Microsoft.Maui.Templates-6.0 version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Templates-6.0 version 6.0.419...
Installing pack Microsoft.Maui.Core.Ref.any version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Ref.any version 6.0.419...
Installing pack Microsoft.Maui.Core.Runtime.any version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Runtime.any version 6.0.419...
Installing pack Microsoft.Maui.Controls.Ref.any version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Ref.any version 6.0.419...
Installing pack Microsoft.Maui.Controls.Runtime.any version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Runtime.any version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Ref.any version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Ref.any version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Runtime.any version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Runtime.any version 6.0.419...
Installing pack Microsoft.Android.Sdk version 32.0.440...
===============Writing workload pack installation record for Microsoft.Android.Sdk version 32.0.440...
Installing pack Microsoft.Android.Ref.31 version 32.0.440...
Writing workload pack installation record for Microsoft.Android.Ref.31 version 32.0.440...
Installing pack Microsoft.Android.Ref.32 version 32.0.440...
Writing workload pack installation record for Microsoft.Android.Ref.32 version 32.0.440...
Installing pack Microsoft.Android.Runtime.32.android-arm version 32.0.440...
Writing workload pack installation record for Microsoft.Android.Runtime.32.android-arm version 32.0.440...
Installing pack Microsoft.Android.Runtime.32.android-arm64 version 32.0.440...
^BWriting workload pack installation record for Microsoft.Android.Runtime.32.android-arm64 version 32.0.440...
Installing pack Microsoft.Android.Runtime.32.android-x86 version 32.0.440...
^R
Writing workload pack installation record for Microsoft.Android.Runtime.32.android-x86 version 32.0.440...
Installing pack Microsoft.Android.Runtime.32.android-x64 version 32.0.440...
Writing workload pack installation record for Microsoft.Android.Runtime.32.android-x64 version 32.0.440...
Installing pack Microsoft.Android.Templates version 32.0.440...
Writing workload pack installation record for Microsoft.Android.Templates version 32.0.440...
Installing pack Microsoft.NETCore.App.Runtime.Mono.android-arm version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.android-arm version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.android-arm64 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.android-arm64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.android-x64 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.android-x64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.android-x86 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.android-x86 version 6.0.7...
Installing pack Microsoft.NET.Runtime.MonoAOTCompiler.Task version 6.0.7...
Writing workload pack installation record for Microsoft.NET.Runtime.MonoAOTCompiler.Task version 6.0.7...
Installing pack Microsoft.NET.Runtime.MonoTargets.Sdk version 6.0.7...
Writing workload pack installation record for Microsoft.NET.Runtime.MonoTargets.Sdk version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64 version 6.0.7...
Installing pack Microsoft.Maui.Core.Ref.ios version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Ref.ios version 6.0.419...
Installing pack Microsoft.Maui.Core.Runtime.ios version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Runtime.ios version 6.0.419...
Installing pack Microsoft.Maui.Controls.Ref.ios version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Ref.ios version 6.0.419...
Installing pack Microsoft.Maui.Controls.Runtime.ios version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Runtime.ios version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Ref.ios version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Ref.ios version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Runtime.ios version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Runtime.ios version 6.0.419...
Installing pack Microsoft.iOS.Sdk version 15.4.315...
====Writing workload pack installation record for Microsoft.iOS.Sdk version 15.4.315...
Installing pack Microsoft.iOS.Ref version 15.4.315...
Writing workload pack installation record for Microsoft.iOS.Ref version 15.4.315...
Installing pack Microsoft.iOS.Runtime.ios-arm version 15.4.315...
Writing workload pack installation record for Microsoft.iOS.Runtime.ios-arm version 15.4.315...
Installing pack Microsoft.iOS.Runtime.ios-arm64 version 15.4.315...
Writing workload pack installation record for Microsoft.iOS.Runtime.ios-arm64 version 15.4.315...
Installing pack Microsoft.iOS.Runtime.iossimulator-x86 version 15.4.315...
Writing workload pack installation record for Microsoft.iOS.Runtime.iossimulator-x86 version 15.4.315...
Installing pack Microsoft.iOS.Runtime.iossimulator-x64 version 15.4.315...
Writing workload pack installation record for Microsoft.iOS.Runtime.iossimulator-x64 version 15.4.315...
Installing pack Microsoft.iOS.Runtime.iossimulator-arm64 version 15.4.315...
Writing workload pack installation record for Microsoft.iOS.Runtime.iossimulator-arm64 version 15.4.315...
Installing pack Microsoft.iOS.Templates version 15.4.315...
Writing workload pack installation record for Microsoft.iOS.Templates version 15.4.315...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm64 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-arm64 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-arm64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x64 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x86 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x86 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.ios-arm version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.ios-arm version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.ios-arm64 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.ios-arm64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86 version 6.0.7...
Installing pack Microsoft.Maui.Core.Ref.tizen version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Ref.tizen version 6.0.419...
Installing pack Microsoft.Maui.Core.Runtime.tizen version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Runtime.tizen version 6.0.419...
Installing pack Microsoft.Maui.Controls.Ref.tizen version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Ref.tizen version 6.0.419...
Installing pack Microsoft.Maui.Controls.Runtime.tizen version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Runtime.tizen version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Ref.tizen version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Ref.tizen version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Runtime.tizen version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Runtime.tizen version 6.0.419...
Installing pack Microsoft.Maui.Core.Ref.maccatalyst version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Ref.maccatalyst version 6.0.419...
Installing pack Microsoft.Maui.Core.Runtime.maccatalyst version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Runtime.maccatalyst version 6.0.419...
Installing pack Microsoft.Maui.Controls.Ref.maccatalyst version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Ref.maccatalyst version 6.0.419...
Installing pack Microsoft.Maui.Controls.Runtime.maccatalyst version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Runtime.maccatalyst version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Ref.maccatalyst version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Ref.maccatalyst version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Runtime.maccatalyst version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Runtime.maccatalyst version 6.0.419...
Installing pack Microsoft.MacCatalyst.Sdk version 15.4.315...
==Writing workload pack installation record for Microsoft.MacCatalyst.Sdk version 15.4.315...
Installing pack Microsoft.MacCatalyst.Ref version 15.4.315...
Writing workload pack installation record for Microsoft.MacCatalyst.Ref version 15.4.315...
Installing pack Microsoft.MacCatalyst.Runtime.maccatalyst-arm64 version 15.4.315...
Writing workload pack installation record for Microsoft.MacCatalyst.Runtime.maccatalyst-arm64 version 15.4.315...
Installing pack Microsoft.MacCatalyst.Runtime.maccatalyst-x64 version 15.4.315...
Writing workload pack installation record for Microsoft.MacCatalyst.Runtime.maccatalyst-x64 version 15.4.315...
Installing pack Microsoft.MacCatalyst.Templates version 15.4.315...
Writing workload pack installation record for Microsoft.MacCatalyst.Templates version 15.4.315...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-arm64 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-arm64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-x64 version 6.0.7...
===Writing workload pack installation record for Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-x64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64 version 6.0.7...
Installing pack Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64 version 6.0.7...
Writing workload pack installation record for Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64 version 6.0.7...
Installing pack Microsoft.Maui.Core.Ref.win version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Ref.win version 6.0.419...
Installing pack Microsoft.Maui.Core.Runtime.win version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Core.Runtime.win version 6.0.419...
Installing pack Microsoft.Maui.Controls.Ref.win version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Ref.win version 6.0.419...
Installing pack Microsoft.Maui.Controls.Runtime.win version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Controls.Runtime.win version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Ref.win version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Ref.win version 6.0.419...
Installing pack Microsoft.Maui.Essentials.Runtime.win version 6.0.419...
Writing workload pack installation record for Microsoft.Maui.Essentials.Runtime.win version 6.0.419...
Installing pack Microsoft.Maui.Graphics.Win2D.WinUI.Desktop version 6.0.403...
Writing workload pack installation record for Microsoft.Maui.Graphics.Win2D.WinUI.Desktop version 6.0.403...
Garbage collecting for SDK feature band(s) 6.0.300...
Successfully installed workload(s) maui.
installPhase completed in 4 minutes 52 seconds
post-installation fixup
rewriting symlink /nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/bin/dotnet to be relative to /nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301
strip is /nix/store/90madzhlr2rnzx2zihn3295ysr0jx325-clang-wrapper-11.1.0/bin/strip
stripping (with command strip and flags -S) in /nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/bin
patching script interpreter paths in /nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301
/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/packs/Microsoft.MacCatalyst.Sdk/15.4.315/tools/bin/bgen: interpreter directive changed from "#!/bin/bash -e" to "/nix/store/m6pqblbr77ady86apyl7ickafgprjd9f-bash-5.1-p16/bin/bash -e"
/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/packs/Microsoft.Android.Sdk.Darwin/32.0.440/tools/Darwin/jit-times: interpreter directive changed from "#!/bin/sh" to "/nix/store/m6pqblbr77ady86apyl7ickafgprjd9f-bash-5.1-p16/bin/sh"
/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/packs/Microsoft.Android.Sdk.Darwin/32.0.440/tools/Darwin/illinkanalyzer: interpreter directive changed from "#!/bin/sh" to "/nix/store/m6pqblbr77ady86apyl7ickafgprjd9f-bash-5.1-p16/bin/sh"
/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/packs/Microsoft.iOS.Sdk/15.4.315/tools/bin/mlaunch: interpreter directive changed from "#!/bin/bash -e" to "/nix/store/m6pqblbr77ady86apyl7ickafgprjd9f-bash-5.1-p16/bin/bash -e"
/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/packs/Microsoft.iOS.Sdk/15.4.315/tools/bin/bgen: interpreter directive changed from "#!/bin/bash -e" to "/nix/store/m6pqblbr77ady86apyl7ickafgprjd9f-bash-5.1-p16/bin/bash -e"
running install tests
=.NET SDK (reflecting any global.json):
Version: 6.0.301
Commit: 43f9b18481
Runtime Environment:
OS Name: Mac OS X
OS Version: 12.4
OS Platform: Darwin
RID: osx.12-arm64
Base Path: /nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/sdk/6.0.301/
Host (useful for support):
Version: 6.0.6
Commit: 7cca709db2
.NET SDKs installed:
6.0.301 [/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.6 [/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.6 [/nix/store/8b43vbzjrmpdb5qw7may8czy74q53mfw-dotnet-sdk-6.0.301/shared/Microsoft.NETCore.App]
To install additional .NET runtimes or SDKs:
https://aka.ms/dotnet-download
warning: dumping very large path (> 256 MiB); this may run out of memory
/nix/store/4qhpk4hixrmdg7rrkblppbm8s4alj6xl-dotnet-sdk-6.0.301

79
flake.lock generated Normal file
View File

@@ -0,0 +1,79 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1638122382,
"narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1658777571,
"narHash": "sha256-gJMDUeaRhi47NxtrfFMIejlV5N3Ra2669w16Ndz2Jo0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "f0fa012b649a47e408291e96a15672a4fe925d65",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-22.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-21_11": {
"locked": {
"lastModified": 1658346836,
"narHash": "sha256-c9BZZbi0tqCQ4j6CMVDlsut3Q3ET1Fezf+qIslCfkhs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a1fe662eb26ffc2a036b37c4670392ade632c413",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-21.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nixpkgs-21_11": "nixpkgs-21_11",
"utils": "utils"
}
},
"utils": {
"inputs": {
"flake-utils": "flake-utils"
},
"locked": {
"lastModified": 1638172912,
"narHash": "sha256-jxhQGNEsZTdop/Br3JPS+xmBf6t9cIWRzVZFxbT76Rw=",
"owner": "gytis-ivaskevicius",
"repo": "flake-utils-plus",
"rev": "166d6ebd9f0de03afc98060ac92cba9c71cfe550",
"type": "github"
},
"original": {
"owner": "gytis-ivaskevicius",
"ref": "v1.3.1",
"repo": "flake-utils-plus",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

265
flake.nix Normal file
View File

@@ -0,0 +1,265 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05";
nixpkgs-21_11.url = "github:nixos/nixpkgs/nixos-21.11";
utils.url = "github:gytis-ivaskevicius/flake-utils-plus/v1.3.1";
};
outputs = inputs @ {
self,
nixpkgs,
utils,
...
}:
utils.lib.mkFlake {
inherit self inputs;
# for Android:
# channelsConfig.android_sdk.accept_license = true;
outputsBuilder = channels: let
inherit (channels.nixpkgs) lib buildEnv dotnetCorePackages stdenvNoCC;
platform =
(
if stdenvNoCC.isLinux
then "linux"
else if stdenvNoCC.isDarwin
then "osx"
else abort "unknown platform"
)
+ "-"
+ (
if stdenvNoCC.hostPlatform.parsed.cpu.family == "x86"
then "x"
else stdenvNoCC.hostPlatform.parsed.cpu.family
)
+ builtins.toString stdenvNoCC.hostPlatform.parsed.cpu.bits;
withWorkload = dotnet: workloads:
channels.nixpkgs.callPackage (import ./combine-packages.nix dotnet workloads) {};
fetchNuGet = {
pname,
version,
hash,
}:
channels.nixpkgs.fetchurl {
name = "nuget-${pname}-${version}.nupkg";
url = "https://www.nuget.org/api/v2/package/${pname}/${version}";
inherit hash;
};
buildDotnetWorkload = input: let
name = "f${input.pname}-${input.version}";
workloadName = input.workloadName or null;
sdkVersion = dotnetCorePackages.sdk_6_0.version;
workload = channels.nixpkgs.stdenvNoCC.mkDerivation {
inherit (input) pname version src;
sourceRoot = "${name}";
nativeBuildInputs = [channels.nixpkgs.unzip];
preUnpack = ''mkdir "$sourceRoot"'';
unpackCmd = ''unzip -qq $curSrc -d "$sourceRoot"'';
dontConfigure = true;
dontBuild = true;
installPhase =
''
workload_out="$out/sdk-manifests/${sdkVersion}/${lib.toLower input.pname}"
mkdir -p "$workload_out"
chmod -R ugo+r data # Work around some nupkgs having no permissions set
cp -R data/* "$workload_out"
''
+ lib.optionalString (!builtins.isNull workloadName) ''
installed_workloads_out="$out/metadata/workloads/${sdkVersion}/InstalledWorkloads"
mkdir -p "$installed_workloads_out"
touch "$installed_workloads_out/${workloadName}"
'';
};
in
buildEnv {
name = "workload-${name}-combined";
paths = nixpkgs.lib.lists.filter (x: !(builtins.isNull x)) (nixpkgs.lib.lists.map (pack:
if nixpkgs.lib.hasAttr "pname" pack
then pack
else nixpkgs.lib.attrsets.attrByPath [platform] null pack) (input.workloadPacks or [])
++ [workload]);
pathsToLink = ["/metadata" "/library-packs" "/packs" "/template-packs" "/sdk-manifests" "/tool-packs"];
};
allManifests = import ./workload-manifest-list.nix fetchNuGet;
composeDotnetWorkload = workloads: let
builtWorkloads =
nixpkgs.lib.lists.map buildDotnetWorkload workloads;
name = nixpkgs.lib.concatStrings builtWorkloads;
fallbackWorkloads =
builtins.filter (fallback: nixpkgs.lib.lists.all (desired: desired.src != fallback.src) workloads) allManifests;
in
buildEnv {
name = "workload-${name}-combined";
paths =
builtWorkloads ++ nixpkgs.lib.lists.map buildDotnetWorkload fallbackWorkloads;
};
buildDotnetPack = {
name ? "${pname}-${version}",
pname,
version,
src,
kind,
dotnet_sdk ? dotnetCorePackages.sdk_6_0,
}: let
kindMapping = {
"framework" = 1;
"sdk" = 0;
"template" = 3;
"library" = 2;
};
manifest = {
Id = pname;
Version = version;
Kind = kindMapping."${kind}";
ResolvedPackageId = pname;
Path =
builtins.placeholder "out"
+ (
if kind == "template"
then "/template-packs/${pname}/${version}/${pname}.nupkg"
else if kind == "library"
then "/library-packs/${pname}.${version}.nupkg"
else "/packs/${pname}/${version}"
);
IsStillPacked = kind != "template";
};
in
channels.nixpkgs.stdenvNoCC.mkDerivation {
inherit pname version src;
sourceRoot = "${pname}-${version}";
nativeBuildInputs = [channels.nixpkgs.unzip channels.nixpkgs-21_11.yq];
preUnpack = ''mkdir "$sourceRoot"'';
unpackCmd = ''unzip -qq $curSrc -d "$sourceRoot"'';
dontConfigure = true;
dontBuild = true;
meta.priority = -1;
installPhase =
lib.optionalString (kind != "template") ''
workload_out="$out/packs/${pname}/${version}"
mkdir -p "$workload_out"
# Install workload files
for f in $(ls -1 | grep -vE '\[Content_Types\].xml|_rels|package'); do
# Some package contents have no read access?!
chmod a+r -R "$f"
ls -la "$f"
cp -R "$f" "$workload_out"
done
# Set file permissions (e.g., for shell scripts)
if [ -f data/UnixFilePermissions.xml ]; then
declare -A perms="($(xq -r '.FileList.File | .[] | @sh "[\(."@Path")]=\(."@Permission")"' data/UnixFilePermissions.xml))"
for file in "''${!perms[@]}"; do
chmod "''${perms[$file]}" "$workload_out/$file"
done
fi
''
+ ''
nupkg_out="$out/${
if kind == "template"
then "template-packs"
else "packs/${pname}/${version}"
}"
nupkg_name="${
if kind == "template"
then (lib.toLower "${pname}.${version}")
else pname
}"
mkdir -p "$nupkg_out"
cp "$src" "$nupkg_out/$nupkg_name.nupkg"
# Register metadata
metadata_out="$out/metadata/workloads/InstalledPacks/v1/${pname}/${version}"
mkdir -p "$metadata_out"
echo '${builtins.toJSON manifest}' > "$metadata_out/${dotnet_sdk.version}"
# Copy signature
${
if kind != "template"
then ''cp .signature.p7s "$nupkg_out"''
else ""
}
'';
};
in {
devShell = let
inherit (channels.nixpkgs) lib mkShell stdenv dotnetCorePackages jdk11 androidenv;
manifest = import ./workload-manifest-contents.nix {inherit buildDotnetPack buildDotnetWorkload fetchNuGet;};
workload = composeDotnetWorkload [manifest.maui manifest.microsoft-net-runtime-android manifest.ios manifest.maccatalyst];
dotnet_sdk = dotnetCorePackages.sdk_6_0.overrideAttrs (old: let
major = lib.versions.major old.version;
minor = lib.versions.minor old.version;
patch = lib.versions.patch old.version;
featureBand = "${major}.${minor}.${builtins.substring 0 1 patch}00";
rpath = with channels.nixpkgs;
lib.makeLibraryPath [
stdenv.cc.cc
zlib
curl
icu
libunwind
libuuid
openssl
];
in {
nativeBuildInputs = old.nativeBuildInputs or [] ++ [channels.nixpkgs.makeBinaryWrapper];
postFixup =
old.postFixup
+ ''
rm "$out/bin/dotnet"
rm -r "$out/sdk-manifests"
cp -r "${workload}/metadata" "$out/metadata"
cp -r "${workload}/template-packs" "$out/template-packs"
cp -r "${workload}/tool-packs" "$out/tool-packs"
makeBinaryWrapper "$out/dotnet" "$out/bin/dotnet" \
--set DOTNETSDK_WORKLOAD_PACK_ROOTS "${workload}" \
--set DOTNETSDK_WORKLOAD_MANIFEST_ROOTS "${workload}/sdk-manifests" \
--set DYLD_FALLBACK_LIBRARY_PATH "${rpath}" \
--set DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE "true"
'';
sandboxProfile = ''(allow file-read* (literal "/usr/share/icu/icudt70l.dat"))'';
});
# for Android:
# android = androidenv.composeAndroidPackages {
# toolsVersion = "26.1.1";
# platformToolsVersion = "30.0.5";
# buildToolsVersions = [ "30.0.3" ];
# includeEmulator = false;
# emulatorVersion = "30.3.4";
# platformVersions = [ "28" "29" "30" ];
# includeSources = false;
# includeSystemImages = false;
# systemImageTypes = [ "google_apis_playstore" ];
# abiVersions = [ "armeabi-v7a" "arm64-v8a" ];
# cmakeVersions = [ "3.10.2" ];
# includeNDK = true;
# ndkVersions = ["22.0.7026061"];
# useGoogleAPIs = false;
# useGoogleTVAddOns = false;
# includeExtras = [
# "extras;google;gcm"
# ];
# };
# then use jdk11 and android.androidsdk in the packages
in
mkShell {
packages = [dotnet_sdk];
DOTNET_ROOT = "${dotnet_sdk}";
DOTNET_CLI_TELEMETRY_OPTOUT = "1";
};
};
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
fetchNuGet: [
{
pname = "microsoft.net.sdk.android";
version = "32.0.440";
src = fetchNuGet {
version = "32.0.440";
hash = "sha256-IBcXur/I4Su+2PiVLuheS0sIxOAHSsS9XMW2knhYCE8=";
pname = "microsoft.net.sdk.android.manifest-6.0.300";
};
workloadPacks = [];
}
{
pname = "microsoft.net.sdk.ios";
version = "15.4.328";
src = fetchNuGet {
version = "15.4.328";
hash = "sha256-BMtCkuBydIlnH5yohg6yKc6lqQ4jcvz9rpP7jLtO5G0=";
pname = "microsoft.net.sdk.ios.manifest-6.0.300";
};
workloadPacks = [];
}
{
pname = "microsoft.net.sdk.maccatalyst";
version = "15.4.328";
src = fetchNuGet {
version = "15.4.328";
hash = "sha256-2G3fLcQKNq2v2aTN13ZNMWdhAfJ5Iv3m6dFzl4c0WqY=";
pname = "microsoft.net.sdk.maccatalyst.manifest-6.0.300";
};
workloadPacks = [];
}
{
pname = "microsoft.net.sdk.macos";
version = "12.3.328";
src = fetchNuGet {
version = "12.3.328";
hash = "sha256-5x4/JHFLKx8x2MniFEsM07GB5sR5nHj834YdYC2Wogc=";
pname = "microsoft.net.sdk.macos.manifest-6.0.300";
};
workloadPacks = [];
}
{
pname = "microsoft.net.sdk.maui";
version = "6.0.419";
src = fetchNuGet {
version = "6.0.419";
hash = "sha256-x84cTUrys135LGizbGMlbe9lA0/MS7bmZ5Agz4T9ooU=";
pname = "microsoft.net.sdk.maui.manifest-6.0.300";
};
workloadPacks = [];
}
{
pname = "microsoft.net.workload.mono.toolchain";
version = "6.0.7";
src = fetchNuGet {
version = "6.0.7";
hash = "sha256-m2W3IZkG04wqVTcq2rauXO3e8hWYh7eHaPc1T99kBjY=";
pname = "microsoft.net.workload.mono.toolchain.manifest-6.0.300";
};
workloadPacks = [];
}
{
pname = "microsoft.net.workload.emscripten";
version = "6.0.4";
src = fetchNuGet {
version = "6.0.4";
hash = "sha256-g5Qsrj3jt8QMysohYFlxy7O9tsN7PYilF8jxonpeORI=";
pname = "microsoft.net.workload.emscripten.manifest-6.0.300";
};
workloadPacks = [];
}
{
pname = "microsoft.net.sdk.tvos";
version = "15.4.328";
src = fetchNuGet {
version = "15.4.328";
hash = "sha256-I9RXJVtLboTdGrrHfcKVPgyUh+4TcarjhCmay0S8/I8=";
pname = "microsoft.net.sdk.tvos.manifest-6.0.300";
};
workloadPacks = [];
}
]