Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
namespace ElectronNET.Runtime.Services.ElectronProcess
{
using ElectronNET.Common;
using ElectronNET.Runtime.Data;
using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ElectronNET.Common;
using ElectronNET.Runtime.Data;

/// <summary>
/// Launches and manages the Electron app process.
Expand All @@ -33,14 +34,42 @@ public ElectronProcessActive(bool isUnpackaged, string electronBinaryName, strin
this.socketPort = socketPort;
}

protected override Task StartCore()
protected override async Task StartCore()
{
var dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
string startCmd, args, workingDir;

if (this.isUnpackaged)
{
this.CheckRuntimeIdentifier();

var electrondir = Path.Combine(dir.FullName, ".electron");

ProcessRunner chmodRunner = null;

try
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var distFolder = Path.Combine(electrondir, "node_modules", "electron", "dist");

chmodRunner = new ProcessRunner("ElectronRunner-Chmod");
chmodRunner.Run("chmod", "-R +x " + distFolder, electrondir);
await chmodRunner.WaitForExitAsync().ConfigureAwait(true);

if (chmodRunner.LastExitCode != 0)
{
throw new Exception("Failed to set executable permissions on Electron dist folder.");
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine("[StartCore]: Exception: " + chmodRunner?.StandardError);
Console.Error.WriteLine("[StartCore]: Exception: " + chmodRunner?.StandardOutput);
Console.Error.WriteLine("[StartCore]: Exception: " + ex);
}

startCmd = Path.Combine(electrondir, "node_modules", "electron", "dist", "electron");

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
Expand All @@ -53,17 +82,71 @@ protected override Task StartCore()
}
else
{
dir = dir.Parent?.Parent;
dir = dir.Parent!.Parent!;
startCmd = Path.Combine(dir.FullName, this.electronBinaryName);
args = $"-dotnetpacked -electronforcedport={this.socketPort:D} " + this.extraArguments;
workingDir = dir.FullName;
}


// We don't await this in order to let the state transition to "Starting"
Task.Run(async () => await this.StartInternal(startCmd, args, workingDir).ConfigureAwait(false));
}

return Task.CompletedTask;
private void CheckRuntimeIdentifier()
{
var buildInfoRid = ElectronNetRuntime.BuildInfo.RuntimeIdentifier;
if (string.IsNullOrEmpty(buildInfoRid))
{
return;
}

var osPart = buildInfoRid.Split('-').First();

var mismatch = false;

switch (osPart)
{
case "win":

if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
mismatch = true;
}

break;

case "linux":

if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
mismatch = true;
}

break;

case "osx":

if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
mismatch = true;
}

break;

case "freebsd":

if (!RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
{
mismatch = true;
}

break;
}

if (mismatch)
{
throw new PlatformNotSupportedException($"This Electron.NET application was built for '{buildInfoRid}'. It cannot run on this platform.");
}
}

protected override Task StopCore()
Expand Down
97 changes: 78 additions & 19 deletions src/ElectronNET/build/ElectronNET.LateImport.targets
Original file line number Diff line number Diff line change
Expand Up @@ -297,12 +297,58 @@
<RemoveDir Directories="$(ElectronHookTargetModuleDir)" Condition="Exists($(ElectronHookTargetModuleDir))" />
</Target>

<Target Name="ElectronCheckVersionMismatch">

<PropertyGroup>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'win-x64'">x64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'win-x86'">ia32</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'win-arm64'">arm64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'linux-x64'">x64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'linux-arm'">armv7l</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">arm64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'osx-x64'">x64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">arm64</ElectronArch>

<ElectronPlatform Condition="'$(RuntimeIdentifier)' == 'win-x64' OR '$(RuntimeIdentifier)' == 'win-x86' OR '$(RuntimeIdentifier)' == 'win-arm64'">win</ElectronPlatform>
<ElectronPlatform Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm' OR '$(RuntimeIdentifier)' == 'linux-arm64'">linux</ElectronPlatform>
<ElectronPlatform Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'">mac</ElectronPlatform>

