Skip to content

Commit

Permalink
Initial implementation for Mac
Browse files Browse the repository at this point in the history
  • Loading branch information
cwensley committed Jun 26, 2024
1 parent 7b41bda commit 8d5c6bb
Show file tree
Hide file tree
Showing 11 changed files with 237 additions and 42 deletions.
47 changes: 42 additions & 5 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build Hops",
"program": "/Applications/RhinoWIP.app/Contents/MacOS/Rhinoceros",
// "program": "/Applications/Rhino 8.app/Contents/MacOS/Rhinoceros",
"program": "/Users/curtis/Library/Developer/Xcode/DerivedData/MacRhino-dalqjlsjnqqsltdayygnhqhgntxb/Build/Products/Debug/Rhinoceros.app/Contents/MacOS/Rhinoceros",
"args": [],
"env": {
"GRASSHOPPER_PLUGINS": "${workspaceFolder}/src/hops/bin/Debug/Hops.gha"
Expand Down Expand Up @@ -45,13 +46,49 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build",
"program": "${workspaceFolder}/src/bin/Debug/compute.geometry/compute.geometry.exe",
"targetArchitecture": "x86_64",
"windows": {
"program": "${workspaceFolder}/src/bin/Debug/compute.geometry/compute.geometry.exe",
"targetArchitecture": "x86_64",
},
"osx": {
"program": "${workspaceFolder}/src/bin/Debug/compute.geometry/osx-arm64/compute.geometry",
"env": {
// "DYLD_LIBRARY_PATH": "/Users/curtis/Library/Developer/Xcode/DerivedData/MacRhino-dalqjlsjnqqsltdayygnhqhgntxb/Build/Products/Debug/Rhinoceros.app/Contents/Frameworks"
"DYLD_LIBRARY_PATH": "/Applications/Rhino 8.app/Contents/Frameworks"
}
},
"justMyCode": false,
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole"
}
"console": "integratedTerminal",

},
{
"name": "Launch compute.geometry C++",
"type": "cppdbg",
"request": "launch",
"preLaunchTask": "Build",
"osx": {
"program": "${workspaceFolder}/src/bin/Debug/compute.geometry/compute.geometry",
},
"args": [
// "-runscript=\"grasshopper\""
],
"stopAtEntry": false,
"targetArchitecture": "arm64",
"cwd": "${workspaceFolder}/src/bin/Debug/compute.geometry",
"externalConsole": false,
"miDebuggerArgs": "--local-lldbinit ",
"MIMode": "lldb",
"environment": [
{ "name": "DYLD_LIBRARY_PATH", "value": "/Users/curtis/Library/Developer/Xcode/DerivedData/MacRhino-dalqjlsjnqqsltdayygnhqhgntxb/Build/Products/Debug/Rhinoceros.app/Contents/Frameworks"}
{ "name": "DOTNET_gcConcurrent", "value": "0" },
{ "name": "DOTNET_EnableDiagnostics", "value": "0" },
{ "name": "DOTNET_TC_QuickJit", "value": "1" },
// { "name": "DYLD_PRINT_LIBRARIES", "value": "1" }
]
},

],
"compounds": []
}
8 changes: 8 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>

<PropertyGroup>
<NoWarn>NU1701;NU1702</NoWarn>
<EnableWindowsTargeting>True</EnableWindowsTargeting>
</PropertyGroup>

</Project>
11 changes: 7 additions & 4 deletions src/compute.geometry/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class Program

static void Main(string[] args)
{
if (RhinoInside.Resolver.RelaunchIfNeeded())
return;

Config.Load();
Logging.Init();

Expand Down Expand Up @@ -76,9 +79,9 @@ static void Main(string[] args)

Log.CloseAndFlush();
}

static void ParseCommandLineArgs(string[] args)
{

static void ParseCommandLineArgs(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
string[] items = args[i].Split(':');
Expand Down Expand Up @@ -221,4 +224,4 @@ public void AddRoutes(IEndpointRouteBuilder app)
}
}
}
}
}
91 changes: 90 additions & 1 deletion src/compute.geometry/Resolver.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -62,6 +63,10 @@ public static string AssemblyPathFromName(string systemDirectory, string name)
if (name == "Microsoft.macOS")
return null;

// only use the plain name to resolve assemblies, not the full name.
var assemblyName = new AssemblyName(name);
name = assemblyName.Name;

