From 72625a9b5038eb82dfe944e93cfb9a4d75f9ec09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Mon, 15 Sep 2025 13:44:23 +0200 Subject: [PATCH 01/12] Make Logger and nativecsharpextension compile on Linux. --- .../dotnet-core-CSharp/include/DotnetEnvironment.h | 10 ++++++++++ .../dotnet-core-CSharp/include/Logger.h | 1 - .../dotnet-core-CSharp/include/nativecsharpextension.h | 3 +++ .../dotnet-core-CSharp/src/native/Logger.cpp | 2 -- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h index c84b6cd..755141a 100644 --- a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h +++ b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h @@ -10,13 +10,23 @@ //********************************************************************* #pragma once +#if defined(__WIN32) || defined(WINDOWS) #include "Windows.h" +#else +#define E_FAIL 0x80004005 +#endif + #include #include #include +#if defined(__WIN32) || defined(WINDOWS) #define STR(s) L ## s #define CH(c) L ## c +#else +#define STR(s) s +#define CH(c) c +#endif using namespace std; using string_t = std::basic_string; diff --git a/language-extensions/dotnet-core-CSharp/include/Logger.h b/language-extensions/dotnet-core-CSharp/include/Logger.h index 2a96ec0..fa43d0b 100644 --- a/language-extensions/dotnet-core-CSharp/include/Logger.h +++ b/language-extensions/dotnet-core-CSharp/include/Logger.h @@ -10,7 +10,6 @@ //********************************************************************* #include #include -#include using namespace std; #define LOG(msg) Logger::Log(msg) diff --git a/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h b/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h index 8a1a341..ad2b0c7 100644 --- a/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h +++ b/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h @@ -20,7 +20,10 @@ #include #include +#if defined(__WIN32) || defined(WINDOWS) #include +#endif + #include #include "sqlexternallanguage.h" #include "sqlexternallibrary.h" diff --git a/language-extensions/dotnet-core-CSharp/src/native/Logger.cpp b/language-extensions/dotnet-core-CSharp/src/native/Logger.cpp index 89d8585..c44b011 100644 --- a/language-extensions/dotnet-core-CSharp/src/native/Logger.cpp +++ b/language-extensions/dotnet-core-CSharp/src/native/Logger.cpp @@ -10,8 +10,6 @@ //********************************************************************* #include #include -#include -#include #include "Logger.h" using namespace std; From d52769f385300687bd75556338907ed0e63871f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Mon, 15 Sep 2025 14:28:40 +0200 Subject: [PATCH 02/12] Make DotnetEnvironment compile on Linux. --- .../include/DotnetEnvironment.h | 3 +- .../src/native/DotnetEnvironment.cpp | 35 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h index 755141a..93edcab 100644 --- a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h +++ b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h @@ -13,7 +13,8 @@ #if defined(__WIN32) || defined(WINDOWS) #include "Windows.h" #else -#define E_FAIL 0x80004005 +#define E_FAIL -1 +#define S_OK 0 #endif #include diff --git a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp index a2b2f82..22e865e 100644 --- a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp +++ b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp @@ -10,16 +10,28 @@ //********************************************************************* #include "DotnetEnvironment.h" #include "Logger.h" + +#if defined(_WIN32) || defined(WINDOWS) #include "Windows.h" +#else +#include +#endif + #include +#include #include #include #include #include #include +#if defined(__WIN32) || defined(WINDOWS) #define STR(s) L ## s #define CH(c) L ## c +#else +#define STR(s) s +#define CH(c) c +#endif using namespace std; using string_t = std::basic_string; @@ -34,7 +46,12 @@ DotnetEnvironment::DotnetEnvironment( std::string language_params, std::string language_path, std::string public_library_path, - std::string private_library_path) : m_root_path(to_utf16_str(language_path)) + std::string private_library_path) : +#if defined(_WIN32) || defined(WINDOWS) + m_root_path(to_utf16_str(language_path)) +#else + m_root_path(language_path) +#endif { } @@ -68,6 +85,7 @@ short DotnetEnvironment::Init() return S_OK; } +#if defined(_WIN32) || defined(WINDOWS) //-------------------------------------------------------------------------------------------------- // Name: DotnetEnvironment::to_utf16_str // @@ -82,6 +100,7 @@ string_t DotnetEnvironment::to_utf16_str(const std::string& utf8str) MultiByteToWideChar(CP_UTF8, 0, utf8str.c_str(), -1, wstr.get(), wchars_num); return string_t(wstr.get()); } +#endif //-------------------------------------------------------------------------------------------------- // Name: DotnetEnvironment::to_hex_string @@ -106,7 +125,11 @@ string DotnetEnvironment::to_hex_string(int value) void* DotnetEnvironment::load_library(const char_t *path) { LOG("DotnetEnvironment::load_library"); +#if defined(_WIN32) || defined(WINDOWS) HMODULE h = ::LoadLibraryW(path); +#else + void *h = dlopen(path, RTLD_LAZY); +#endif assert(h != nullptr); return (void*)h; } @@ -120,13 +143,17 @@ void* DotnetEnvironment::load_library(const char_t *path) void* DotnetEnvironment::get_export(void *h, const char *name) { LOG("DotnetEnvironment::get_export"); +#if defined(_WIN32) || defined(WINDOWS) void *f = ::GetProcAddress((HMODULE)h, name); +#else + void *f = dlsym(h, name); +#endif assert(f != nullptr); return f; } //-------------------------------------------------------------------------------------------------- -// Name: DotnetEnvironment::get_export +// Name: DotnetEnvironment::load_hostfxr // // Description: // Load hostfxr and get desired exports @@ -134,7 +161,11 @@ void* DotnetEnvironment::get_export(void *h, const char *name) bool DotnetEnvironment::load_hostfxr() { LOG("DotnetEnvironment::load_hostfxr"); +#if defined(_WIN32) || defined(WINDOWS) string_t hostfxr_location = m_root_path + STR("\\hostfxr.dll"); +#else + string_t hostfxr_location = STR("libhostfxr.so"); +#endif void *lib = load_library(hostfxr_location.c_str()); m_init_fptr = (hostfxr_initialize_for_runtime_config_fn)get_export(lib, "hostfxr_initialize_for_runtime_config"); m_get_delegate_fptr = (hostfxr_get_runtime_delegate_fn)get_export(lib, "hostfxr_get_runtime_delegate"); From 02420c2321e36ee2afd953ec2d590caeafb29575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Mon, 15 Sep 2025 15:07:15 +0200 Subject: [PATCH 03/12] Add build script for Linux. --- .../build-dotnet-core-CSharp-extension.ps1 | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100755 language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 diff --git a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 new file mode 100755 index 0000000..4f2c09e --- /dev/null +++ b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 @@ -0,0 +1,106 @@ +#!/usr/bin/env pwsh + +# Set root and working directories +$ENL_ROOT = Join-Path $PSScriptRoot "../../../.." +$DOTNET_EXTENSION_HOME = Join-Path $ENL_ROOT "language-extensions/dotnet-core-CSharp" +$DOTNET_EXTENSION_WORKING_DIR = Join-Path $ENL_ROOT "build-output/dotnet-core-CSharp-extension/linux" + +# Clean and create working directory +if (Test-Path $DOTNET_EXTENSION_WORKING_DIR) { + Remove-Item $DOTNET_EXTENSION_WORKING_DIR -Recurse -Force +} +New-Item -ItemType Directory -Path $DOTNET_EXTENSION_WORKING_DIR | Out-Null + +$i = 0 + +# Process each build configuration +while($true) { + $BUILD_CONFIGURATION = "" + if ($i -lt $args.Count) { + $BUILD_CONFIGURATION = $args[$i] + } + # Default to release if not debug + if ($BUILD_CONFIGURATION -ne "debug") { + $BUILD_CONFIGURATION = "release" + } + + # Set target directory + $TARGET = Join-Path $ENL_ROOT "build-output/dotnet-core-CSharp-extension/target/$BUILD_CONFIGURATION" + + # Clean and create target directory + if (Test-Path $TARGET) { + Remove-Item $TARGET -Recurse -Force + } + New-Item -ItemType Directory -Path $TARGET | Out-Null + + Write-Host "[Info] Building dotnet-core-CSharp-extension nativecsharpextension dll..." + + # Set build output directory + $BUILD_OUTPUT = Join-Path $DOTNET_EXTENSION_WORKING_DIR $BUILD_CONFIGURATION + if (Test-Path $BUILD_OUTPUT) { + Remove-Item $BUILD_OUTPUT -Recurse -Force + } + New-Item -ItemType Directory -Path $BUILD_OUTPUT | Out-Null + Push-Location $BUILD_OUTPUT + + # Set source and include paths + $DOTNET_NATIVE_SRC = Join-Path $DOTNET_EXTENSION_HOME "src/native" + $DOTNET_NATIVE_INCLUDE = Join-Path $DOTNET_EXTENSION_HOME "include" + $EXTENSION_HOST_INCLUDE = Join-Path $ENL_ROOT "extension-host/include" + $DOTNET_NATIVE_LIB = Join-Path $DOTNET_EXTENSION_HOME "lib" + + # Build native code + $ccArgs = @( + "-shared", + "-fPIC", + "-o", "libnativecsharpextension.so", + "-I", $DOTNET_NATIVE_INCLUDE, + "-I", $EXTENSION_HOST_INCLUDE, + "-D", "LINUX" + ) + $ccArgs += Get-ChildItem -Path $DOTNET_NATIVE_SRC -Filter "*.cpp" | ForEach-Object { $_.FullName } + if ($BUILD_CONFIGURATION -eq "debug") { + $ccArgs += "-D", "DEBUG" + } + + if ($null -ne $env:CXX) { + $cxx = $env:CXX + } else { + $cxx = "c++" + } + + $proc = Start-Process -FilePath $cxx -ArgumentList $ccArgs -NoNewWindow -Wait -PassThru + if ($proc.ExitCode -ne 0) { + Write-Host "Error: Failed to build nativecsharpextension for configuration=$BUILD_CONFIGURATION" + exit $proc.ExitCode + } + + Write-Host "[Info] Copying dependent libraries..." + Copy-Item (Join-Path $DOTNET_NATIVE_LIB "libhostfxr.so") $BUILD_OUTPUT -Force + + # Build managed code + Write-Host "[Info] Building Microsoft.SqlServer.CSharpExtension dll..." + $DOTNET_MANAGED_SRC = Join-Path $DOTNET_EXTENSION_HOME "src/managed" + $dotnetProc = Start-Process -FilePath "dotnet" -ArgumentList @( + "build", + (Join-Path $DOTNET_MANAGED_SRC "Microsoft.SqlServer.CSharpExtension.csproj"), + "-m", + "-c", $BUILD_CONFIGURATION, + "-o", $BUILD_OUTPUT, + "--no-dependencies" + ) -NoNewWindow -Wait -PassThru + + if ($dotnetProc.ExitCode -ne 0) { + Write-Host "Error: Failed to build for Microsoft.SqlServer.CSharpExtension.dll for configuration=$BUILD_CONFIGURATION" + exit $dotnetProc.ExitCode + } + + Write-Host "Success: Built dotnet-core-CSharp-extension for $BUILD_CONFIGURATION configuration." + + $i++ + if ($i -ge $args.Count) { + break + } +} + +exit 0 From 1b8b12e67aeb7d42debb6e17a697e39305e3062a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Mon, 15 Sep 2025 15:32:44 +0200 Subject: [PATCH 04/12] Add archive script for Linux. SQL Server on Linux expects a .tar.gz file instead of a .zip when using CREATE EXTERNAL LANGUAGE. --- .../build-dotnet-core-CSharp-extension.ps1 | 6 +- ...reate-dotnet-core-CSharp-extension-zip.ps1 | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100755 language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 diff --git a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 index 4f2c09e..092ecd1 100755 --- a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 +++ b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 @@ -14,11 +14,12 @@ New-Item -ItemType Directory -Path $DOTNET_EXTENSION_WORKING_DIR | Out-Null $i = 0 # Process each build configuration -while($true) { +while ($true) { $BUILD_CONFIGURATION = "" if ($i -lt $args.Count) { $BUILD_CONFIGURATION = $args[$i] } + $BUILD_CONFIGURATION = $BUILD_CONFIGURATION.ToLower() # Default to release if not debug if ($BUILD_CONFIGURATION -ne "debug") { $BUILD_CONFIGURATION = "release" @@ -65,7 +66,8 @@ while($true) { if ($null -ne $env:CXX) { $cxx = $env:CXX - } else { + } + else { $cxx = "c++" } diff --git a/language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 b/language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 new file mode 100755 index 0000000..47c3338 --- /dev/null +++ b/language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 @@ -0,0 +1,65 @@ +#!/usr/bin/env pwsh + +$ENL_ROOT = Join-Path $PSScriptRoot "../../../.." +$DOTNET_EXTENSION_WORKING_DIR = Join-Path -Path $ENL_ROOT -ChildPath "build-output/dotnet-core-CSharp-extension/linux" + +function CheckError { + param( + [int]$errorLevel, + [string]$errorMessage + ) + if ($errorLevel -ne 0) { + Write-Error $errorMessage + exit $errorLevel + } +} + + +$i = 0 + +# Process each build configuration +while ($true) { + $BUILD_CONFIGURATION = "" + if ($i -lt $args.Count) { + $BUILD_CONFIGURATION = $args[$i] + } + $BUILD_CONFIGURATION = $BUILD_CONFIGURATION.ToLower() + # Default to release if not debug + if ($BUILD_CONFIGURATION -ne "debug") { + $BUILD_CONFIGURATION = "release" + } + + $BUILD_OUTPUT = Join-Path -Path $DOTNET_EXTENSION_WORKING_DIR -ChildPath $BUILD_CONFIGURATION + New-Item -ItemType Directory -Force -Path "$BUILD_OUTPUT/packages" | Out-Null + + # Delete the ref folder so that the zip can be loaded by the SPEES + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$BUILD_OUTPUT/ref" + + # Define files to compress, conditionally including .pdb files if BUILD_CONFIGURATION is "debug" + $FILES_TO_COMPRESS = @( + "Microsoft.SqlServer.CSharpExtension.runtimeconfig.json", + "Microsoft.SqlServer.CSharpExtension.deps.json" + ) + $FILES_TO_COMPRESS += Get-ChildItem -Path $BUILD_OUTPUT -Filter "*.dll" | ForEach-Object { $_.Name } + $FILES_TO_COMPRESS += Get-ChildItem -Path $BUILD_OUTPUT -Filter "*.so" | ForEach-Object { $_.Name } + if ($BUILD_CONFIGURATION -ieq "debug") { + $FILES_TO_COMPRESS += Get-ChildItem -Path $BUILD_OUTPUT -Filter "*.pdb" | ForEach-Object { $_.Name } + } + + # Package the signed binaries. + try { + Push-Location $BUILD_OUTPUT + & tar -czvf "$BUILD_OUTPUT/packages/dotnet-core-CSharp-lang-extension.tar.gz" $FILES_TO_COMPRESS + CheckError $LASTEXITCODE "Error: Failed to create zip for dotnet-core-CSharp-extension for configuration=$BUILD_CONFIGURATION" + Pop-Location + Write-Host "Success: Compressed dotnet-core-CSharp-extension for $BUILD_CONFIGURATION configuration." + } + catch { + CheckError 1 "Error: Failed to create zip for dotnet-core-CSharp-extension for configuration=$BUILD_CONFIGURATION" + } + + $i++ + if ($i -ge $args.Count) { + break + } +} From e53d68b603ae24631274326b109173dcba7d99b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Tue, 16 Sep 2025 09:16:10 +0200 Subject: [PATCH 05/12] Bump .NET from unsupported 6.0 to 8.0. --- .../dotnet-core-CSharp/sample/regex/pkg/RegexSample.csproj | 2 +- .../src/managed/Microsoft.SqlServer.CSharpExtension.csproj | 2 +- .../src/managed/Microsoft.SqlServer.CSharpExtensionTest.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/sample/regex/pkg/RegexSample.csproj b/language-extensions/dotnet-core-CSharp/sample/regex/pkg/RegexSample.csproj index 07d7f1f..a0a78ac 100644 --- a/language-extensions/dotnet-core-CSharp/sample/regex/pkg/RegexSample.csproj +++ b/language-extensions/dotnet-core-CSharp/sample/regex/pkg/RegexSample.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 true true diff --git a/language-extensions/dotnet-core-CSharp/src/managed/Microsoft.SqlServer.CSharpExtension.csproj b/language-extensions/dotnet-core-CSharp/src/managed/Microsoft.SqlServer.CSharpExtension.csproj index a7f4a8b..375c866 100644 --- a/language-extensions/dotnet-core-CSharp/src/managed/Microsoft.SqlServer.CSharpExtension.csproj +++ b/language-extensions/dotnet-core-CSharp/src/managed/Microsoft.SqlServer.CSharpExtension.csproj @@ -1,6 +1,6 @@ - net6.0 + net8.0 true true diff --git a/language-extensions/dotnet-core-CSharp/test/src/managed/Microsoft.SqlServer.CSharpExtensionTest.csproj b/language-extensions/dotnet-core-CSharp/test/src/managed/Microsoft.SqlServer.CSharpExtensionTest.csproj index 758bc79..01b7d11 100644 --- a/language-extensions/dotnet-core-CSharp/test/src/managed/Microsoft.SqlServer.CSharpExtensionTest.csproj +++ b/language-extensions/dotnet-core-CSharp/test/src/managed/Microsoft.SqlServer.CSharpExtensionTest.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 true From 72dccc5daf35dd3b487ba673c2e183e3163049bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Wed, 17 Sep 2025 08:40:12 +0200 Subject: [PATCH 06/12] Add static nethost library from .NET 8.0 Linux runtime. We will use the nethost to locate the system's installed hostfxr, as using a local libhostfxr.so breaks the .NET runtime lookup. nethost contains the logic needed to find the .NET root based on the DOTNET_ROOT environment variable or the install_location configuration file, which we will require for .NET runtime lookup on diverging Linux distributions (e.g. RHEL and Debian packages not installing .NET in the same base directories). --- .../dotnet-core-CSharp/include/nethost.h | 99 ++++++++++++++++++ .../dotnet-core-CSharp/lib/libnethost.a | Bin 0 -> 178378 bytes 2 files changed, 99 insertions(+) create mode 100644 language-extensions/dotnet-core-CSharp/include/nethost.h create mode 100644 language-extensions/dotnet-core-CSharp/lib/libnethost.a diff --git a/language-extensions/dotnet-core-CSharp/include/nethost.h b/language-extensions/dotnet-core-CSharp/include/nethost.h new file mode 100644 index 0000000..eaca175 --- /dev/null +++ b/language-extensions/dotnet-core-CSharp/include/nethost.h @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __NETHOST_H__ +#define __NETHOST_H__ + +#include + +#ifdef _WIN32 + #ifdef NETHOST_EXPORT + #define NETHOST_API __declspec(dllexport) + #else + // Consuming the nethost as a static library + // Shouldn't export attempt to dllimport. + #ifdef NETHOST_USE_AS_STATIC + #define NETHOST_API + #else + #define NETHOST_API __declspec(dllimport) + #endif + #endif + + #define NETHOST_CALLTYPE __stdcall + #ifdef _WCHAR_T_DEFINED + typedef wchar_t char_t; + #else + typedef unsigned short char_t; + #endif +#else + #ifdef NETHOST_EXPORT + #define NETHOST_API __attribute__((__visibility__("default"))) + #else + #define NETHOST_API + #endif + + #define NETHOST_CALLTYPE + typedef char char_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Parameters for get_hostfxr_path +// +// Fields: +// size +// Size of the struct. This is used for versioning. +// +// assembly_path +// Path to the component's assembly. +// If specified, hostfxr is located as if the assembly_path is the apphost +// +// dotnet_root +// Path to directory containing the dotnet executable. +// If specified, hostfxr is located as if an application is started using +// 'dotnet app.dll', which means it will be searched for under the dotnet_root +// path and the assembly_path is ignored. +// +struct get_hostfxr_parameters { + size_t size; + const char_t *assembly_path; + const char_t *dotnet_root; +}; + +// +// Get the path to the hostfxr library +// +// Parameters: +// buffer +// Buffer that will be populated with the hostfxr path, including a null terminator. +// +// buffer_size +// [in] Size of buffer in char_t units. +// [out] Size of buffer used in char_t units. If the input value is too small +// or buffer is nullptr, this is populated with the minimum required size +// in char_t units for a buffer to hold the hostfxr path +// +// get_hostfxr_parameters +// Optional. Parameters that modify the behaviour for locating the hostfxr library. +// If nullptr, hostfxr is located using the environment variable or global registration +// +// Return value: +// 0 on success, otherwise failure +// 0x80008098 - buffer is too small (HostApiBufferTooSmall) +// +// Remarks: +// The full search for the hostfxr library is done on every call. To minimize the need +// to call this function multiple times, pass a large buffer (e.g. PATH_MAX). +// +NETHOST_API int NETHOST_CALLTYPE get_hostfxr_path( + char_t * buffer, + size_t * buffer_size, + const struct get_hostfxr_parameters *parameters); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __NETHOST_H__ diff --git a/language-extensions/dotnet-core-CSharp/lib/libnethost.a b/language-extensions/dotnet-core-CSharp/lib/libnethost.a new file mode 100644 index 0000000000000000000000000000000000000000..9b333a48619ed1002570e148f9a916d5ab2c9dd6 GIT binary patch literal 178378 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 literal 0 HcmV?d00001 From 97535d3518226fc6d6624fb3742d59a1d90ac8df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Wed, 17 Sep 2025 09:00:17 +0200 Subject: [PATCH 07/12] Use nethost to lookup hostfxr on Linux. --- .../build/linux/build-dotnet-core-CSharp-extension.ps1 | 10 ++++------ .../src/native/DotnetEnvironment.cpp | 8 +++++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 index 092ecd1..2bafbee 100755 --- a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 +++ b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 @@ -55,11 +55,12 @@ while ($true) { "-shared", "-fPIC", "-o", "libnativecsharpextension.so", - "-I", $DOTNET_NATIVE_INCLUDE, - "-I", $EXTENSION_HOST_INCLUDE, - "-D", "LINUX" + "-I$DOTNET_NATIVE_INCLUDE", + "-I$EXTENSION_HOST_INCLUDE", + "-DLINUX" ) $ccArgs += Get-ChildItem -Path $DOTNET_NATIVE_SRC -Filter "*.cpp" | ForEach-Object { $_.FullName } + $ccArgs += Join-Path -Path $DOTNET_NATIVE_LIB -ChildPath "libnethost.a" if ($BUILD_CONFIGURATION -eq "debug") { $ccArgs += "-D", "DEBUG" } @@ -77,9 +78,6 @@ while ($true) { exit $proc.ExitCode } - Write-Host "[Info] Copying dependent libraries..." - Copy-Item (Join-Path $DOTNET_NATIVE_LIB "libhostfxr.so") $BUILD_OUTPUT -Force - # Build managed code Write-Host "[Info] Building Microsoft.SqlServer.CSharpExtension dll..." $DOTNET_MANAGED_SRC = Join-Path $DOTNET_EXTENSION_HOME "src/managed" diff --git a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp index 22e865e..c8fe12d 100644 --- a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp +++ b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #if defined(__WIN32) || defined(WINDOWS) #define STR(s) L ## s @@ -164,7 +165,12 @@ bool DotnetEnvironment::load_hostfxr() #if defined(_WIN32) || defined(WINDOWS) string_t hostfxr_location = m_root_path + STR("\\hostfxr.dll"); #else - string_t hostfxr_location = STR("libhostfxr.so"); + char buffer[4096]; + size_t buffer_size = sizeof(buffer); + if (get_hostfxr_path(buffer, &buffer_size, nullptr) != 0) { + return false; + } + string_t hostfxr_location(buffer); #endif void *lib = load_library(hostfxr_location.c_str()); m_init_fptr = (hostfxr_initialize_for_runtime_config_fn)get_export(lib, "hostfxr_initialize_for_runtime_config"); From db1ec51f3f5b3f45fb0629102cfdbe5bcf660016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Wed, 17 Sep 2025 09:07:16 +0200 Subject: [PATCH 08/12] Add debug compiler flag when building in debug. --- .../build/linux/build-dotnet-core-CSharp-extension.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 index 2bafbee..228df9b 100755 --- a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 +++ b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 @@ -62,7 +62,7 @@ while ($true) { $ccArgs += Get-ChildItem -Path $DOTNET_NATIVE_SRC -Filter "*.cpp" | ForEach-Object { $_.FullName } $ccArgs += Join-Path -Path $DOTNET_NATIVE_LIB -ChildPath "libnethost.a" if ($BUILD_CONFIGURATION -eq "debug") { - $ccArgs += "-D", "DEBUG" + $ccArgs += "-D", "DEBUG", "-g" } if ($null -ne $env:CXX) { From 493a29ba9b3ef17893612ef513a68c5b5d715a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Wed, 17 Sep 2025 09:50:31 +0200 Subject: [PATCH 09/12] Fix Linux/Windows portability issues. --- .../dotnet-core-CSharp/include/DotnetEnvironment.h | 10 ++++++++-- .../src/native/DotnetEnvironment.cpp | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h index 93edcab..f58b30e 100644 --- a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h +++ b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h @@ -24,9 +24,11 @@ #if defined(__WIN32) || defined(WINDOWS) #define STR(s) L ## s #define CH(c) L ## c +#define PATH_SEPARATOR CH('\\') #else #define STR(s) s #define CH(c) c +#define PATH_SEPARATOR CH('/') #endif using namespace std; @@ -57,10 +59,14 @@ class DotnetEnvironment // Load managed assembly and get function pointer to a managed method // const string_t ManagedExtensionName = STR("Microsoft.SqlServer.CSharpExtension"); - const string_t ManagedExtensionPath = m_root_path + STR("\\") + ManagedExtensionName + STR(".dll"); + const string_t ManagedExtensionPath = m_root_path + PATH_SEPARATOR + ManagedExtensionName + STR(".dll"); const string_t ManagedExtensionType = ManagedExtensionName + STR(".CSharpExtension, ") + ManagedExtensionName; +#if defined(_WIN32) || defined(WINDOWS) const string_t ManagedExtensionMethod = to_utf16_str(method_name); - const string_t DelegateTypeName = ManagedExtensionName + STR(".CSharpExtension+") + to_utf16_str(method_name) + STR("Delegate, ") + ManagedExtensionName; +#else + const string_t ManagedExtensionMethod = method_name; +#endif + const string_t DelegateTypeName = ManagedExtensionName + STR(".CSharpExtension+") + ManagedExtensionMethod + STR("Delegate, ") + ManagedExtensionName; int rc = m_load_assembly_and_get_function_pointer( ManagedExtensionPath.c_str(), ManagedExtensionType.c_str(), diff --git a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp index c8fe12d..c9f4c50 100644 --- a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp +++ b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp @@ -74,7 +74,7 @@ short DotnetEnvironment::Init() // STEP 2: Initialize and start the .NET Core runtime // - const string_t config_path = m_root_path + STR("\\Microsoft.SqlServer.CSharpExtension.runtimeconfig.json"); + const string_t config_path = m_root_path + PATH_SEPARATOR + STR("Microsoft.SqlServer.CSharpExtension.runtimeconfig.json"); hostfxr_handle cxt = get_dotnet(config_path.c_str()); m_load_assembly_and_get_function_pointer = get_dotnet_load_assembly(cxt); From fa0673837c1d255d04239b91925a862c7311b99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Wed, 17 Sep 2025 18:11:29 +0200 Subject: [PATCH 10/12] Add documentation about C# on Linux. --- .../dotnet-core-CSharp/README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/README.md b/language-extensions/dotnet-core-CSharp/README.md index c5fbeb2..0c49b13 100644 --- a/language-extensions/dotnet-core-CSharp/README.md +++ b/language-extensions/dotnet-core-CSharp/README.md @@ -5,11 +5,11 @@ Language Extensions is a feature of SQL Server used for executing external code. For more information about SQL Server Language Extensions, refer to this [documentation](https://docs.microsoft.com/en-us/sql/language-extensions/language-extensions-overview?view=sql-server-ver15). -The dotnet-core-CSharp-extension version in this repository is compatible with SQL Server 2019 CU3 onwards. It integrates .NET core in SQL Server and works with .NET 6.0 in **Windows only**. +The dotnet-core-CSharp-extension version in this repository is compatible with SQL Server 2019 CU3 onwards. It integrates .NET Core in SQL Server and works with .NET 8.0 and up on Windows and Linux. Currently, the extension supports the following data types: SQL_C_SLONG, SQL_C_ULONG, SQL_C_SSHORT, SQL_C_USHORT, SQL_C_SBIGINT, SQL_C_UBIGINT, SQL_C_STINYINT, SQL_C_UTINYINT, SQL_C_BIT, SQL_C_FLOAT, SQL_C_DOUBLE, SQL_C_CHAR. It supports the following SQL data types: int, bigint, smallint, tinyint, real, float, bit, varchar(n). -To use this dotnet-core-CSharp-lang-extension.zip package, follow [this tutorial](./sample/regex/README.md). For any fixes or enhancements, you are welcome to modify, rebuild and use the binaries using the following instructions. +To use this `dotnet-core-CSharp-lang-extension.zip` (Windows) or `dotnet-core-CSharp-lang-extension.tar.gz` (Linux) package, follow [this tutorial](./sample/regex/README.md). For any fixes or enhancements, you are welcome to modify, rebuild and use the binaries using the following instructions. ## Building @@ -24,15 +24,24 @@ To use this dotnet-core-CSharp-lang-extension.zip package, follow [this tutorial - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\windows\release\nativecsharpextension.dll \ - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\windows\release\hostfxr.dll \ - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\windows\release\Microsoft.SqlServer.CSharpExtension.dll \ - - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\windows\release\Microsoft.SqlServer.CSharpExtension.runtimeconfig.json\ + - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\windows\release\Microsoft.SqlServer.CSharpExtension.runtimeconfig.json \ - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\windows\release\Microsoft.SqlServer.CSharpExtension.deps.json 5. Run [create-dotnet-core-CSharp-extension-zip.cmd](./build/windows/create-dotnet-core-CSharp-extension-zip.cmd) which will generate: \ - - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\target\debug\dotnet-core-CSharp-lang-extension.zip + - PATH\TO\ENLISTMENT\build-output\dotnet-core-CSharp-extension\windows\release\packages\dotnet-core-CSharp-lang-extension.zip This zip can be used in CREATE EXTERNAL LANGUAGE, as detailed in the tutorial in the Usage section below. ### Linux -Not Supported. + +1. Run [build-dotnet-core-CSharp-extension.ps1](./build/windows/build-dotnet-core-CSharp-extension.cmd) which will generate: \ + - PATH/TO/ENLISTMENT/build-output/dotnet-core-CSharp-extension/linux/release/libnativecsharpextension.so \ + - PATH/TO/ENLISTMENT/build-output/dotnet-core-CSharp-extension/linux/release/Microsoft.SqlServer.CSharpExtension.dll \ + - PATH/TO/ENLISTMENT/build-output/dotnet-core-CSharp-extension/linux/release/Microsoft.SqlServer.CSharpExtension.runtimeconfig.json \ + - PATH/TO/ENLISTMENT/build-output/dotnet-core-CSharp-extension/linux/release/Microsoft.SqlServer.CSharpExtension.deps.json + +2. Run [create-dotnet-core-CSharp-extension-zip.ps1](./build/windows/create-dotnet-core-CSharp-extension-zip.cmd) which will generate: \ + - PATH/TO/ENLISTMENT/build-output/dotnet-core-CSharp-extension/linux/release/packages/dotnet-core-CSharp-lang-extension.tar.gz + This tarball can be used in CREATE EXTERNAL LANGUAGE, as detailed in the tutorial in the Usage section below. ## Testing (Optional) From ba5507dca62cdda9f66c719a80c7dbeb3e2fb3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Fri, 10 Oct 2025 10:31:58 +0200 Subject: [PATCH 11/12] Fix _WIN32 preprocessor symbol typo. --- .../dotnet-core-CSharp/include/DotnetEnvironment.h | 4 ++-- .../dotnet-core-CSharp/include/nativecsharpextension.h | 2 +- .../dotnet-core-CSharp/src/native/DotnetEnvironment.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h index f58b30e..e12856c 100644 --- a/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h +++ b/language-extensions/dotnet-core-CSharp/include/DotnetEnvironment.h @@ -10,7 +10,7 @@ //********************************************************************* #pragma once -#if defined(__WIN32) || defined(WINDOWS) +#if defined(_WIN32) || defined(WINDOWS) #include "Windows.h" #else #define E_FAIL -1 @@ -21,7 +21,7 @@ #include #include -#if defined(__WIN32) || defined(WINDOWS) +#if defined(_WIN32) || defined(WINDOWS) #define STR(s) L ## s #define CH(c) L ## c #define PATH_SEPARATOR CH('\\') diff --git a/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h b/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h index ad2b0c7..3a8fad5 100644 --- a/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h +++ b/language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h @@ -20,7 +20,7 @@ #include #include -#if defined(__WIN32) || defined(WINDOWS) +#if defined(_WIN32) || defined(WINDOWS) #include #endif diff --git a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp index c9f4c50..2b3f47d 100644 --- a/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp +++ b/language-extensions/dotnet-core-CSharp/src/native/DotnetEnvironment.cpp @@ -26,7 +26,7 @@ #include #include -#if defined(__WIN32) || defined(WINDOWS) +#if defined(_WIN32) || defined(WINDOWS) #define STR(s) L ## s #define CH(c) L ## c #else From 04be02eb8016231ff045d15a94caa48099e8e053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindstr=C3=B6m?= Date: Fri, 10 Oct 2025 10:48:33 +0200 Subject: [PATCH 12/12] Cleanup argument loop in Linux scripts. --- .../build-dotnet-core-CSharp-extension.ps1 | 19 ++++++++---------- ...reate-dotnet-core-CSharp-extension-zip.ps1 | 20 ++++++++----------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 index 228df9b..7ec3394 100755 --- a/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 +++ b/language-extensions/dotnet-core-CSharp/build/linux/build-dotnet-core-CSharp-extension.ps1 @@ -11,14 +11,16 @@ if (Test-Path $DOTNET_EXTENSION_WORKING_DIR) { } New-Item -ItemType Directory -Path $DOTNET_EXTENSION_WORKING_DIR | Out-Null -$i = 0 +if ($args.Count -eq 0) { + # Default to release + $actualArgs = @("release") +} +else { + $actualArgs = $args +} # Process each build configuration -while ($true) { - $BUILD_CONFIGURATION = "" - if ($i -lt $args.Count) { - $BUILD_CONFIGURATION = $args[$i] - } +foreach ($BUILD_CONFIGURATION in $actualArgs) { $BUILD_CONFIGURATION = $BUILD_CONFIGURATION.ToLower() # Default to release if not debug if ($BUILD_CONFIGURATION -ne "debug") { @@ -96,11 +98,6 @@ while ($true) { } Write-Host "Success: Built dotnet-core-CSharp-extension for $BUILD_CONFIGURATION configuration." - - $i++ - if ($i -ge $args.Count) { - break - } } exit 0 diff --git a/language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 b/language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 index 47c3338..06b20dd 100755 --- a/language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 +++ b/language-extensions/dotnet-core-CSharp/build/linux/create-dotnet-core-CSharp-extension-zip.ps1 @@ -14,15 +14,16 @@ function CheckError { } } - -$i = 0 +if ($args.Count -eq 0) { + # Default to release + $actualArgs = @("release") +} +else { + $actualArgs = $args +} # Process each build configuration -while ($true) { - $BUILD_CONFIGURATION = "" - if ($i -lt $args.Count) { - $BUILD_CONFIGURATION = $args[$i] - } +foreach ($BUILD_CONFIGURATION in $actualArgs) { $BUILD_CONFIGURATION = $BUILD_CONFIGURATION.ToLower() # Default to release if not debug if ($BUILD_CONFIGURATION -ne "debug") { @@ -57,9 +58,4 @@ while ($true) { catch { CheckError 1 "Error: Failed to create zip for dotnet-core-CSharp-extension for configuration=$BUILD_CONFIGURATION" } - - $i++ - if ($i -ge $args.Count) { - break - } }