Skip to content

Commit

Permalink
Merge pull request #656 from ikvmnet/net472unix
Browse files Browse the repository at this point in the history
NET472 tool support on Unix
  • Loading branch information
wasabii authored Feb 2, 2025
2 parents 928905d + c85f31f commit 14fdb4f
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@
</ItemGroup>

<ItemGroup>
<PublishProjectReference Include="..\ikvmc\ikvmc.csproj">
<SetTargetFramework>TargetFramework=net472</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=linux-x64</SetRuntimeIdentifier>
<PublishTargetPath Condition=" '$(TargetFramework)' != '' ">ikvmc\net472\linux-x64</PublishTargetPath>
<CopyToOutputDirectory Condition=" '$(TargetFramework)' != '' ">PreserveNewest</CopyToOutputDirectory>
<PublishPackagePath>ikvmc\net472\linux-x64</PublishPackagePath>
<Pack>true</Pack>
</PublishProjectReference>
<PublishProjectReference Include="..\ikvmstub\ikvmstub.csproj">
<SetTargetFramework>TargetFramework=net472</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=linux-x64</SetRuntimeIdentifier>
<PublishTargetPath Condition=" '$(TargetFramework)' != '' ">ikvmstub\net472\linux-x64</PublishTargetPath>
<CopyToOutputDirectory Condition=" '$(TargetFramework)' != '' ">PreserveNewest</CopyToOutputDirectory>
<PublishPackagePath>ikvmstub\net472\linux-x64</PublishPackagePath>
<Pack>true</Pack>
</PublishProjectReference>
<PublishProjectReference Include="..\ikvmc\ikvmc.csproj">
<SetTargetFramework>TargetFramework=net8.0</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=linux-x64</SetRuntimeIdentifier>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
</PropertyGroup>

<ItemGroup>
<IkvmCompilerToolPath Include="$(MSBuildThisFileDirectory)..\ikvmc\net472\linux-x64\" TargetFramework="net472" RuntimeIdentifier="linux-x64" />
<IkvmCompilerToolPath Include="$(MSBuildThisFileDirectory)..\ikvmc\net8.0\linux-x64\" TargetFramework="net8.0" RuntimeIdentifier="linux-x64" />
<IkvmExporterToolPath Include="$(MSBuildThisFileDirectory)..\ikvmstub\net472\linux-x64\" TargetFramework="net472" RuntimeIdentifier="linux-x64" />
<IkvmExporterToolPath Include="$(MSBuildThisFileDirectory)..\ikvmstub\net8.0\linux-x64\" TargetFramework="net8.0" RuntimeIdentifier="linux-x64" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@
</ItemGroup>

<ItemGroup>
<PublishProjectReference Include="..\ikvmc\ikvmc.csproj">
<SetTargetFramework>TargetFramework=net472</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=osx-arm64</SetRuntimeIdentifier>
<PublishTargetPath Condition=" '$(TargetFramework)' != '' ">ikvmc\net472\osx-arm64</PublishTargetPath>
<CopyToOutputDirectory Condition=" '$(TargetFramework)' != '' ">PreserveNewest</CopyToOutputDirectory>
<PublishPackagePath>ikvmc\net472\osx-arm64</PublishPackagePath>
<Pack>true</Pack>
</PublishProjectReference>
<PublishProjectReference Include="..\ikvmstub\ikvmstub.csproj">
<SetTargetFramework>TargetFramework=net472</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=osx-arm64</SetRuntimeIdentifier>
<PublishTargetPath Condition=" '$(TargetFramework)' != '' ">ikvmstub\net472\osx-arm64</PublishTargetPath>
<CopyToOutputDirectory Condition=" '$(TargetFramework)' != '' ">PreserveNewest</CopyToOutputDirectory>
<PublishPackagePath>ikvmstub\net472\osx-arm64</PublishPackagePath>
<Pack>true</Pack>
</PublishProjectReference>
<PublishProjectReference Include="..\ikvmc\ikvmc.csproj">
<SetTargetFramework>TargetFramework=net8.0</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=osx-arm64</SetRuntimeIdentifier>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
</PropertyGroup>

