diff --git a/NuGet.config b/NuGet.config
index 3b47eb2e33ec79..a1337574ac916a 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -9,7 +9,7 @@
-
+
7.0.100-rc.1.22402.1
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 2.5.1-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
- 7.0.0-beta.23164.3
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 2.5.1-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
+ 7.0.0-beta.23211.2
6.0.0-preview.1.102
@@ -177,7 +177,7 @@
7.0.100-1.23207.1
$(MicrosoftNETILLinkTasksVersion)
- 7.0.0-rtm.23115.1
+ 7.0.0-rtm.23211.1
2.1.1
7.0.0-alpha.1.22459.1
diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh
index 41a26d802a93f8..f13b74080edf9b 100644
--- a/eng/common/native/init-compiler.sh
+++ b/eng/common/native/init-compiler.sh
@@ -71,7 +71,7 @@ if [[ -z "$CLR_CC" ]]; then
# Set default versions
if [[ -z "$majorVersion" ]]; then
# note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero.
- if [[ "$compiler" == "clang" ]]; then versions=( 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 )
+ if [[ "$compiler" == "clang" ]]; then versions=( 16 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 )
elif [[ "$compiler" == "gcc" ]]; then versions=( 12 11 10 9 8 7 6 5 4.9 ); fi
for version in "${versions[@]}"; do
diff --git a/eng/pipelines/runtime-extra-platforms-other.yml b/eng/pipelines/runtime-extra-platforms-other.yml
index 7ef2f1bee1e6a5..3f77cd342fc374 100644
--- a/eng/pipelines/runtime-extra-platforms-other.yml
+++ b/eng/pipelines/runtime-extra-platforms-other.yml
@@ -143,7 +143,7 @@ jobs:
jobParameters:
testScope: innerloop
nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true
+ buildArgs: -s mono+mono.mscordbi+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true
timeoutInMinutes: 120
condition: >-
or(
diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml
index caae555af012d9..569e0052ee1f28 100644
--- a/eng/pipelines/runtime-official.yml
+++ b/eng/pipelines/runtime-official.yml
@@ -144,7 +144,7 @@ stages:
# - windows_arm
# - windows_arm64
jobParameters:
- buildArgs: -s mono+libs+host+packs+mono.mscordbi -c $(_BuildConfig)
+ buildArgs: -s mono+libs+host+packs -c $(_BuildConfig)
nameSuffix: AllSubsets_Mono
isOfficialBuild: ${{ variables.isOfficialBuild }}
extraStepsTemplate: /eng/pipelines/common/upload-intermediate-artifacts-step.yml
@@ -159,7 +159,7 @@ stages:
platforms:
- Browser_wasm
jobParameters:
- buildArgs: -s mono+libs+host+packs+mono.mscordbi -c $(_BuildConfig) /p:MonoWasmBuildVariant=perftrace
+ buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) /p:MonoWasmBuildVariant=perftrace
nameSuffix: AllSubsets_Mono_perftrace
isOfficialBuild: ${{ variables.isOfficialBuild }}
runtimeVariant: perftrace
@@ -175,7 +175,7 @@ stages:
platforms:
- Browser_wasm
jobParameters:
- buildArgs: -s mono+libs+host+packs+mono.mscordbi -c $(_BuildConfig) /p:MonoWasmBuildVariant=multithread
+ buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) /p:MonoWasmBuildVariant=multithread
nameSuffix: AllSubsets_Mono_multithread
isOfficialBuild: ${{ variables.isOfficialBuild }}
runtimeVariant: multithread
diff --git a/global.json b/global.json
index 4a7f1a9cdb1f6e..b9d7d81f1f2ad2 100644
--- a/global.json
+++ b/global.json
@@ -1,16 +1,16 @@
{
"sdk": {
- "version": "7.0.104",
+ "version": "7.0.105",
"allowPrerelease": true,
"rollForward": "major"
},
"tools": {
- "dotnet": "7.0.104"
+ "dotnet": "7.0.105"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23164.3",
- "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23164.3",
- "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23164.3",
+ "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23211.2",
+ "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23211.2",
+ "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23211.2",
"Microsoft.Build.NoTargets": "3.5.0",
"Microsoft.Build.Traversal": "3.1.6",
"Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6"
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
index 8e383b44d85033..0c1a2a520e2cf0 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
@@ -309,8 +309,8 @@ internal static unsafe void FixupModuleCell(ModuleFixupCell* pCell)
hModule = NativeLibrary.LoadBySearch(
callingAssembly,
- searchAssemblyDirectory: false,
- dllImportSearchPathFlags: 0,
+ searchAssemblyDirectory: (dllImportSearchPath & (uint)DllImportSearchPath.AssemblyDirectory) != 0,
+ dllImportSearchPathFlags: (int)(dllImportSearchPath & ~(uint)DllImportSearchPath.AssemblyDirectory),
ref loadLibErrorTracker,
moduleName);
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs
index 3708b256808e88..1c95dbc088b4fd 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs
@@ -20,7 +20,7 @@ internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly,
bool searchAssemblyDirectory;
if (searchPath.HasValue)
{
- searchPathFlags = (int)(searchPath.Value & ~DllImportSearchPath.AssemblyDirectory);
+ searchPathFlags = (int)(searchPath!.Value & ~DllImportSearchPath.AssemblyDirectory);
searchAssemblyDirectory = (searchPath.Value & DllImportSearchPath.AssemblyDirectory) != 0;
}
else
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
index 4971ca48763fe9..4be5ad213a1b84 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using Internal.IL.Stubs;
@@ -97,8 +98,16 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField)
PInvokeMetadata metadata = pInvokeLazyFixupField.PInvokeMetadata;
ModuleDesc declaringModule = ((MetadataType)pInvokeLazyFixupField.TargetMethod.OwningType).Module;
- DllImportSearchPath? dllImportSearchPath = default;
- if (declaringModule.Assembly is EcmaAssembly asm)
+ CustomAttributeValue? decodedAttr = null;
+
+ // Look for DefaultDllImportSearchPath on the method
+ if (pInvokeLazyFixupField.TargetMethod is EcmaMethod method)
+ {
+ decodedAttr = method.GetDecodedCustomAttribute("System.Runtime.InteropServices", "DefaultDllImportSearchPathsAttribute");
+ }
+
+ // If the attribute it wasn't found on the method, look for it on the assembly
+ if (!decodedAttr.HasValue && declaringModule.Assembly is EcmaAssembly asm)
{
// We look for [assembly:DefaultDllImportSearchPaths(...)]
var attrHandle = asm.MetadataReader.GetCustomAttributeHandle(asm.AssemblyDefinition.GetCustomAttributes(),
@@ -106,14 +115,18 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField)
if (!attrHandle.IsNil)
{
var attr = asm.MetadataReader.GetCustomAttribute(attrHandle);
- var decoded = attr.DecodeValue(new CustomAttributeTypeProvider(asm));
- if (decoded.FixedArguments.Length == 1 &&
- decoded.FixedArguments[0].Value is int searchPath)
- {
- dllImportSearchPath = (DllImportSearchPath)searchPath;
- }
+ decodedAttr = attr.DecodeValue(new CustomAttributeTypeProvider(asm));
}
}
+
+ DllImportSearchPath? dllImportSearchPath = default;
+ if (decodedAttr.HasValue
+ && decodedAttr.Value.FixedArguments.Length == 1
+ && decodedAttr.Value.FixedArguments[0].Value is int searchPath)
+ {
+ dllImportSearchPath = (DllImportSearchPath)searchPath;
+ }
+
ModuleData = new PInvokeModuleData(metadata.Module, dllImportSearchPath, declaringModule);
EntryPointName = metadata.Name;
diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs
index 95b3f870db5d0b..63b4a827d6790b 100644
--- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs
+++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs
@@ -64,8 +64,21 @@ private MsQuicApi(QUIC_API_TABLE* apiTable)
#pragma warning disable CA1810 // Initialize all static fields in 'MsQuicApi' when those fields are declared and remove the explicit static constructor
static MsQuicApi()
{
- if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MinMsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle) &&
- !NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle))
+ bool loaded = false;
+ IntPtr msQuicHandle;
+ if (OperatingSystem.IsWindows())
+ {
+ // Windows ships msquic in the assembly directory.
+ loaded = NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle);
+ }
+ else
+ {
+ // Non-Windows relies on the package being installed on the system and may include the version in its name
+ loaded = NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MinMsQuicVersion.Major}", typeof(MsQuicApi).Assembly, null, out msQuicHandle) ||
+ NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, null, out msQuicHandle);
+ }
+
+ if (!loaded)
{
// MsQuic library not loaded
return;
diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c
index 164a3aef132f22..e89a741752f2af 100644
--- a/src/mono/mono/metadata/native-library.c
+++ b/src/mono/mono/metadata/native-library.c
@@ -533,10 +533,13 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags, Mo
ERROR_DECL (bad_image_error);
- // Try without any path additions
+#if defined(HOST_ANDROID)
+ // On Android, try without any path additions first. It is sensitive to probing that will always miss
+ // and lookup for some libraries is required to use a relative path
module = netcore_probe_for_module_variations (NULL, file_name, lflags, error);
if (!module && !is_ok (error) && mono_error_get_error_code (error) == MONO_ERROR_BAD_IMAGE)
mono_error_move (bad_image_error, error);
+#endif
// Check the NATIVE_DLL_SEARCH_DIRECTORIES
for (int i = 0; i < pinvoke_search_directories_count && module == NULL; ++i) {
@@ -560,6 +563,16 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags, Mo
g_free (mdirname);
}
+#if !defined(HOST_ANDROID)
+ // Try without any path additions
+ if (module == NULL)
+ {
+ module = netcore_probe_for_module_variations (NULL, file_name, lflags, error);
+ if (!module && !is_ok (error) && mono_error_get_error_code (error) == MONO_ERROR_BAD_IMAGE)
+ mono_error_move (bad_image_error, error);
+ }
+#endif
+
// TODO: Pass remaining flags on to LoadLibraryEx on Windows where appropriate, see https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportsearchpath?view=netcore-3.1
if (!module && !is_ok (bad_image_error)) {
diff --git a/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs b/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs
index 429d637b28de79..5d15c0825d532f 100644
--- a/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs
+++ b/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs
@@ -10,8 +10,12 @@ public static class PlatformDetection
{
public static bool Is32BitProcess => IntPtr.Size == 4;
public static bool Is64BitProcess => IntPtr.Size == 8;
-
+
public static bool IsX86Process => RuntimeInformation.ProcessArchitecture == Architecture.X86;
public static bool IsNotX86Process => !IsX86Process;
+
+ private static string _variant = Environment.GetEnvironmentVariable("DOTNET_RUNTIME_VARIANT");
+
+ public static bool IsMonoLLVMFULLAOT => _variant == "llvmfullaot";
}
}
diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj
index afa5bbecf7b684..b601b280a1ed4a 100644
--- a/src/tests/Common/testenvironment.proj
+++ b/src/tests/Common/testenvironment.proj
@@ -258,6 +258,8 @@
<_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'monointerpreter'" Include="set MONO_ENV_OPTIONS=--interpreter" />
+ <_TestEnvFileLine Condition="'$(RuntimeVariant)' != ''" Include="set DOTNET_RUNTIME_VARIANT=$(RuntimeVariant)" />
+
<_TestEnvFileLine Condition="'$(Scenario)' == 'clrinterpreter'" Include="set COMPlus_Interpret=%2A" />
<_TestEnvFileLine Condition="'$(Scenario)' == 'clrinterpreter'" Include="set COMPlus_InterpreterHWIntrinsicsIsSupportedFalse=1" />
@@ -273,6 +275,8 @@
<_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'monointerpreter'" Include="export MONO_ENV_OPTIONS=--interpreter" />
+ <_TestEnvFileLine Condition="'$(RuntimeVariant)' != ''" Include="export DOTNET_RUNTIME_VARIANT=$(RuntimeVariant)" />
+
<_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'llvmaot'" Include="export MONO_ENV_OPTIONS=--llvm" />
diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets
index 000af600e2a616..7008a3c4e0ce55 100644
--- a/src/tests/Directory.Build.targets
+++ b/src/tests/Directory.Build.targets
@@ -537,13 +537,17 @@
<_UsingDefaultForHasRuntimeOutput>false
+
+
+
+
diff --git a/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs
new file mode 100644
index 00000000000000..31e69aeab90f72
--- /dev/null
+++ b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xunit;
+
+public class DllImportSearchPathsTest
+{
+ private static string Subdirectory => Path.Combine(NativeLibraryToLoad.GetDirectory(), "subdirectory");
+
+ [Fact]
+ public static void AssemblyDirectory_NotFound()
+ {
+ // Library should not be found in the assembly directory
+ Assert.Throws(() => NativeLibraryPInvoke.Sum(1, 2));
+ }
+
+ public static bool CanLoadAssemblyInSubdirectory =>
+ !TestLibrary.Utilities.IsNativeAot && !TestLibrary.PlatformDetection.IsMonoLLVMFULLAOT;
+
+ [ConditionalFact(nameof(CanLoadAssemblyInSubdirectory))]
+ public static void AssemblyDirectory_Found()
+ {
+ // Library should be found in the assembly directory
+ var assembly = Assembly.LoadFile(Path.Combine(Subdirectory, $"{nameof(DllImportSearchPathsTest)}.dll"));
+ var type = assembly.GetType(nameof(NativeLibraryPInvoke));
+ var method = type.GetMethod(nameof(NativeLibraryPInvoke.Sum));
+
+ int sum = (int)method.Invoke(null, new object[] { 1, 2 });
+ Assert.Equal(3, sum);
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void AssemblyDirectory_Fallback_Found()
+ {
+ string currentDirectory = Environment.CurrentDirectory;
+ try
+ {
+ Environment.CurrentDirectory = Subdirectory;
+
+ // Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows
+ int sum = NativeLibraryPInvoke.Sum(1, 2);
+ Assert.Equal(3, sum);
+ }
+ finally
+ {
+ Environment.CurrentDirectory = currentDirectory;
+ }
+ }
+}
+
+public class NativeLibraryPInvoke
+{
+ public static int Sum(int a, int b)
+ {
+ return NativeSum(a, b);
+ }
+
+ [DllImport(NativeLibraryToLoad.Name)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
+ static extern int NativeSum(int arg1, int arg2);
+}
diff --git a/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.csproj b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.csproj
new file mode 100644
index 00000000000000..2456564dbb9304
--- /dev/null
+++ b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.csproj
@@ -0,0 +1,24 @@
+
+
+ true
+
+
+
+
+
+
+
+
+
+ $(OutDir)/subdirectory
+ -in-subdirectory
+
+
+ <_FilesToCopy Include="$(OutDir)/$(TargetName).dll" />
+ <_FilesToMove Include="$(OutDir)/libNativeLibrary.*" />
+ <_FilesToMove Include="$(OutDir)/NativeLibrary.*" />
+
+
+
+
+
diff --git a/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs b/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs
index 58ec31f5d60b91..edefe6e32f446a 100644
--- a/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs
+++ b/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs
@@ -45,7 +45,7 @@ public static void GloballyLoadedLibrarySymbolsVisibleFromMainProgramHandle()
// On non-Windows platforms, symbols from globally loaded shared libraries will also be discoverable.
// Globally loading symbols is not the .NET default, so we use a call to dlopen in native code
// with the right flags to test the scenario.
- IntPtr handle = LoadLibraryGlobally(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary")));
+ IntPtr handle = LoadLibraryGlobally(Path.Combine(NativeLibraryToLoad.GetDirectory(), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary")));
try
{
@@ -64,7 +64,7 @@ public static void InvalidSymbolName_Fails()
// On non-Windows platforms, symbols from globally loaded shared libraries will also be discoverable.
// Globally loading symbols is not the .NET default, so we use a call to dlopen in native code
// with the right flags to test the scenario.
- IntPtr handle = LoadLibraryGlobally(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary")));
+ IntPtr handle = LoadLibraryGlobally(Path.Combine(NativeLibraryToLoad.GetDirectory(), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary")));
try
{
@@ -83,7 +83,7 @@ public static void GloballyLoadedLibrarySymbolsVisibleFromMainProgramHandle_Mang
// On non-Windows platforms, symbols from globally loaded shared libraries will also be discoverable.
// Globally loading symbols is not the .NET default, so we use a call to dlopen in native code
// with the right flags to test the scenario.
- IntPtr handle = LoadLibraryGlobally(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary")));
+ IntPtr handle = LoadLibraryGlobally(Path.Combine(NativeLibraryToLoad.GetDirectory(), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary")));
try
{
diff --git a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs
index 2d5f1c3734557c..f3115f5f4e4207 100644
--- a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs
+++ b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs
@@ -17,7 +17,7 @@ public class NativeLibraryTests : IDisposable
public NativeLibraryTests()
{
assembly = System.Reflection.Assembly.GetExecutingAssembly();
- testBinDir = Path.GetDirectoryName(assembly.Location);
+ testBinDir = NativeLibraryToLoad.GetDirectory();
libFullPath = NativeLibraryToLoad.GetFullPath();
}
@@ -133,11 +133,19 @@ public void LoadLibraryFullPathWithoutNativePrefixOrSuffix_WithAssembly_Failure(
public void LoadSystemLibrary_WithSearchPath()
{
string libName = "url.dll";
- // Calls on a valid library from System32 directory
+ // Library should be found in the system directory
EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.System32));
EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.System32));
- // Calls on a valid library from application directory
+ // Library should not be found in the assembly directory and should be found in the system directory
+ EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32));
+ EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32));
+
+ // Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows
+ EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory));
+ EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory));
+
+ // Library should not be found in application directory
EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.ApplicationDirectory), TestResult.DllNotFound);
EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.ApplicationDirectory), TestResult.ReturnFailure);
}
@@ -165,6 +173,40 @@ public void LoadLibrary_UsesFullPath_EvenWhen_AssemblyDirectory_Specified()
EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.ReturnFailure);
}
+ [Fact]
+ public void LoadLibrary_AssemblyDirectory()
+ {
+ string suffix = "-in-subdirectory";
+ string libName = $"{NativeLibraryToLoad.Name}{suffix}";
+
+ string subdirectory = Path.Combine(testBinDir, "subdirectory");
+
+ if (!TestLibrary.Utilities.IsNativeAot && !TestLibrary.PlatformDetection.IsMonoLLVMFULLAOT)
+ {
+ // Library should be found in the assembly directory
+ Assembly assemblyInSubdirectory = Assembly.LoadFile(Path.Combine(subdirectory, $"{Path.GetFileNameWithoutExtension(assembly.Location)}{suffix}.dll"));
+ EXPECT(LoadLibrary_WithAssembly(libName, assemblyInSubdirectory, DllImportSearchPath.AssemblyDirectory));
+ EXPECT(TryLoadLibrary_WithAssembly(libName, assemblyInSubdirectory, DllImportSearchPath.AssemblyDirectory));
+ }
+
+ if (OperatingSystem.IsWindows())
+ {
+ string currentDirectory = Environment.CurrentDirectory;
+ try
+ {
+ Environment.CurrentDirectory = subdirectory;
+
+ // Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows
+ EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory));
+ EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory));
+ }
+ finally
+ {
+ Environment.CurrentDirectory = currentDirectory;
+ }
+ }
+ }
+
[Fact]
public void Free()
{
diff --git a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj
index 50c9834e83a168..f6dd733af6d438 100644
--- a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj
+++ b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj
@@ -15,4 +15,17 @@
+
+
+
+ $(OutDir)/subdirectory
+ -in-subdirectory
+
+
+
+
+
+
+
+
diff --git a/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs b/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs
index c77a187e5c0874..351b8b4d1a5a09 100644
--- a/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs
+++ b/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs
@@ -99,7 +99,7 @@ private IntPtr ResolveDllImport(string libraryName, Assembly asm, DllImportSearc
if (string.Equals(libraryName, NativeLibraryToLoad.InvalidName))
{
Assert.Equal(DllImportSearchPath.System32, dllImportSearchPath);
- return NativeLibrary.Load(NativeLibraryToLoad.Name, asm, null);
+ return NativeLibrary.Load(NativeLibraryToLoad.GetFullPath(), asm, null);
}
return IntPtr.Zero;
diff --git a/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs b/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs
index 21dc1ca1c9c986..3acc65116eab28 100644
--- a/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs
+++ b/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs
@@ -32,8 +32,23 @@ public static string GetLibraryFileName(string name)
public static string GetFullPath()
{
- Assembly assembly = Assembly.GetExecutingAssembly();
- string directory = Path.GetDirectoryName(assembly.Location);
- return Path.Combine(directory, GetFileName());
+ return Path.Combine(GetDirectory(), GetFileName());
+ }
+
+ public static string GetDirectory()
+ {
+ string directory;
+ if (TestLibrary.Utilities.IsNativeAot)
+ {
+ // NativeAOT test is put in a native/ subdirectory, so we want the parent
+ // directory that contains the native library to load
+ directory = new DirectoryInfo(AppContext.BaseDirectory).Parent.FullName;
+ }
+ else
+ {
+ directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ }
+
+ return directory;
}
}
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index cf842bd2967bd8..db7896e9d99325 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -1032,9 +1032,6 @@
https://github.com/dotnet/runtimelab/issues/166
-
- https://github.com/dotnet/runtimelab/issues/206
-
https://github.com/dotnet/runtimelab/issues/176: VARIANT marshalling