<!-- npm uses different OS names than Electron -->
<NpmOs Condition="'$(ElectronPlatform)' == 'win'">win32</NpmOs>
<NpmOs Condition="'$(ElectronPlatform)' == 'linux'">linux</NpmOs>
<NpmOs Condition="'$(ElectronPlatform)' == 'mac'">darwin</NpmOs>

<!-- npm CPU is same as ElectronArch except for linux-arm -->
<NpmCpu>$(ElectronArch)</NpmCpu>
<NpmCpu Condition="'$(RuntimeIdentifier)' == 'linux-arm'">arm</NpmCpu>

<_CurrentOSPlatform Condition="$([MSBuild]::IsOSPlatform('Windows'))">win</_CurrentOSPlatform>
<_CurrentOSPlatform Condition="$([MSBuild]::IsOSPlatform('Linux'))">linux</_CurrentOSPlatform>
<_CurrentOSPlatform Condition="$([MSBuild]::IsOSPlatform('OSX'))">mac</_CurrentOSPlatform>
</PropertyGroup>

<!-- Validate that the target platform matches the current OS -->
<PropertyGroup>
<IsLinuxWsl>false</IsLinuxWsl>
<IsLinuxWsl Condition="'$(ElectronPlatform)' == 'linux' AND '$(_CurrentOSPlatform)' == 'win'">true</IsLinuxWsl>

<_IsCrossCompileAllowed>false</_IsCrossCompileAllowed>
<!-- Allow Linux builds on Windows via WSL -->
<_IsCrossCompileAllowed Condition="'$(_CurrentOSPlatform)' == 'win' AND '$(ElectronPlatform)' == 'linux' AND '$(IsLinuxWsl)' == 'true'">true</_IsCrossCompileAllowed>

<_IsPlatformMismatch>false</_IsPlatformMismatch>
<_IsPlatformMismatch Condition="'$(_CurrentOSPlatform)' != '$(ElectronPlatform)' AND '$(_IsCrossCompileAllowed)' != 'true'">true</_IsPlatformMismatch>

</PropertyGroup>

</Target>


<Target Name="ElectronConfigureApp"
Inputs="@(ElectronPackageJsonFiles)"
Outputs="@(ElectronPackageJsonFiles->'$(OutDir)%(TargetPath)')"
AfterTargets="CopyFilesToOutputDirectory"
DependsOnTargets="ElectronResetHostHook"
DependsOnTargets="ElectronResetHostHook;ElectronCheckVersionMismatch"
>

<Copy SourceFiles="@(ElectronPackageJsonFiles)" DestinationFiles="@(ElectronPackageJsonFiles->'$(OutDir)%(TargetPath)')" >
Expand All @@ -316,10 +362,9 @@

<PropertyGroup>
<ElectronOutputPath>$([System.IO.Path]::GetFullPath('$(ElectronOutDir)'))</ElectronOutputPath>
<LinuxPrefix>linux</LinuxPrefix>
<IsLinuxWsl>false</IsLinuxWsl>
<IsLinuxWsl Condition="'$(RuntimeIdentifier.StartsWith($(LinuxPrefix)))' == 'true'AND $([MSBuild]::IsOSPlatform('Windows'))">true</IsLinuxWsl>
<_NpmCmd>npm install --no-bin-links</_NpmCmd>
<!-- Add cross-platform parameters when there's a platform mismatch (for remote debugging preparation) -->
<_NpmCmd Condition="'$(_IsPlatformMismatch)' == 'true'">$(_NpmCmd) --os=$(NpmOs) --cpu=$(NpmCpu) --arch=$(NpmCpu) --platform=$(NpmOs)</_NpmCmd>
<_NpmCmd Condition="'$(IsLinuxWsl)' == 'true'">wsl bash -ic '$(_NpmCmd)'</_NpmCmd>
</PropertyGroup>