<ItemGroup>
<IkvmCompilerToolPath Include="$(MSBuildThisFileDirectory)..\ikvmc\net472\osx-arm64\" TargetFramework="net472" RuntimeIdentifier="osx-arm64" />
<IkvmCompilerToolPath Include="$(MSBuildThisFileDirectory)..\ikvmc\net8.0\osx-arm64\" TargetFramework="net8.0" RuntimeIdentifier="osx-arm64" />
<IkvmExporterToolPath Include="$(MSBuildThisFileDirectory)..\ikvmstub\net472\osx-arm64\" TargetFramework="net472" RuntimeIdentifier="osx-arm64" />
<IkvmExporterToolPath Include="$(MSBuildThisFileDirectory)..\ikvmstub\net8.0\osx-arm64\" TargetFramework="net8.0" RuntimeIdentifier="osx-arm64" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@
</ItemGroup>

<ItemGroup>
<PublishProjectReference Include="..\ikvmc\ikvmc.csproj">
<SetTargetFramework>TargetFramework=net472</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=osx-x64</SetRuntimeIdentifier>
<PublishTargetPath Condition=" '$(TargetFramework)' != '' ">ikvmc\net472\osx-x64</PublishTargetPath>
<CopyToOutputDirectory Condition=" '$(TargetFramework)' != '' ">PreserveNewest</CopyToOutputDirectory>
<PublishPackagePath>ikvmc\net472\osx-x64</PublishPackagePath>
<Pack>true</Pack>
</PublishProjectReference>
<PublishProjectReference Include="..\ikvmstub\ikvmstub.csproj">
<SetTargetFramework>TargetFramework=net472</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=osx-x64</SetRuntimeIdentifier>
<PublishTargetPath Condition=" '$(TargetFramework)' != '' ">ikvmstub\net472\osx-x64</PublishTargetPath>
<CopyToOutputDirectory Condition=" '$(TargetFramework)' != '' ">PreserveNewest</CopyToOutputDirectory>
<PublishPackagePath>ikvmstub\net472\osx-x64</PublishPackagePath>
<Pack>true</Pack>
</PublishProjectReference>
<PublishProjectReference Include="..\ikvmc\ikvmc.csproj">
<SetTargetFramework>TargetFramework=net8.0</SetTargetFramework>
<SetRuntimeIdentifier>RuntimeIdentifier=osx-x64</SetRuntimeIdentifier>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
</PropertyGroup>

<ItemGroup>
<IkvmCompilerToolPath Include="$(MSBuildThisFileDirectory)..\ikvmc\net472\osx-x64\" TargetFramework="net472" RuntimeIdentifier="osx-x64" />
<IkvmCompilerToolPath Include="$(MSBuildThisFileDirectory)..\ikvmc\net8.0\osx-x64\" TargetFramework="net8.0" RuntimeIdentifier="osx-x64" />
<IkvmExporterToolPath Include="$(MSBuildThisFileDirectory)..\ikvmstub\net472\osx-x64\" TargetFramework="net472" RuntimeIdentifier="osx-x64" />
<IkvmExporterToolPath Include="$(MSBuildThisFileDirectory)..\ikvmstub\net8.0\osx-x64\" TargetFramework="net8.0" RuntimeIdentifier="osx-x64" />
</ItemGroup>

Expand Down
16 changes: 12 additions & 4 deletions src/IKVM.Tests.Util/DotNetSdkUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;

using Microsoft.Build.Utilities;