string path = null;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Expand Down Expand Up @@ -98,6 +103,7 @@ static Assembly ResolveForRhinoAssemblies(object sender, ResolveEventArgs args)

static string FindRhinoSystemDirectory()
{

var major = Assembly.GetExecutingAssembly().GetName().Version.Major;

if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
Expand Down Expand Up @@ -134,9 +140,82 @@ static string FindRhinoSystemDirectory()
}
}
}

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// TODO: detect the app location
var path = "/Applications/Rhino 8.app";
// var path = "/Users/curtis/Library/Developer/Xcode/DerivedData/MacRhino-dalqjlsjnqqsltdayygnhqhgntxb/Build/Products/Debug/Rhinoceros.app";

path = Path.Combine(path, "Contents", "Frameworks");
if (Directory.Exists(path))
{
return path;
}
}

return null;
}

public static bool RelaunchIfNeeded()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return false;

const string RHCORE_LIB = "RhCore.framework/Versions/A/RhCore";
bool found = false;
var libPaths = Environment.GetEnvironmentVariable("DYLD_LIBRARY_PATH")?.Split(";").ToList();
if (libPaths != null)
{
foreach (var libPath in libPaths)
{
if (File.Exists(Path.Combine(libPath, RHCORE_LIB)))
{
// found Rhino! Let's use it.
RhinoSystemDirectory = libPath;
Console.WriteLine($"Using Rhino from {RhinoSystemDirectory}");
found = true;
break;
}
}
}
else
{
Console.WriteLine("DYLD_LIBRARY_PATH is null");
}

if (!found)
{
Console.WriteLine("DYLD_LIBRARY_PATH not set, launching as child process");

string systemDirectory = RhinoSystemDirectory;
if (!File.Exists(Path.Combine(systemDirectory, RHCORE_LIB)))
{
Console.WriteLine("Could not find Rhino");
return true;
}

// executable has the same name without the .dll extension
var executable = Assembly.GetEntryAssembly().Location;
if (executable.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
executable = executable.Substring(0, executable.Length - 4);
var startInfo = new ProcessStartInfo
{
UseShellExecute = false,
FileName = executable
};
foreach (var arg in Environment.GetCommandLineArgs())
{
startInfo.ArgumentList.Add(arg);
}
startInfo.Environment.Add("DYLD_LIBRARY_PATH", systemDirectory);
var process = Process.Start(startInfo);
process.WaitForExit();
return true;
}
return false;
}

public static void LoadRhino()
{
string systemDirectory = RhinoSystemDirectory;
Expand All @@ -158,13 +237,14 @@ public static void LoadRhino()
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
rhinoLibraryHandle = NativeLibrary.Load(Path.Combine(systemDirectory, "RhinoLibrary.framework/Versions/A/RhinoLibrary"));
AssemblyLoadContext.Default.ResolvingUnmanagedDll += ResolvingUnmanagedDll;
}
else
{
throw new Exception("Unsupported platform");
}

nint handle = NativeLibrary.GetExport(rhinoLibraryHandle, "RhLibRegisterDotNetInitializer");
IntPtr handle = NativeLibrary.GetExport(rhinoLibraryHandle, "RhLibRegisterDotNetInitializer");
var setLoaderProc = Marshal.GetDelegateForFunctionPointer<SetLoaderProc>(handle);

//Action load = () => ExecuteLoadProc(rhinoContext);
Expand All @@ -173,6 +253,15 @@ public static void LoadRhino()
setLoaderProc(load);
}

private static IntPtr ResolvingUnmanagedDll(Assembly assembly, string unmanagedDllName)
{
var systemDirectory = RhinoSystemDirectory;
if (unmanagedDllName == "RhinoLibrary")
return NativeLibrary.Load(Path.Combine(systemDirectory, "RhinoLibrary.framework/Versions/A/RhinoLibrary"));

return IntPtr.Zero;
}

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void SetLoaderProc(Action p);

Expand Down
39 changes: 26 additions & 13 deletions src/compute.geometry/compute.geometry.csproj
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<TargetFrameworks>net7.0;net7.0-windows</TargetFrameworks>
<AssemblyName>compute.geometry</AssemblyName>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<RuntimeFrameworkVersion>7.0.0</RuntimeFrameworkVersion>
<RollForward>LatestMinor</RollForward>
<UseWpf>True</UseWpf>
<UseWindowsForms>True</UseWindowsForms>
<SelfContained>False</SelfContained>
<PublishSingleFile>False</PublishSingleFile>
<AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>False</AppendRuntimeIdentifierToOutputPath>
<EnableWindowsTargeting>True</EnableWindowsTargeting>
<Version>8.0.0</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<OutputPath>..\bin\Debug\$(AssemblyName)</OutputPath>