Expand All @@ -335,6 +380,23 @@

<Message Importance="High" Text="Electron setup failed!" Condition="'$(ExecExitCode)' != '0'" />

<!-- Fix up incorrect symlinks created by npm on Windows when targeting macOS -->
<PropertyGroup>
<_ElectronFrameworksDir>$(ElectronOutDir)node_modules\electron\dist\Electron.app\Contents\Frameworks</_ElectronFrameworksDir>
</PropertyGroup>

<ItemGroup>
<_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\Electron Framework.framework" />
<_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\Mantle.framework" />
<_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\ReactiveObjC.framework" />
<_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\Squirrel.framework" />
</ItemGroup>

<!-- Only execute on Windows host when targeting macOS -->
<Message Importance="High" Text="Fixing macOS framework Resources symlinks" Condition="'$(ElectronPlatform)' == 'mac' AND '$(_CurrentOSPlatform)' == 'win'" />

<Exec Command="cmd /c del Resources &amp;&amp; mklink /D Resources &quot;Versions\Current\Resources&quot;" WorkingDirectory="%(_ElectronFrameworkDirs.Identity)" Condition="'$(ElectronPlatform)' == 'mac' AND '$(_CurrentOSPlatform)' == 'win'" />

</Target>

<Target Name="BeforePublishElectronApp" BeforeTargets="PrepareForPublish">
Expand Down Expand Up @@ -367,7 +429,7 @@
<_ElectronPublishAppAfterTarget Condition="'$(UsingMicrosoftNETSdkWeb)' != 'true'">Publish</_ElectronPublishAppAfterTarget>
</PropertyGroup>

<Target Name="ElectronPublishApp" AfterTargets="$(_ElectronPublishAppAfterTarget)">
<Target Name="ElectronPublishApp" AfterTargets="$(_ElectronPublishAppAfterTarget)" DependsOnTargets="ElectronCheckVersionMismatch">

<PropertyGroup>
<PublishDir>$(_OriginalPublishDir)</PublishDir>
Expand All @@ -376,21 +438,18 @@
</PropertyGroup>


<PropertyGroup>
<!-- Default values -->
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'win-x64'">x64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'win-x86'">ia32</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'win-arm64'">arm64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'linux-x64'">x64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'linux-arm'">armv7l</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">arm64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'osx-x64'">x64</ElectronArch>
<ElectronArch Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">arm64</ElectronArch>
<Error Condition="'$(_IsPlatformMismatch)' == 'true'"
Code="ELECTRON100"
Text="The target RuntimeIdentifier '$(RuntimeIdentifier)' (platform: $(ElectronPlatform)) does not match the current operating system ($(_CurrentOSPlatform)).
<ElectronPlatform Condition="'$(RuntimeIdentifier)' == 'win-x64' OR '$(RuntimeIdentifier)' == 'win-x86' OR '$(RuntimeIdentifier)' == 'win-arm64'">win</ElectronPlatform>
<ElectronPlatform Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm' OR '$(RuntimeIdentifier)' == 'linux-arm64'">linux</ElectronPlatform>
<ElectronPlatform Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'">mac</ElectronPlatform>
</PropertyGroup>
Electron applications must be built on the target operating system:
- Windows targets (win-x64, win-x86, win-arm64) must be built on Windows
- Linux targets (linux-x64, linux-arm, linux-arm64) must be built on Linux (or Windows with WSL)
- macOS targets (osx-x64, osx-arm64) must be built on macOS
EXCEPTION: Linux targets can be built on Windows using WSL (Windows Subsystem for Linux).
For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migration-Checks#8-cross-platform-build-validation" />

<RemoveEnvironmentVariables Variables="BUILD_BUILDNUMBER;BUILD_NUMBER;TRAVIS_BUILD_NUMBER;APPVEYOR_BUILD_NUMBER;CIRCLE_BUILD_NUM;CI_PIPELINE_IID" />

Expand Down