namespace IKVM.Tests.Util
{

Expand Down Expand Up @@ -63,11 +61,21 @@ public static string GetCoreLibName(string tfm, string targetFrameworkIdentifier
public static IList<string> GetPathToReferenceAssemblies(string tfm, string targetFrameworkIdentifier, string targetFrameworkVersion)
{
if (targetFrameworkIdentifier == ".NETFramework")
return ToolLocationHelper.GetPathToReferenceAssemblies(targetFrameworkIdentifier, targetFrameworkVersion, "");
{
var l = new List<string>();
var dir = Path.Combine(Path.GetDirectoryName(typeof(DotNetSdkUtil).Assembly.Location), "netfxref", tfm);
if (Directory.Exists(dir))
l.Add(dir);

return l;
}

if (targetFrameworkIdentifier == ".NETCore")
{
return GetCorePathToReferenceAssemblies(tfm, targetFrameworkVersion);
}

throw new InvalidOperationException();
throw new ArgumentException(nameof(targetFrameworkIdentifier));
}

/// <summary>
Expand Down
29 changes: 28 additions & 1 deletion src/IKVM.Tests.Util/IKVM.Tests.Util.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
<TargetFrameworks>net472;net6.0;net7.0;net8.0</TargetFrameworks>
</PropertyGroup>
Expand All @@ -8,5 +10,30 @@
<PackageReference Include="Microsoft.Build" Version="17.3.2" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.3.2" />
<PackageReference Include="System.Reflection.Metadata" Version="8.0.1" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net472" Version="1.0.3" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net481" Version="1.0.3" GeneratePathProperty="true" />
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
<AssignTargetPathsDependsOn>
IncludeReferenceAssemblies;
$(AssignTargetPathsDependsOn)
</AssignTargetPathsDependsOn>
</PropertyGroup>

<Target Name="IncludeReferenceAssemblies" BeforeTargets="AssignTargetPaths">
<ItemGroup>
<__ReferenceAssemblies Include="$(PkgMicrosoft_NETFramework_ReferenceAssemblies_net472)\build\.NETFramework\v4.7.2\*.dll" Framework="net472" />
<__ReferenceAssemblies Include="$(PkgMicrosoft_NETFramework_ReferenceAssemblies_net472)\build\.NETFramework\v4.7.2\Facades\*.dll" Framework="net472" />
<__ReferenceAssemblies Include="$(PkgMicrosoft_NETFramework_ReferenceAssemblies_net481)\build\.NETFramework\v4.8.1\*.dll" Framework="net481" />
<__ReferenceAssemblies Include="$(PkgMicrosoft_NETFramework_ReferenceAssemblies_net481)\build\.NETFramework\v4.8.1\Facades\*.dll" Framework="net481" />
<None Include="@(__ReferenceAssemblies)">
<TargetPath>netfxref\%(Framework)\%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Target>

</Project>
45 changes: 34 additions & 11 deletions src/IKVM.Tools.Runner/Exporter/IkvmExporterLauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -145,30 +146,52 @@ public async Task<int> ExecuteAsync(IkvmExporterOptions options, CancellationTok
try
{
// locate EXE file
string? wrap = null;
var exe = GetToolExe();
if (File.Exists(exe) == false)
if (exe is null || File.Exists(exe) == false)
throw new FileNotFoundException($"Could not locate tool at '{exe}'.");

// if we're running on Unix, we might need to set the execute bit on the file,
// since the NuGet package is built on Windows
// executing on Unix requires some considerations
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
try
// tool executables on Unix need to be invoked through Mono
if (exe.EndsWith(".exe"))
{
var psx = Mono.Unix.UnixFileSystemInfo.GetFileSystemEntry(exe);
if (psx.FileAccessPermissions.HasFlag(Mono.Unix.FileAccessPermissions.UserExecute) == false)
psx.FileAccessPermissions |= Mono.Unix.FileAccessPermissions.UserExecute;
wrap = "mono";
}
catch (Exception e)
else
{
throw new IkvmToolException($"Could not set user executable bit on '{exe}'.", e);
// else we need to ensure executable bit is set

try
{
var psx = Mono.Unix.UnixFileSystemInfo.GetFileSystemEntry(exe);
if (psx.FileAccessPermissions.HasFlag(Mono.Unix.FileAccessPermissions.UserExecute) == false)
psx.FileAccessPermissions |= Mono.Unix.FileAccessPermissions.UserExecute;
}
catch (Exception e)
{
throw new IkvmToolException($"Could not set user executable bit on '{exe}'.", e);
}
}
}

// configure CLI
var cli = Cli.Wrap(exe).WithWorkingDirectory(Environment.CurrentDirectory);
// configure CLI, with wrapper if required
Command cli;
if (wrap != null)
{
cli = Cli.Wrap(wrap);
args.Insert(0, exe);
}
else
cli = Cli.Wrap(exe);

// set configuration of CLI
cli = cli.WithWorkingDirectory(Environment.CurrentDirectory);
cli = cli.WithArguments(args);
cli = cli.WithValidation(CommandResultValidation.None);

// log the command we're about to run
await LogEventAsync(IkvmToolDiagnosticEventLevel.Trace, "Executing {0} {1}", [cli.TargetFilePath, cli.Arguments], ctk);

// send output to MSBuild (TODO, replace with binary reading)
Expand Down
38 changes: 5 additions & 33 deletions src/IKVM.Tools.Runner/IkvmToolLauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,44 +92,16 @@ protected IkvmToolDiagnosticEvent ParseEvent(string line)
/// <summary>
/// Gets the path to executable for the given environment.
/// </summary>
/// <param name="platform"></param>
/// <param name="architecture"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="NotImplementedException"></exception>
public string GetToolExe(OSPlatform platform, Architecture architecture)
public string? GetToolExe()
{
return Path.Combine(toolPath, platform == OSPlatform.Windows ? $"{toolName}.exe" : toolName);
}

/// <summary>
/// Gets the path to executable for the given environment.
/// </summary>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="NotImplementedException"></exception>
public string GetToolExe()
{
return GetToolExe(GetOSPlatform(), RuntimeInformation.OSArchitecture);
}

/// <summary>
/// Gets the current OS platform.
/// </summary>
/// <returns></returns>
/// <exception cref="PlatformNotSupportedException"></exception>
OSPlatform GetOSPlatform()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return OSPlatform.Windows;

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return OSPlatform.Linux;

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return OSPlatform.OSX;
foreach (var name in (Span<string>)[toolName + ".exe", toolName])
if (File.Exists(Path.Combine(toolPath, name)))
return Path.Combine(toolPath, name);

throw new PlatformNotSupportedException();
return null;
}

}
Expand Down
59 changes: 41 additions & 18 deletions src/IKVM.Tools.Runner/Importer/IkvmImporterLauncher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -263,40 +264,62 @@ public async Task<int> ExecuteAsync(IkvmImporterOptions options, CancellationTok
try
{
// create response file
Directory.CreateDirectory(Path.GetDirectoryName(response));
Directory.CreateDirectory(Path.GetDirectoryName(response) ?? throw new InvalidOperationException());
File.WriteAllText(response, w.ToString());

// locate EXE file
string? wrap = null;
var exe = GetToolExe();
if (File.Exists(exe) == false)
if (exe is null || File.Exists(exe) == false)
throw new FileNotFoundException($"Could not locate tool at '{exe}'.");

// if we're running on Linux, we might need to set the execute bit on the file,
// since the NuGet package is built on Windows
// executing on Unix requires some considerations
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
try
// tool executables on Unix need to be invoked through Mono
if (exe.EndsWith(".exe"))
{
var psx = Mono.Unix.UnixFileSystemInfo.GetFileSystemEntry(exe);
var prm = psx.FileAccessPermissions;
prm |= Mono.Unix.FileAccessPermissions.UserExecute;
prm |= Mono.Unix.FileAccessPermissions.GroupExecute;
prm |= Mono.Unix.FileAccessPermissions.OtherExecute;
if (prm != psx.FileAccessPermissions)
psx.FileAccessPermissions = prm;
wrap = "mono";
}
catch (Exception e)
else
{
throw new IkvmToolException($"Could not set user executable bit on '{exe}'.", e);
// else we need to ensure executable bit is set

try
{
var psx = Mono.Unix.UnixFileSystemInfo.GetFileSystemEntry(exe);
if (psx.FileAccessPermissions.HasFlag(Mono.Unix.FileAccessPermissions.UserExecute) == false)
psx.FileAccessPermissions |= Mono.Unix.FileAccessPermissions.UserExecute;
}
catch (Exception e)
{
throw new IkvmToolException($"Could not set user executable bit on '{exe}'.", e);
}
}
}

// configure CLI
var cli = Cli.Wrap(exe).WithWorkingDirectory(Environment.CurrentDirectory);
// assemble list of args
var args = new List<string>();
args.Add($"@{response}");

// execute the contents of the response file
cli = cli.WithArguments([$"@{response}"]);
// configure CLI, with wrapper if required
Command cli;
if (wrap != null)
{
cli = Cli.Wrap(wrap);
args.Insert(0, exe);
}
else
cli = Cli.Wrap(exe);

// set working directory
cli = cli.WithWorkingDirectory(Environment.CurrentDirectory);

// set configuration of CLI
cli = cli.WithArguments(args);
cli = cli.WithValidation(CommandResultValidation.None);

// log the command we're about to run
await LogEventAsync(IkvmToolDiagnosticEventLevel.Trace, "Executing {0} {1}", [cli.TargetFilePath, cli.Arguments], ctk);

// send output to MSBuild (TODO, replace with binary reading)
Expand Down
Loading

0 comments on commit 14fdb4f

Please sign in to comment.