Unstable v0.19.3.0
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml.Linq;
|
||||
using AsmResolver.PE;
|
||||
using AsmResolver.PE.File;
|
||||
using AsmResolver.PE.File.Headers;
|
||||
using AsmResolver.PE.Win32Resources.Builder;
|
||||
|
||||
namespace DeployAll;
|
||||
|
||||
public static class DotnetCmd
|
||||
{
|
||||
private const string DotnetAppName = "dotnet";
|
||||
|
||||
private const string desiredRuntimeVersion = "6.0.8";
|
||||
|
||||
public static void Publish(string projPath, string configuration, string runtime, string resultPath)
|
||||
{
|
||||
ProcessStartInfo psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = DotnetAppName,
|
||||
ArgumentList =
|
||||
{
|
||||
"publish",
|
||||
projPath,
|
||||
"-c",
|
||||
configuration,
|
||||
"-clp:ErrorsOnly;Summary",
|
||||
"--self-contained",
|
||||
"-r",
|
||||
runtime,
|
||||
"/p:Platform=x64",
|
||||
"/p:ErrorOnDuplicatePublishOutputFiles=false", //TODO: fix our duplicate files
|
||||
"/p:RollForward=Disable",
|
||||
$"/p:RuntimeFrameworkVersion={desiredRuntimeVersion}",
|
||||
"-o",
|
||||
resultPath
|
||||
},
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
var process = Util.StartProcess(psi);
|
||||
process.WaitForExit();
|
||||
string stdout = process.StandardOutput.ReadToEnd();
|
||||
string stderr = process.StandardError.ReadToEnd();
|
||||
|
||||
string errorLine = $"{stdout}\n{stderr}".Split('\n')
|
||||
.First(ln => ln.Contains("Error(s)", StringComparison.OrdinalIgnoreCase))
|
||||
.Trim();
|
||||
|
||||
if (!errorLine.StartsWith("0 ", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new Exception($"Failed to build {projPath}, {errorLine}");
|
||||
}
|
||||
|
||||
Console.WriteLine($" - Published \"{projPath}\" to \"{resultPath}\", {errorLine}");
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !runtime.StartsWith("win")) { return; }
|
||||
|
||||
// You may be wondering, what is this crap?
|
||||
// Cross-compiling is something that should work perfectly, because it's super convenient.
|
||||
// However, thanks to the way .NET works, cross-compiling to Windows from *nix platforms
|
||||
// results in an executable with basically no metadata, and the wrong subsystem!
|
||||
// (see https://github.com/dotnet/sdk/blob/375955d3a9de213a01d70eb6180298000dee30ee/src/Tasks/Microsoft.NET.Build.Tasks/GenerateShims.cs#L127-L132)
|
||||
// Does it look like we're about to modify the SDK itself to solve this problem? Yeah right.
|
||||
// Instead let's just take the shim generated by the SDK and fix it ourselves.
|
||||
|
||||
XElement firstPropertyGroup = XDocument.Load(projPath)
|
||||
.Root?
|
||||
.Element("PropertyGroup")
|
||||
?? throw new Exception("PropertyGroup not found");
|
||||
|
||||
string assemblyName = firstPropertyGroup.Element("AssemblyName")?.Value
|
||||
?? throw new Exception("AssemblyName not found");
|
||||
|
||||
// This is the shim that doesn't have the stuff we want.
|
||||
var fileToChange = PEFile.FromFile(Path.Combine(resultPath, $"{assemblyName}.exe"));
|
||||
// Luckily, the SDK does embed all of that data in the assembly with all of the IL!
|
||||
// We can just yoink it from here.
|
||||
var managedAssembly = PEImage.FromFile(Path.Combine(resultPath, $"{assemblyName}.dll"));
|
||||
|
||||
// Here's a whole lot of magic to set up the resources section of the executable
|
||||
var resourceSection = new PESection(".rsrc", SectionFlags.ContentInitializedData | SectionFlags.MemoryRead);
|
||||
var resourceDirectoryBuffer = new ResourceDirectoryBuffer();
|
||||
resourceDirectoryBuffer.AddDirectory(managedAssembly.Resources ?? throw new Exception($"{assemblyName}.dll has no resources"));
|
||||
resourceSection.Contents = resourceDirectoryBuffer;
|
||||
fileToChange.Sections.Add(resourceSection);
|
||||
fileToChange.AlignSections();
|
||||
var dataDirectories = fileToChange.OptionalHeader.DataDirectories;
|
||||
dataDirectories[2] = new DataDirectory(resourceDirectoryBuffer.Rva, resourceDirectoryBuffer.GetPhysicalSize());
|
||||
|
||||
// And here's something a little less magical that fixes the subsystem
|
||||
fileToChange.OptionalHeader.SubSystem = firstPropertyGroup.Element("OutputType")?.Value == "WinExe"
|
||||
? SubSystem.WindowsGui
|
||||
: SubSystem.WindowsCui;
|
||||
|
||||
using var writeStream = File.Open(Path.Combine(resultPath, $"{assemblyName}.exe"), FileMode.Create);
|
||||
fileToChange.Write(writeStream);
|
||||
}
|
||||
|
||||
public static Version GetSdkVersion()
|
||||
{
|
||||
ProcessStartInfo psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = DotnetAppName,
|
||||
ArgumentList =
|
||||
{
|
||||
"--version"
|
||||
},
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
var process = Util.StartProcess(psi);
|
||||
process.WaitForExit();
|
||||
string stdout = process.StandardOutput.ReadToEnd();
|
||||
|
||||
return Version.Parse(stdout.Trim());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user