Skip to content

Commit

Permalink
Merge pull request #229 from agracio/clr-runtime
Browse files Browse the repository at this point in the history
Merging from clr-runtime branch
  • Loading branch information
agracio authored Oct 25, 2024
2 parents 7b178f1 + 62d9638 commit 3c4966c
Show file tree
Hide file tree
Showing 38 changed files with 559 additions and 32 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ on:
- '.circleci'
- '.circleci/*'
- 'README.md'
- '*.sln'
- '*.vcxproj'
push:
branches-ignore:
- 'circleci'
Expand Down Expand Up @@ -57,6 +59,8 @@ on:
- '.circleci'
- '.circleci/*'
- 'README.md'
- '*.sln'
- '*.vcxproj'


env:
Expand Down
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,5 @@ mochawesome.json
.circleci
*.sln
xunit*.*
getVersion*.js
getVersion*.js
*.vcxproj
25 changes: 25 additions & 0 deletions EdgeJsCpp.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2015
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "edge_coreclr", "src/edge_coreclr.vcxproj", "{C4F6A0C1-4D35-3CDF-02A8-A0A36667597E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "edge_nativeclr", "src/edge_nativeclr.vcxproj", "{876FD028-79E4-32A3-43C2-16DA11AD880C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{876FD028-79E4-32A3-43C2-16DA11AD880C}.Debug|x64.ActiveCfg = Debug|x64
{876FD028-79E4-32A3-43C2-16DA11AD880C}.Debug|x64.Build.0 = Debug|x64
{876FD028-79E4-32A3-43C2-16DA11AD880C}.Release|x64.ActiveCfg = Release|x64
{876FD028-79E4-32A3-43C2-16DA11AD880C}.Release|x64.Build.0 = Release|x64
{C4F6A0C1-4D35-3CDF-02A8-A0A36667597E}.Debug|x64.ActiveCfg = Debug|x64
{C4F6A0C1-4D35-3CDF-02A8-A0A36667597E}.Debug|x64.Build.0 = Debug|x64
{C4F6A0C1-4D35-3CDF-02A8-A0A36667597E}.Release|x64.ActiveCfg = Release|x64
{C4F6A0C1-4D35-3CDF-02A8-A0A36667597E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,9 @@ set EDGE_APP_ROOT=c:\DotNet\MyProject\bin\Release\netstandard1.6
node app.js
```

Edge.js also supports running published .NET Core applications on servers that do not have the .NET Core SDK and CLI installed, which is a common scenario in production environments. To do so, the `.csproj` for your application should meet the following requirements:
When calling a compiled assembly, Edge.js supports running with only the .NET runtime installed (and not the SDK or CLI). In this case a `appname.runtimeconfig.json` has to be created when building the project an present in your `EDGE_APP_ROOT` directory. `<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>`should be present under `<PropertyGroup>` in your `.csproj`file to create this file.

Edge.js also supports running published .NET Core applications on servers that do not have the .NET Core SDK and CLI or .NET runtime installed, which is a common scenario in production environments. To do so, the `.csproj` for your application should meet the following requirements:

1. It should target the `netcoreapp2.x` or `netstandard2.0` framework moniker.
2. It should reference `Microsoft.NETCore.DotNetHost` and `Microsoft.NETCore.DotNetHostPolicy`. This is required so that the publish process can provide all the native libraries required to create a completely standalone version of your application.
Expand Down
4 changes: 4 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ environment:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
matrix:
# node.js
- nodejs: "23"
- nodejs: "22"
- nodejs: "20"
- nodejs: "18"
Expand Down Expand Up @@ -66,6 +67,9 @@ skip_commits:
- 'appveyor_double.yml'
- '.circleci'
- '.circleci/*'
- '*.sln'
- '*.vcxproj'


build: off

Expand Down
Binary file modified lib/native/win32/arm64/20/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/arm64/20/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/arm64/22/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/arm64/22/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/arm64/23/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/arm64/23/edge_nativeclr.node
Binary file not shown.
2 changes: 1 addition & 1 deletion lib/native/win32/arm64/23/node.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23.0.0
23.1.0
Binary file modified lib/native/win32/ia32/16/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/ia32/16/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/ia32/18/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/ia32/18/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/ia32/20/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/ia32/20/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/ia32/22/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/ia32/22/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/16/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/16/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/18/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/18/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/20/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/20/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/22/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/22/edge_nativeclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/23/edge_coreclr.node
Binary file not shown.
Binary file modified lib/native/win32/x64/23/edge_nativeclr.node
Binary file not shown.
2 changes: 1 addition & 1 deletion lib/native/win32/x64/23/node.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23.0.0
23.1.0
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"url": "http://tomasz.janczuk.org",
"twitter": "tjanczuk"
},
"version": "23.0.0",
"version": "23.1.0",
"description": "Edge.js: run .NET and Node.js in-process on Windows, Mac OS, and Linux",
"tags": [
"owin",
Expand Down
65 changes: 46 additions & 19 deletions src/CoreCLREmbedding/coreclrembedding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ InitializeFunction initialize;
"EdgeJs",\
"CoreCLREmbedding",\
functionName,\
(void**) functionPointer);\
(void**) (functionPointer));\
pal::clr_palstring(functionName, &functionNameString);\
\
if (FAILED(result))\
Expand Down Expand Up @@ -209,7 +209,7 @@ HRESULT CoreClrEmbedding::Initialize(BOOL debugMode)
pal::string_t edgeDebug;
pal::getenv(_X("EDGE_DEBUG"), &edgeDebug);

if (edgeDebug.length() > 0)
if (!edgeDebug.empty())
{
trace::enable();
}
Expand Down Expand Up @@ -265,9 +265,9 @@ HRESULT CoreClrEmbedding::Initialize(BOOL debugMode)
pal::string_t edgeBootstrapDir;
pal::getenv(_X("EDGE_BOOTSTRAP_DIR"), &edgeBootstrapDir);

if (edgeAppDir.length() == 0)
if (edgeAppDir.empty())
{
if (edgeBootstrapDir.length() != 0)
if (!edgeBootstrapDir.empty())
{
trace::info(_X("CoreClrEmbedding::Initialize - No EDGE_APP_ROOT environment variable present, using the Edge bootstrapper directory at %s"), edgeBootstrapDir.c_str());
edgeAppDir = edgeBootstrapDir;
Expand Down Expand Up @@ -321,7 +321,7 @@ HRESULT CoreClrEmbedding::Initialize(BOOL debugMode)
size_t previousIndex = 0;
size_t currentIndex = pathEnvironmentVariable.find(PATH_SEPARATOR);

while (dotnetExecutablePath.length() == 0 && previousIndex != std::string::npos)
while (dotnetExecutablePath.empty() && previousIndex != std::string::npos)
{
if (currentIndex != std::string::npos)
{
Expand Down Expand Up @@ -371,16 +371,43 @@ HRESULT CoreClrEmbedding::Initialize(BOOL debugMode)
if (mode != host_mode_t::standalone)
{
trace::verbose(_X("CoreClrEmbedding::Initialize - host mode: muxer"));

std::vector<pal::string_t> appConfigFiles;
pal::readdir(edgeAppDir, _X("*.runtimeconfig.json"), &appConfigFiles);
pal::string_t runtimeconfigfile;

pal::string_t sdkDirectory;

fx_muxer_t::resolve_sdk_dotnet_path(dotnetDirectory, &sdkDirectory);

pal::string_t dotnetAssemblyPath(sdkDirectory);
append_path(&dotnetAssemblyPath, _X("dotnet.dll"));
if (!sdkDirectory.empty()) // Default case: SDK is installed and found - using dotnet.runtimeconfig.json from SDK folder
{
runtimeconfigfile = pal::string_t(sdkDirectory);
append_path(&runtimeconfigfile, _X("dotnet.dll"));
get_runtime_config_paths_from_app(runtimeconfigfile, &configFile, &devConfigFile);
}
else if (appConfigFiles.size() == 1) // Fallback: No SDK directory found (probably only .NET runtime installed), trying to use [appname].runtimeconfig.json instead
{
runtimeconfigfile = pal::string_t(edgeAppDir);
append_path(&runtimeconfigfile, appConfigFiles[0].c_str());

get_runtime_config_paths_from_app(dotnetAssemblyPath, &configFile, &devConfigFile);
}
trace::info(_X("CoreClrEmbedding::Initialize - No SDK directory found - Exactly one (%s) app runtimeconfig file found in the Edge app directory, using that"), runtimeconfigfile.c_str());
configFile = pal::string_t(runtimeconfigfile);
}
else if (appConfigFiles.size() > 1) // Throw error: No SDK found but more than one runtimeconfig.json found in app folder - Which one is correct?
{
std::vector<char> edgeAppDirCstr;
pal::pal_clrstring(edgeAppDir, &edgeAppDirCstr);

throwV8Exception("CoreClrEmbedding::Initialize - Multiple app runtimeconfig files (*.runtimeconfig.json) files exist in the Edge.js application directory (%s).", edgeAppDirCstr.data());
return E_FAIL;
}
else // No app runtimeconfigfile found and also no SDK found
{
throwV8Exception("CoreClrEmbedding::Initialize - Could not find any runtimeconfig file ([appname].runtimeconfig.json in app folder nor dotnet.runtimeconfig.json in sdk folder)");
return E_FAIL;
}
}
else
{
trace::verbose(_X("CoreClrEmbedding::Initialize - host mode: standalone"));
Expand All @@ -392,12 +419,12 @@ HRESULT CoreClrEmbedding::Initialize(BOOL debugMode)
pal::string_t packagesEnvironmentVariable;
pal::getenv(_X("NUGET_PACKAGES"), &packagesEnvironmentVariable);

if (packagesEnvironmentVariable.length() == 0)
if (packagesEnvironmentVariable.empty())
{
pal::string_t profileDirectory;
pal::getenv(_X("USERPROFILE"), &profileDirectory);

if (profileDirectory.length() == 0)
if (profileDirectory.empty())
{
pal::getenv(_X("HOME"), &profileDirectory);
}
Expand Down Expand Up @@ -638,14 +665,14 @@ HRESULT CoreClrEmbedding::Initialize(BOOL debugMode)

SetCallV8FunctionDelegateFunction setCallV8Function;

CREATE_DELEGATE("GetFunc", &getFunc);
CREATE_DELEGATE("CallFunc", &callFunc);
CREATE_DELEGATE("ContinueTask", &continueTask);
CREATE_DELEGATE("FreeHandle", &freeHandle);
CREATE_DELEGATE("FreeMarshalData", &freeMarshalData);
CREATE_DELEGATE("SetCallV8FunctionDelegate", &setCallV8Function);
CREATE_DELEGATE("CompileFunc", &compileFunc);
CREATE_DELEGATE("Initialize", &initialize);
CREATE_DELEGATE("GetFunc", &getFunc)
CREATE_DELEGATE("CallFunc", &callFunc)
CREATE_DELEGATE("ContinueTask", &continueTask)
CREATE_DELEGATE("FreeHandle", &freeHandle)
CREATE_DELEGATE("FreeMarshalData", &freeMarshalData)
CREATE_DELEGATE("SetCallV8FunctionDelegate", &setCallV8Function)
CREATE_DELEGATE("CompileFunc", &compileFunc)
CREATE_DELEGATE("Initialize", &initialize)

trace::info(_X("CoreClrEmbedding::Initialize - Getting runtime info"));

Expand Down
39 changes: 33 additions & 6 deletions src/CoreCLREmbedding/host/runtime_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ runtime_config_t::runtime_config_t(const pal::string_t& path, const pal::string_
trace::verbose(_X("Runtime config [%s] is valid=[%d]"), path.c_str(), m_valid);
}

// Parse runtimeconfig, see documentation here https://github.com/dotnet/sdk/blob/main/documentation/specs/runtime-configuration-file.md
bool runtime_config_t::parse_opts(const json_value& opts)
{
// Note: both runtime_config and dev_runtime_config call into the function.
Expand Down Expand Up @@ -71,17 +72,43 @@ bool runtime_config_t::parse_opts(const json_value& opts)
m_prerelease_roll_fwd = prerelease_roll_fwd->second.as_bool();
}

auto framework = opts_obj.find(_X("framework"));
if (framework == opts_obj.end())
auto framework = opts_obj.find(_X("framework"));
const web::json::object* fx_obj = nullptr;

if (framework == opts_obj.end()) // Found no "framework" section in file, trying "frameworks" or "includedFrameworks"
{
return true;
auto frameworks = opts_obj.find(_X("frameworks"));
if (frameworks == opts_obj.end())
{
frameworks = opts_obj.find(_X("includedFrameworks"));

if (frameworks == opts_obj.end())
{
trace::verbose(_X("Found neither 'framework' nor 'frameworks' nor 'includedFrameworks' section in runtimeconfig.json file"));
return true;
}
}

const auto& frameworks_array = frameworks->second.as_array();
if (frameworks_array.size() == 0)
{
trace::verbose(_X("'Frameworks' in runtimeconfig.json file section found but is empty"));
return true;
}

fx_obj = &frameworks_array.at(0).as_object(); // Using first element of frameworks array
}
else
{
fx_obj = &framework->second.as_object();
}

m_portable = true;
m_fx_name = fx_obj->at(_X("name")).as_string();
m_fx_ver = fx_obj->at(_X("version")).as_string();

trace::verbose(_X("Found framework [%s] with version [%s] in runtimeconfig.json file"), m_fx_name.c_str(), m_fx_ver.c_str());

const auto& fx_obj = framework->second.as_object();
m_fx_name = fx_obj.at(_X("name")).as_string();
m_fx_ver = fx_obj.at(_X("version")).as_string();
return true;
}

Expand Down
Loading

0 comments on commit 3c4966c

Please sign in to comment.