Skip to content
This repository has been archived by the owner on Jan 25, 2023. It is now read-only.

Commit

Permalink
Implemented auto symlink creation for required python library.
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanov committed Oct 14, 2016
1 parent 6310f7b commit 74636e7
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 35 deletions.
6 changes: 0 additions & 6 deletions src/Python.Bootstrapper.Test/BootstrapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,5 @@ public void LoadAssemblyTest()
dllContent = PythonRuntimeBootstrapper.LoadRequiredAssembly("SomeNonZipFile.txt");
dllContent.Length.Should().BePositive();
}

[Test]
public void UpdateLdLibraryPathTest()
{
PythonRuntimeBootstrapper.ExtendLinuxLibraryPath();
}
}
}
64 changes: 62 additions & 2 deletions src/Python.Bootstrapper.Test/Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,70 @@
namespace Python.Bootstrapper.Test
{
using System;
using System.IO;

using Runtime;
public class Program
{
static void Main(string[] args)
static Program()
{
Console.WriteLine("Starting application...");

// Required to be placed in the static constructor for Mono.
var loadedLib = PythonRuntimeBootstrapper.DetectPythonAndRegisterRuntime();
Console.WriteLine($"{loadedLib} runtime loaded.");
}
static int Main(string[] args)
{
PythonRuntimeBootstrapper.DetectPythonAndRegisterRuntime();
// Mono workaround required to fix AssemblyResolve + EntryPoint class bug.
// Classes that was referenced from EntryPoint class cannot use assemblies resolved through "AssemblyResolve"
Action monoWorkaround = () =>
{
try
{
// You should put this initialized only if some component starting to use it before first application configuration file read attempt.
// So in rare cases.
//// PythonConfig.EnsureInitialized();


PythonEngine.Initialize();

try
{
using (Py.GIL())
{
dynamic sysModule = Py.Import("sys");
Console.WriteLine("Python engine version:");
Console.WriteLine(sysModule.version);
}

// This workaround reduces risk of Mono crash.
// Problem will be fixed in mono 4.6
if (Path.DirectorySeparatorChar == '/' || Type.GetType("Mono.Runtime") != null)
{
Runtime.Py_Main(3, new[] { "/pcfgtest.exe", "-c", "exit" });
}
else
{
// Program will crash if we will try to do this under Windows.
//// Runtime.Py_Main(3, new[] { "/pcfgtest.exe", "-c", "exit" });
}
}
finally
{
PythonEngine.Shutdown();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}

};

monoWorkaround();

return 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
<HintPath>..\..\packages\FluentAssertions.4.15.0\lib\net45\FluentAssertions.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
Expand Down
7 changes: 0 additions & 7 deletions src/Python.Bootstrapper/Python.Bootstrapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
Expand All @@ -51,9 +47,6 @@
<Compile Include="PythonRuntimeBootstrapper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
26 changes: 11 additions & 15 deletions src/Python.Bootstrapper/PythonRuntimeBootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;

/// <summary>
Expand Down Expand Up @@ -36,17 +37,18 @@ public static string DetectPythonAndRegisterRuntime()
throw new FileNotFoundException($"Error loading {dllName} from Python.Runtime.zip: {ex.Message}");
}

if (os == "elf")
{
ExtendLinuxLibraryPath();
}

AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolveHandler;
var pythonRuntimeType =
Type.GetType(
"Python.Runtime.Runtime, Python.Runtime, Version=4.0.0.1, Culture=neutral, PublicKeyToken=null",
true);

if (os == "elf")
{
MakeLibSymLink(pythonRuntimeType);
}

return dllName;
}

Expand Down Expand Up @@ -159,7 +161,7 @@ internal static string DetectRequiredPythonRuntimDll(out string os)
/// <summary>
/// Adds required python libraries pathes to LD_LIBRARY_PATH variable.
/// </summary>
internal static void ExtendLinuxLibraryPath()
internal static void MakeLibSymLink(Type pythonLoaderType)
{
string stdOut;
string stdErr;
Expand Down Expand Up @@ -197,7 +199,6 @@ internal static void ExtendLinuxLibraryPath()
var result = stdOut.Split('\n');
if (result.Length == 2)
{
string librariesPath = (Environment.GetEnvironmentVariable("LD_LIBRARY_PATH") ?? string.Empty).Trim();
var librariesPathElements = new List<string>();
for (int i = 0; i < result.Length; i++)
{
Expand All @@ -208,16 +209,11 @@ internal static void ExtendLinuxLibraryPath()
}
}

if (librariesPath != string.Empty)
{
librariesPathElements.Add(librariesPath);
}
var makeSymLinkLibMethodInfo = pythonLoaderType.GetMethod(
"MakeLibSymLink",
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

librariesPath = string.Join(":", librariesPathElements);
if (librariesPath != string.Empty)
{
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", librariesPath);
}
makeSymLinkLibMethodInfo.Invoke(null, new object[] { librariesPathElements });
}
else
{
Expand Down
4 changes: 0 additions & 4 deletions src/Python.Bootstrapper/packages.config

This file was deleted.

43 changes: 42 additions & 1 deletion src/runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Python.Runtime
{
using System.Collections.Generic;
using System.IO;
using System.Linq;

[SuppressUnmanagedCodeSecurityAttribute()]
Expand Down Expand Up @@ -215,8 +217,47 @@ public class Runtime
internal static bool IsFinalizing = false;

internal static bool wrap_exceptions;
internal static bool is32bit;
internal static bool is32bit;

#if MONO_LINUX
internal static void MakeLibSymLink(List<string> seachPathes)
{
try
{
string foundLibFullPath = null;
foreach (var seachPath in seachPathes)
{
var pathToTest = Path.Combine(seachPath, $"lib{dll}.so");
if (File.Exists(pathToTest))
{
foundLibFullPath = pathToTest;
break;
}
}

if (foundLibFullPath != null)
{
var localLibFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"lib{dll}.so");
if (File.Exists(localLibFile))
{
File.Delete(localLibFile);
}

UnixFileInfo libFileInfo = new UnixFileInfo(foundLibFullPath);
libFileInfo.CreateSymbolicLink(localLibFile);
}
}
catch (Exception ex)
{
// do nothing.
}
}
#else
internal static void MakeLibSymLink(List<string> seachPathes)
{
throw new NotSupportedException("Sym Link patch only required on linux platform.");
}
#endif
/// <summary>
/// Intitialize the runtime...
/// </summary>
Expand Down

0 comments on commit 74636e7

Please sign in to comment.