2017-10-05 04:44:58 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
2019-11-30 23:30:15 +01:00
|
|
|
|
using System.Linq;
|
2017-10-05 04:44:58 +02:00
|
|
|
|
using System.Threading.Tasks;
|
2017-11-04 23:17:04 +01:00
|
|
|
|
using ElectronNET.CLI.Commands.Actions;
|
2017-10-05 04:44:58 +02:00
|
|
|
|
|
|
|
|
|
|
namespace ElectronNET.CLI.Commands
|
|
|
|
|
|
{
|
|
|
|
|
|
public class BuildCommand : ICommand
|
|
|
|
|
|
{
|
|
|
|
|
|
public const string COMMAND_NAME = "build";
|
|
|
|
|
|
public const string COMMAND_DESCRIPTION = "Build your Electron Application.";
|
2021-09-15 11:14:45 +02:00
|
|
|
|
public const string COMMAND_ARGUMENTS =
|
|
|
|
|
|
@"Needed: '/target' with params 'win/osx/linux' to build for a typical app or use 'custom' and specify .NET Core build config & electron build config
|
|
|
|
|
|
for custom target, check .NET Core RID Catalog and Electron build target/
|
|
|
|
|
|
e.g. '/target win' or '/target custom ""win7-x86;win""'
|
|
|
|
|
|
Optional: '/dotnet-configuration' with the desired .NET Core build config e.g. release or debug. Default = Release
|
|
|
|
|
|
Optional: '/electron-arch' to specify the resulting electron processor architecture (e.g. ia86 for x86 builds). Be aware to use the '/target custom' param as well!
|
|
|
|
|
|
Optional: '/electron-params' specify any other valid parameter, which will be routed to the electron-packager.
|
|
|
|
|
|
Optional: '/relative-path' to specify output a subdirectory for output.
|
|
|
|
|
|
Optional: '/absolute-path to specify and absolute path for output.
|
|
|
|
|
|
Optional: '/package-json' to specify a custom package.json file.
|
|
|
|
|
|
Optional: '/install-modules' to force node module install. Implied by '/package-json'
|
|
|
|
|
|
Optional: '/Version' to specify the version that should be applied to both the `dotnet publish` and `electron-builder` commands. Implied by '/Version'
|
|
|
|
|
|
Optional: '/p:[property]' or '/property:[property]' to pass in dotnet publish properties. Example: '/property:Version=1.0.0' to override the FileVersion
|
|
|
|
|
|
Full example for a 32bit debug build with electron prune: build /target custom win7-x86;win32 /dotnet-configuration Debug /electron-arch ia32 /electron-params ""--prune=true """;
|
2018-02-19 22:07:07 +01:00
|
|
|
|
|
2017-10-05 04:44:58 +02:00
|
|
|
|
public static IList<CommandOption> CommandOptions { get; set; } = new List<CommandOption>();
|
|
|
|
|
|
|
2021-09-17 16:05:40 +02:00
|
|
|
|
private readonly string[] _args;
|
2017-10-17 23:15:05 +02:00
|
|
|
|
|
|
|
|
|
|
public BuildCommand(string[] args)
|
|
|
|
|
|
{
|
|
|
|
|
|
_args = args;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-24 18:45:28 +01:00
|
|
|
|
private const string _defaultElectronVersion = "17.2.0";
|
2021-12-03 09:16:44 +01:00
|
|
|
|
|
2021-07-12 17:05:26 +02:00
|
|
|
|
private const string _paramTarget = "target";
|
|
|
|
|
|
private const string _paramDotNetConfig = "dotnet-configuration";
|
|
|
|
|
|
private const string _paramElectronArch = "electron-arch";
|
|
|
|
|
|
private const string _paramElectronParams = "electron-params";
|
|
|
|
|
|
private const string _paramElectronVersion = "electron-version";
|
|
|
|
|
|
private const string _paramOutputDirectory = "relative-path";
|
|
|
|
|
|
private const string _paramAbsoluteOutput = "absolute-path";
|
|
|
|
|
|
private const string _paramPackageJson = "package-json";
|
|
|
|
|
|
private const string _paramForceNodeInstall = "install-modules";
|
|
|
|
|
|
private const string _manifest = "manifest";
|
|
|
|
|
|
private const string _paramPublishReadyToRun = "PublishReadyToRun";
|
|
|
|
|
|
private const string _paramPublishSingleFile = "PublishSingleFile";
|
|
|
|
|
|
private const string _paramVersion = "Version";
|
2018-02-12 21:17:40 +01:00
|
|
|
|
|
2017-10-05 04:44:58 +02:00
|
|
|
|
public Task<bool> ExecuteAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
return Task.Run(() =>
|
|
|
|
|
|
{
|
2017-10-08 23:22:20 +02:00
|
|
|
|
Console.WriteLine("Build Electron Application...");
|
2017-10-05 04:44:58 +02:00
|
|
|
|
|
2018-02-11 22:24:12 +01:00
|
|
|
|
SimpleCommandLineParser parser = new SimpleCommandLineParser();
|
|
|
|
|
|
parser.Parse(_args);
|
|
|
|
|
|
|
2021-03-04 14:45:52 +00:00
|
|
|
|
//This version will be shared between the dotnet publish and electron-builder commands
|
|
|
|
|
|
string version = null;
|
|
|
|
|
|
if (parser.Arguments.ContainsKey(_paramVersion))
|
|
|
|
|
|
version = parser.Arguments[_paramVersion][0];
|
|
|
|
|
|
|
2019-11-16 15:13:02 +00:00
|
|
|
|
if (!parser.Arguments.ContainsKey(_paramTarget))
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine($"Error: missing '{_paramTarget}' argument.");
|
|
|
|
|
|
Console.WriteLine(COMMAND_ARGUMENTS);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-12 21:17:40 +01:00
|
|
|
|
var desiredPlatform = parser.Arguments[_paramTarget][0];
|
2018-02-11 22:24:12 +01:00
|
|
|
|
string specifiedFromCustom = string.Empty;
|
2018-02-12 21:17:40 +01:00
|
|
|
|
if (desiredPlatform == "custom" && parser.Arguments[_paramTarget].Length > 1)
|
2018-02-11 22:24:12 +01:00
|
|
|
|
{
|
2018-04-19 21:14:00 +02:00
|
|
|
|
specifiedFromCustom = parser.Arguments[_paramTarget][1];
|
2018-02-11 22:24:12 +01:00
|
|
|
|
}
|
2018-02-12 21:17:40 +01:00
|
|
|
|
|
|
|
|
|
|
string configuration = "Release";
|
|
|
|
|
|
if (parser.Arguments.ContainsKey(_paramDotNetConfig))
|
|
|
|
|
|
{
|
|
|
|
|
|
configuration = parser.Arguments[_paramDotNetConfig][0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-11 22:24:12 +01:00
|
|
|
|
var platformInfo = GetTargetPlatformInformation.Do(desiredPlatform, specifiedFromCustom);
|
2017-10-17 23:15:05 +02:00
|
|
|
|
|
2018-01-24 22:39:46 +01:00
|
|
|
|
Console.WriteLine($"Build ASP.NET Core App for {platformInfo.NetCorePublishRid}...");
|
|
|
|
|
|
|
2017-11-04 23:17:04 +01:00
|
|
|
|
string tempPath = Path.Combine(Directory.GetCurrentDirectory(), "obj", "desktop", desiredPlatform);
|
2020-11-12 11:15:37 +00:00
|
|
|
|
|
2017-11-04 23:17:04 +01:00
|
|
|
|
if (Directory.Exists(tempPath) == false)
|
2017-10-08 23:22:20 +02:00
|
|
|
|
{
|
2017-11-04 23:17:04 +01:00
|
|
|
|
Directory.CreateDirectory(tempPath);
|
2020-11-12 11:15:37 +00:00
|
|
|
|
}
|
2019-11-30 23:30:15 +01:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.Delete(tempPath, true);
|
|
|
|
|
|
Directory.CreateDirectory(tempPath);
|
2017-10-08 23:22:20 +02:00
|
|
|
|
}
|
2020-11-12 11:15:37 +00:00
|
|
|
|
|
2017-10-05 04:44:58 +02:00
|
|
|
|
|
2017-10-19 21:31:32 +02:00
|
|
|
|
Console.WriteLine("Executing dotnet publish in this directory: " + tempPath);
|
|
|
|
|
|
|
|
|
|
|
|
string tempBinPath = Path.Combine(tempPath, "bin");
|
|
|
|
|
|
|
2018-02-12 21:17:40 +01:00
|
|
|
|
Console.WriteLine($"Build ASP.NET Core App for {platformInfo.NetCorePublishRid} under {configuration}-Configuration...");
|
2021-01-25 12:13:44 -06:00
|
|
|
|
|
2021-07-12 17:05:26 +02:00
|
|
|
|
var dotNetPublishFlags = GetDotNetPublishFlags(parser, "false", "false");
|
2017-10-11 23:29:58 +02:00
|
|
|
|
|
2021-01-25 12:13:44 -06:00
|
|
|
|
var command =
|
|
|
|
|
|
$"dotnet publish -r {platformInfo.NetCorePublishRid} -c \"{configuration}\" --output \"{tempBinPath}\" {string.Join(' ', dotNetPublishFlags.Select(kvp => $"{kvp.Key}={kvp.Value}"))} --self-contained";
|
|
|
|
|
|
|
|
|
|
|
|
// output the command
|
|
|
|
|
|
Console.ForegroundColor = ConsoleColor.Green;
|
|
|
|
|
|
Console.WriteLine(command);
|
|
|
|
|
|
Console.ResetColor();
|
2020-05-10 00:31:28 +02:00
|
|
|
|
|
2021-01-25 12:13:44 -06:00
|
|
|
|
var resultCode = ProcessHelper.CmdExecute(command, Directory.GetCurrentDirectory());
|
2017-11-15 23:42:15 +01:00
|
|
|
|
|
|
|
|
|
|
if (resultCode != 0)
|
|
|
|
|
|
{
|
2018-09-27 22:48:54 +02:00
|
|
|
|
Console.WriteLine("Error occurred during dotnet publish: " + resultCode);
|
2017-11-15 23:42:15 +01:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2017-10-11 23:29:58 +02:00
|
|
|
|
|
2017-11-04 23:17:04 +01:00
|
|
|
|
DeployEmbeddedElectronFiles.Do(tempPath);
|
2019-01-15 22:21:25 +01:00
|
|
|
|
var nodeModulesDirPath = Path.Combine(tempPath, "node_modules");
|
2017-10-07 01:32:19 +02:00
|
|
|
|
|
2019-03-28 14:42:21 -07:00
|
|
|
|
if (parser.Arguments.ContainsKey(_paramPackageJson))
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("Copying custom package.json.");
|
|
|
|
|
|
|
|
|
|
|
|
File.Copy(parser.Arguments[_paramPackageJson][0], Path.Combine(tempPath, "package.json"), true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-11-15 22:58:33 +01:00
|
|
|
|
var checkForNodeModulesDirPath = Path.Combine(tempPath, "node_modules");
|
2017-10-05 04:44:58 +02:00
|
|
|
|
|
2021-06-28 15:01:10 +02:00
|
|
|
|
if (!Directory.Exists(checkForNodeModulesDirPath)|| parser.Contains(_paramForceNodeInstall) || parser.Contains(_paramPackageJson))
|
|
|
|
|
|
{
|
2020-11-12 11:15:37 +00:00
|
|
|
|
Console.WriteLine("Start npm install...");
|
2021-06-28 15:01:10 +02:00
|
|
|
|
ProcessHelper.CmdExecute("npm install --production", tempPath);
|
|
|
|
|
|
}
|
2019-01-15 22:21:25 +01:00
|
|
|
|
|
2019-01-09 23:04:56 +01:00
|
|
|
|
Console.WriteLine("ElectronHostHook handling started...");
|
|
|
|
|
|
|
|
|
|
|
|
string electronhosthookDir = Path.Combine(Directory.GetCurrentDirectory(), "ElectronHostHook");
|
|
|
|
|
|
|
|
|
|
|
|
if (Directory.Exists(electronhosthookDir))
|
|
|
|
|
|
{
|
|
|
|
|
|
string hosthookDir = Path.Combine(tempPath, "ElectronHostHook");
|
|
|
|
|
|
DirectoryCopy.Do(electronhosthookDir, hosthookDir, true, new List<string>() { "node_modules" });
|
|
|
|
|
|
|
2019-10-07 22:53:50 +02:00
|
|
|
|
Console.WriteLine("Start npm install for hosthooks...");
|
2019-10-14 22:44:30 +02:00
|
|
|
|
ProcessHelper.CmdExecute("npm install", hosthookDir);
|
2019-01-09 23:04:56 +01:00
|
|
|
|
|
|
|
|
|
|
// ToDo: Not sure if this runs under linux/macos
|
2019-10-22 23:59:47 -04:00
|
|
|
|
ProcessHelper.CmdExecute(@"npx tsc -p . --sourceMap false", hosthookDir);
|
2017-10-08 23:56:04 +02:00
|
|
|
|
}
|
2017-10-05 04:44:58 +02:00
|
|
|
|
|
2017-10-05 21:28:47 +02:00
|
|
|
|
Console.WriteLine("Build Electron Desktop Application...");
|
2019-03-28 14:42:21 -07:00
|
|
|
|
|
|
|
|
|
|
// Specifying an absolute path supercedes a relative path
|
2017-10-19 21:58:50 +02:00
|
|
|
|
string buildPath = Path.Combine(Directory.GetCurrentDirectory(), "bin", "desktop");
|
2019-03-28 14:42:21 -07:00
|
|
|
|
if (parser.Arguments.ContainsKey(_paramAbsoluteOutput))
|
|
|
|
|
|
{
|
|
|
|
|
|
buildPath = parser.Arguments[_paramAbsoluteOutput][0];
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (parser.Arguments.ContainsKey(_paramOutputDirectory))
|
|
|
|
|
|
{
|
2020-11-12 11:15:37 +00:00
|
|
|
|
buildPath = Path.Combine(Directory.GetCurrentDirectory(), parser.Arguments[_paramOutputDirectory][0]);
|
2019-03-28 14:42:21 -07:00
|
|
|
|
}
|
2017-10-19 21:31:32 +02:00
|
|
|
|
|
2017-10-05 23:37:52 +02:00
|
|
|
|
Console.WriteLine("Executing electron magic in this directory: " + buildPath);
|
|
|
|
|
|
|
2018-02-12 21:17:40 +01:00
|
|
|
|
string electronArch = "x64";
|
|
|
|
|
|
if (parser.Arguments.ContainsKey(_paramElectronArch))
|
|
|
|
|
|
{
|
|
|
|
|
|
electronArch = parser.Arguments[_paramElectronArch][0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-03 09:16:44 +01:00
|
|
|
|
var electronVersion = _defaultElectronVersion;
|
2021-06-28 15:04:26 +02:00
|
|
|
|
if (parser.Arguments.ContainsKey(_paramElectronVersion))
|
|
|
|
|
|
{
|
|
|
|
|
|
electronVersion = parser.Arguments[_paramElectronVersion][0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-12 21:17:40 +01:00
|
|
|
|
string electronParams = "";
|
|
|
|
|
|
if (parser.Arguments.ContainsKey(_paramElectronParams))
|
|
|
|
|
|
{
|
2018-02-12 21:23:23 +01:00
|
|
|
|
electronParams = parser.Arguments[_paramElectronParams][0];
|
2018-02-12 21:17:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-05-18 02:01:06 +02:00
|
|
|
|
// ToDo: Make the same thing easer with native c# - we can save a tmp file in production code :)
|
|
|
|
|
|
Console.WriteLine("Create electron-builder configuration file...");
|
2019-11-30 23:30:15 +01:00
|
|
|
|
|
|
|
|
|
|
string manifestFileName = "electron.manifest.json";
|
|
|
|
|
|
|
2020-11-12 11:15:37 +00:00
|
|
|
|
if (parser.Arguments.ContainsKey(_manifest))
|
2019-11-30 23:30:15 +01:00
|
|
|
|
{
|
|
|
|
|
|
manifestFileName = parser.Arguments[_manifest].First();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-04 14:45:52 +00:00
|
|
|
|
ProcessHelper.CmdExecute(
|
|
|
|
|
|
string.IsNullOrWhiteSpace(version)
|
|
|
|
|
|
? $"node build-helper.js {manifestFileName}"
|
|
|
|
|
|
: $"node build-helper.js {manifestFileName} {version}", tempPath);
|
2019-05-18 02:01:06 +02:00
|
|
|
|
|
2017-11-04 23:17:04 +01:00
|
|
|
|
Console.WriteLine($"Package Electron App for Platform {platformInfo.ElectronPackerPlatform}...");
|
2021-06-28 15:04:26 +02:00
|
|
|
|
ProcessHelper.CmdExecute($"npx electron-builder --config=./bin/electron-builder.json --{platformInfo.ElectronPackerPlatform} --{electronArch} -c.electronVersion={electronVersion} {electronParams}", tempPath);
|
2017-10-11 23:29:58 +02:00
|
|
|
|
|
2017-10-16 22:58:52 +02:00
|
|
|
|
Console.WriteLine("... done");
|
|
|
|
|
|
|
2017-10-05 04:44:58 +02:00
|
|
|
|
return true;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2021-01-25 12:13:44 -06:00
|
|
|
|
|
2021-07-12 17:05:26 +02:00
|
|
|
|
internal static Dictionary<string, string> GetDotNetPublishFlags(SimpleCommandLineParser parser, string defaultReadyToRun, string defaultSingleFile)
|
2021-01-25 12:13:44 -06:00
|
|
|
|
{
|
|
|
|
|
|
var dotNetPublishFlags = new Dictionary<string, string>
|
|
|
|
|
|
{
|
2021-07-12 17:05:26 +02:00
|
|
|
|
{"/p:PublishReadyToRun", parser.TryGet(_paramPublishReadyToRun, out var rtr) ? rtr[0] : defaultReadyToRun},
|
|
|
|
|
|
{"/p:PublishSingleFile", parser.TryGet(_paramPublishSingleFile, out var psf) ? psf[0] : defaultSingleFile},
|
2021-01-25 12:13:44 -06:00
|
|
|
|
};
|
|
|
|
|
|
|
2021-07-02 16:07:31 +01:00
|
|
|
|
if (parser.Arguments.ContainsKey(_paramVersion))
|
|
|
|
|
|
{
|
|
|
|
|
|
if(parser.Arguments.Keys.All(key => !key.StartsWith("p:Version=") && !key.StartsWith("property:Version=")))
|
|
|
|
|
|
dotNetPublishFlags.Add("/p:Version", parser.Arguments[_paramVersion][0]);
|
|
|
|
|
|
if(parser.Arguments.Keys.All(key => !key.StartsWith("p:ProductVersion=") && !key.StartsWith("property:ProductVersion=")))
|
|
|
|
|
|
dotNetPublishFlags.Add("/p:ProductVersion", parser.Arguments[_paramVersion][0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-01-25 12:13:44 -06:00
|
|
|
|
foreach (var parm in parser.Arguments.Keys.Where(key => key.StartsWith("p:") || key.StartsWith("property:")))
|
|
|
|
|
|
{
|
|
|
|
|
|
var split = parm.IndexOf('=');
|
|
|
|
|
|
if (split < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var key = $"/{parm.Substring(0, split)}";
|
|
|
|
|
|
// normalize the key
|
|
|
|
|
|
if (key.StartsWith("/property:"))
|
|
|
|
|
|
{
|
|
|
|
|
|
key = key.Replace("/property:", "/p:");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var value = parm.Substring(split + 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (dotNetPublishFlags.ContainsKey(key))
|
|
|
|
|
|
{
|
|
|
|
|
|
dotNetPublishFlags[key] = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
dotNetPublishFlags.Add(key, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return dotNetPublishFlags;
|
|
|
|
|
|
}
|
2017-10-05 04:44:58 +02:00
|
|
|
|
}
|
2020-11-12 11:15:37 +00:00
|
|
|
|
}
|