-
Notifications
You must be signed in to change notification settings - Fork 47
Add Linux support to .NET language extension #64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
72625a9
d52769f
02420c2
1b8b12e
e53d68b
72dccc5
97535d3
db1ec51
493a29b
fa06738
ba5507d
04be02e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| #!/usr/bin/env pwsh | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we using powershell script for linux instead of bash script?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As written in the description, PowerShell was chosen as a scripting language to serve as a potential base for a cross-platform script. If this is not desired, I can rewrite it in bash.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean this script can be used for both windows/linux now or we should have a follow-up work item for this? |
||
|
|
||
| # 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 | ||
|
|
||
| if ($args.Count -eq 0) { | ||
| # Default to release | ||
| $actualArgs = @("release") | ||
| } | ||
| else { | ||
| $actualArgs = $args | ||
| } | ||
|
|
||
| # Process each build configuration | ||
| foreach ($BUILD_CONFIGURATION in $actualArgs) { | ||
| $BUILD_CONFIGURATION = $BUILD_CONFIGURATION.ToLower() | ||
| # 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", | ||
| "-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", "-g" | ||
| } | ||
|
|
||
| if ($null -ne $env:CXX) { | ||
| $cxx = $env:CXX | ||
| } | ||
| else { | ||
| $cxx = "c++" | ||
SicongLiu2000 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| $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 | ||
| } | ||
|
|
||
| # 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." | ||
| } | ||
|
|
||
| exit 0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| #!/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 | ||
| } | ||
| } | ||
|
|
||
| if ($args.Count -eq 0) { | ||
| # Default to release | ||
| $actualArgs = @("release") | ||
| } | ||
| else { | ||
| $actualArgs = $args | ||
| } | ||
|
|
||
| # Process each build configuration | ||
| foreach ($BUILD_CONFIGURATION in $actualArgs) { | ||
| $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" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,13 +10,26 @@ | |
| //********************************************************************* | ||
| #pragma once | ||
|
|
||
| #if defined(_WIN32) || defined(WINDOWS) | ||
| #include "Windows.h" | ||
| #else | ||
| #define E_FAIL -1 | ||
| #define S_OK 0 | ||
| #endif | ||
|
|
||
| #include <string> | ||
| #include <coreclr_delegates.h> | ||
| #include <hostfxr.h> | ||
|
|
||
| #if defined(_WIN32) || defined(WINDOWS) | ||
| #define STR(s) L ## s | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The two adjacent |
||
| #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; | ||
| using string_t = std::basic_string<char_t>; | ||
|
|
@@ -46,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"); | ||
SicongLiu2000 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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(), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <stddef.h> | ||
|
|
||
| #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__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The link text says
.cmdbut the actual file is a.ps1script, and the path points to./build/windows/rather than./build/linux/. Should be:[build-dotnet-core-CSharp-extension.ps1](./build/linux/build-dotnet-core-CSharp-extension.ps1)