Skip to content
Open
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
26 changes: 12 additions & 14 deletions sources/ClangSharp.Interop/clang.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -29,27 +30,24 @@ private static IntPtr OnDllImport(string libraryName, Assembly assembly, DllImpo
return nativeLibrary;
}

if (libraryName.Equals("libclang", StringComparison.Ordinal) && TryResolveClang(assembly, searchPath, out nativeLibrary))
// When invoked as a dotnet tool (ClangSharpPInvokeGenerator), native libraries
// are co-located with the executable in the NuGet cache but aren't found
// by the default resolver on Unix (default dlopen only searches system paths
// and LD_LIBRARY_PATH), so we explicitly try the application base directory.
// NativeLibrary.TryLoad with an absolute path does not apply platform-specific
// name mangling (lib prefix, .so/.dylib/.dll suffix), so we add it explicitly.
var suffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll"
: RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib"
: ".so";

if (NativeLibrary.TryLoad(Path.Combine(AppContext.BaseDirectory, libraryName + suffix), out nativeLibrary))
{
return nativeLibrary;
}

return IntPtr.Zero;
}

private static bool TryResolveClang(Assembly assembly, DllImportSearchPath? searchPath, out IntPtr nativeLibrary)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We explicitly want to keep this functionality.

I'm fine with explicitly trying the application directory first on non-Windows (which then is similar to SafeDirectories for Windows which is application directory, %windir%\system32, and user directories in the dll search path)

But we do want to search the system folder still otherwise and check for the various names it can bind to there

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since LoadLibraryHelper on unix ignores the flags, we'd rather want to effectively do something like

if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    if (searchPath.GetValueOrDefault().HasFlag(DllImportSearchPath.ApplicationDirectory))
    {
        // Try the names using AppContext.BaseDirectory
    }

    // Try the standard variations
}

For apple target we want to try just the name + .dylib

For Linux we want to try the 3 variations already covered, in that order; first for app directory then for the normal system search

{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return NativeLibrary.TryLoad("libclang.so.20", assembly, searchPath, out nativeLibrary)
|| NativeLibrary.TryLoad("libclang-20", assembly, searchPath, out nativeLibrary)
|| NativeLibrary.TryLoad("libclang.so.1", assembly, searchPath, out nativeLibrary);
}

nativeLibrary = IntPtr.Zero;
return false;
}

private static bool TryResolveLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr nativeLibrary)
{
var resolveLibrary = ResolveLibrary;
Expand Down
Loading