<PropertyGroup Condition="$(TargetFramework) == 'net7.0-windows'">
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<UseWpf>True</UseWpf>
<UseWindowsForms>True</UseWindowsForms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<OutputPath>..\bin\Release\$(AssemblyName)</OutputPath>
<PublishDir>..\dist\$(AssemblyName)</PublishDir>
<PropertyGroup Condition="$(TargetFramework) == 'net7.0'">
<RuntimeIdentifiers>osx-x64;osx-arm64</RuntimeIdentifiers>
<ProduceOnlyReferenceAssembly Condition="$(RuntimeIdentifier) == ''">true</ProduceOnlyReferenceAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Optimize>True</Optimize>

<PropertyGroup>
<OutputPath Condition="$(ProduceOnlyReferenceAssembly) != 'true'">..\bin\$(Configuration)\$(AssemblyName)</OutputPath>
<PublishDir>..\dist\$(AssemblyName)</PublishDir>
</PropertyGroup>

<ItemGroup>
<Compile Remove="RhinoCompute.cs" />
</ItemGroup>
Expand All @@ -46,6 +48,17 @@
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.Management" Version="7.0.0" />
<PackageReference Include="System.Runtime.Caching" Version="7.0.0" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="7.0.0" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="7.0.0" Condition="$(TargetFramework) == 'net7.0-windows'" />
</ItemGroup>

<Target Name="After" AfterTargets="AfterBuild" Condition="$(TargetFramework) == 'net7.0'">
<Delete Files="$(OutputPath)System.Drawing.Common.dll" />
</Target>

<Target Name="BuildMac" AfterTargets="AfterBuild" Condition="$(RuntimeIdentifier) == 'win-x64'">
<MSBuild Projects="$(MSBuildProjectFile)" Properties="RuntimeIdentifier=osx-arm64;TargetFramework=net7.0" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="RuntimeIdentifier=osx-x64;TargetFramework=net7.0" />
</Target>


</Project>
18 changes: 9 additions & 9 deletions src/hops/HopsAppSettingsUserControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ public HopsAppSettingsUserControl()
};
_lblCacheCount.Text = $"({Hops.MemoryCache.EntryCount} items in cache)";

if (Rhino.Runtime.HostUtils.RunningOnOSX)
{
_hideWorkerWindows.Visible = false;
_launchWorkerAtStart.Visible = false;
_childComputeCount.Visible = false;
_updateChildCountButton.Visible = false;
}
else if (Rhino.Runtime.HostUtils.RunningOnWindows)
// if (Rhino.Runtime.HostUtils.RunningOnOSX)
// {
// _hideWorkerWindows.Visible = false;
// _launchWorkerAtStart.Visible = false;
// _childComputeCount.Visible = false;
// _updateChildCountButton.Visible = false;
// }
// else if (Rhino.Runtime.HostUtils.RunningOnWindows)
{
_hideWorkerWindows.Checked = HopsAppSettings.HideWorkerWindows;
_hideWorkerWindows.CheckedChanged += (s, e) =>
Expand Down Expand Up @@ -99,7 +99,7 @@ public HopsAppSettingsUserControl()
HopsUIHelper.MinGroupBoxHeight += extraSpace;
HopsUIHelper.MinControlHeight -= 32;
_gpboxFunctionMgr.Height += extraSpace;
_gpboxFunctionMgr.Top -= 74;
// _gpboxFunctionMgr.Top -= 74;
Size = new System.Drawing.Size(Size.Width, _gpboxFunctionMgr.Bottom + 4);
}

Expand Down
4 changes: 2 additions & 2 deletions src/hops/HopsComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public class HopsComponent : GH_TaskCapableComponent<Schema>, IGH_VariableParame

static HopsComponent()
{
if (!Rhino.Runtime.HostUtils.RunningOnWindows)
return;
// if (!Rhino.Runtime.HostUtils.RunningOnWindows)
// return;
if (Rhino.RhinoApp.IsRunningHeadless)
return;
if (Hops.HopsAppSettings.Servers.Length > 0)
Expand Down
Loading

0 comments on commit 8d5c6bb

Please sign in to comment.