Skip to content

Commit ae64899

Browse files
authored
Add runtime property HOSTFXR_PATH (#55369)
* Add property HOSTFXR_PATH * Comment * PR feedback * Use get_own_module_path since we are on hostfxr * Dispose FileStream
1 parent f82b730 commit ae64899

File tree

7 files changed

+102
-17
lines changed

7 files changed

+102
-17
lines changed

src/installer/tests/Assets/TestProjects/RuntimeProperties/Program.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ public static void Main(string[] args)
1414

1515
foreach (string propertyName in args)
1616
{
17-
Console.WriteLine($"AppContext.GetData({propertyName}) = {System.AppContext.GetData(propertyName)}");
17+
var propertyValue = (string)System.AppContext.GetData(propertyName);
18+
if (string.IsNullOrEmpty(propertyValue))
19+
{
20+
Console.WriteLine($"Property '{propertyName}' was not found.");
21+
continue;
22+
}
23+
24+
Console.WriteLine($"AppContext.GetData({propertyName}) = {propertyValue}");
1825
}
1926
}
2027
}

src/installer/tests/HostActivation.Tests/DotNetBuilder.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,22 @@ public DotNetBuilder AddFramework(
174174
return this;
175175
}
176176

177+
public DotNetBuilder AddMockSDK(
178+
string version,
179+
string MNAVersion)
180+
{
181+
string path = Path.Combine(_path, "sdk", version);
182+
Directory.CreateDirectory(path);
183+
184+
using var _ = File.Create(Path.Combine(path, "dotnet.dll"));
185+
186+
RuntimeConfig dotnetRuntimeConfig = new RuntimeConfig(Path.Combine(path, "dotnet.runtimeconfig.json"));
187+
dotnetRuntimeConfig.WithFramework(new RuntimeConfig.Framework("Microsoft.NETCore.App", MNAVersion));
188+
dotnetRuntimeConfig.Save();
189+
190+
return this;
191+
}
192+
177193
public DotNetCli Build()
178194
{
179195
return new DotNetCli(_path);

src/installer/tests/HostActivation.Tests/RuntimeProperties.cs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.IO;
6+
using Microsoft.DotNet.Cli.Build;
67
using Xunit;
78

89
namespace Microsoft.DotNet.CoreSetup.Test.HostActivation
@@ -25,9 +26,7 @@ public void AppConfigProperty_AppCanGetData()
2526
var dotnet = fixture.BuiltDotnet;
2627
var appDll = fixture.TestProject.AppDll;
2728
dotnet.Exec(appDll, sharedState.AppTestPropertyName)
28-
.EnvironmentVariable("COREHOST_TRACE", "1")
29-
.CaptureStdErr()
30-
.CaptureStdOut()
29+
.EnableTracingAndCaptureOutputs()
3130
.Execute()
3231
.Should().Pass()
3332
.And.HaveStdErrContaining($"Property {sharedState.AppTestPropertyName} = {sharedState.AppTestPropertyValue}")
@@ -43,9 +42,7 @@ public void FrameworkConfigProperty_AppCanGetData()
4342
var dotnet = fixture.BuiltDotnet;
4443
var appDll = fixture.TestProject.AppDll;
4544
dotnet.Exec(appDll, sharedState.FrameworkTestPropertyName)
46-
.EnvironmentVariable("COREHOST_TRACE", "1")
47-
.CaptureStdErr()
48-
.CaptureStdOut()
45+
.EnableTracingAndCaptureOutputs()
4946
.Execute()
5047
.Should().Pass()
5148
.And.HaveStdErrContaining($"Property {sharedState.FrameworkTestPropertyName} = {sharedState.FrameworkTestPropertyValue}")
@@ -65,15 +62,39 @@ public void DuplicateConfigProperty_AppConfigValueUsed()
6562
var dotnet = fixture.BuiltDotnet;
6663
var appDll = fixture.TestProject.AppDll;
6764
dotnet.Exec(appDll, sharedState.FrameworkTestPropertyName)
68-
.EnvironmentVariable("COREHOST_TRACE", "1")
69-
.CaptureStdErr()
70-
.CaptureStdOut()
65+
.EnableTracingAndCaptureOutputs()
7166
.Execute()
7267
.Should().Pass()
7368
.And.HaveStdErrContaining($"Property {sharedState.FrameworkTestPropertyName} = {sharedState.AppTestPropertyValue}")
7469
.And.HaveStdOutContaining($"AppContext.GetData({sharedState.FrameworkTestPropertyName}) = {sharedState.AppTestPropertyValue}");
7570
}
7671

72+
[Fact]
73+
public void HostFxrPathProperty_SetWhenRunningSDKCommand()
74+
{
75+
var dotnet = sharedState.MockSDK;
76+
dotnet.Exec("--info")
77+
.EnableTracingAndCaptureOutputs()
78+
.Execute()
79+
.Should().Pass()
80+
.And.HaveStdErrContaining($"Property {sharedState.HostFxrPathPropertyName} = {dotnet.GreatestVersionHostFxrFilePath}");
81+
}
82+
83+
[Fact]
84+
public void HostFxrPathProperty_NotVisibleFromApp()
85+
{
86+
var fixture = sharedState.RuntimePropertiesFixture
87+
.Copy();
88+
89+
var dotnet = fixture.BuiltDotnet;
90+
var appDll = fixture.TestProject.AppDll;
91+
dotnet.Exec(appDll, sharedState.HostFxrPathPropertyName)
92+
.EnableTracingAndCaptureOutputs()
93+
.Execute()
94+
.Should().Pass()
95+
.And.HaveStdOutContaining($"Property '{sharedState.HostFxrPathPropertyName}' was not found.");
96+
}
97+
7798
[Fact]
7899
public void DuplicateCommonProperty_Fails()
79100
{
@@ -88,9 +109,7 @@ public void DuplicateCommonProperty_Fails()
88109
var dotnet = fixture.BuiltDotnet;
89110
var appDll = fixture.TestProject.AppDll;
90111
dotnet.Exec(appDll)
91-
.EnvironmentVariable("COREHOST_TRACE", "1")
92-
.CaptureStdErr()
93-
.CaptureStdOut()
112+
.EnableTracingAndCaptureOutputs()
94113
.Execute()
95114
.Should().Fail()
96115
.And.HaveStdErrContaining($"Duplicate runtime property found: {name}");
@@ -100,11 +119,13 @@ public class SharedTestState : IDisposable
100119
{
101120
public TestProjectFixture RuntimePropertiesFixture { get; }
102121
public RepoDirectoriesProvider RepoDirectories { get; }
122+
public DotNetCli MockSDK { get; }
103123

104124
public string AppTestPropertyName => "APP_TEST_PROPERTY";
105125
public string AppTestPropertyValue => "VALUE_FROM_APP";
106126
public string FrameworkTestPropertyName => "FRAMEWORK_TEST_PROPERTY";
107127
public string FrameworkTestPropertyValue => "VALUE_FROM_FRAMEWORK";
128+
public string HostFxrPathPropertyName => "HOSTFXR_PATH";
108129

109130
private readonly string copiedDotnet;
110131

@@ -113,6 +134,19 @@ public SharedTestState()
113134
copiedDotnet = Path.Combine(TestArtifact.TestArtifactsPath, "runtimeProperties");
114135
SharedFramework.CopyDirectory(Path.Combine(TestArtifact.TestArtifactsPath, "sharedFrameworkPublish"), copiedDotnet);
115136

137+
MockSDK = new DotNetBuilder(copiedDotnet, Path.Combine(TestArtifact.TestArtifactsPath, "sharedFrameworkPublish"), "exe")
138+
.AddMicrosoftNETCoreAppFrameworkMockCoreClr("9999.0.0")
139+
.AddMockSDK("9999.0.0-dev", "9999.0.0")
140+
.Build();
141+
142+
File.WriteAllText(Path.Combine(MockSDK.BinPath, "global.json"),
143+
@"
144+
{
145+
""sdk"": {
146+
""version"": ""9999.0.0-dev""
147+
}
148+
}");
149+
116150
RepoDirectories = new RepoDirectoriesProvider(builtDotnet: copiedDotnet);
117151

118152
RuntimePropertiesFixture = new TestProjectFixture("RuntimeProperties", RepoDirectories)

src/native/corehost/fxr/corehost_init.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ corehost_init_t::corehost_init_t(
2020
const pal::string_t& additional_deps_serialized,
2121
const std::vector<pal::string_t>& probe_paths,
2222
const host_mode_t mode,
23-
const fx_definition_vector_t& fx_definitions)
23+
const fx_definition_vector_t& fx_definitions,
24+
const std::vector<std::pair<pal::string_t, pal::string_t>>& additional_properties)
2425
: m_tfm(get_app(fx_definitions).get_runtime_config().get_tfm())
2526
, m_deps_file(deps_file)
2627
, m_additional_deps_serialized(additional_deps_serialized)
@@ -35,6 +36,12 @@ corehost_init_t::corehost_init_t(
3536
{
3637
make_cstr_arr(m_probe_paths, &m_probe_paths_cstr);
3738

39+
for (const auto& additional_property : additional_properties)
40+
{
41+
m_clr_keys.push_back(additional_property.first);
42+
m_clr_values.push_back(additional_property.second);
43+
}
44+
3845
size_t fx_count = fx_definitions.size();
3946
m_fx_names.reserve(fx_count);
4047
m_fx_dirs.reserve(fx_count);

src/native/corehost/fxr/corehost_init.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class corehost_init_t
4545
const pal::string_t& additional_deps_serialized,
4646
const std::vector<pal::string_t>& probe_paths,
4747
const host_mode_t mode,
48-
const fx_definition_vector_t& fx_definitions);
48+
const fx_definition_vector_t& fx_definitions,
49+
const std::vector<std::pair<pal::string_t, pal::string_t>>& additional_properties);
4950

5051
const host_interface_t& get_host_init_data();
5152

src/native/corehost/fxr/fx_muxer.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ namespace
370370
const pal::string_t &app_candidate,
371371
const opt_map_t &opts,
372372
host_mode_t mode,
373+
const bool is_sdk_command,
373374
/*out*/ pal::string_t &hostpolicy_dir,
374375
/*out*/ std::unique_ptr<corehost_init_t> &init)
375376
{
@@ -473,6 +474,16 @@ namespace
473474
}
474475
}
475476

477+
std::vector<std::pair<pal::string_t, pal::string_t>> additional_properties;
478+
if (is_sdk_command)
479+
{
480+
pal::string_t fxr_path;
481+
pal::get_own_module_path(&fxr_path);
482+
483+
// We pass the loaded hostfxr path to the SDK can load it without relying on dlopen/LoadLibrary to find it.
484+
additional_properties.push_back(std::make_pair(_X("HOSTFXR_PATH"), fxr_path));
485+
}
486+
476487
const known_options opts_probe_path = known_options::additional_probing_path;
477488
std::vector<pal::string_t> spec_probe_paths = opts.count(opts_probe_path) ? opts.find(opts_probe_path)->second : std::vector<pal::string_t>();
478489
std::vector<pal::string_t> probe_realpaths = get_probe_realpaths(fx_definitions, spec_probe_paths);
@@ -485,7 +496,7 @@ namespace
485496
return StatusCode::CoreHostLibMissingFailure;
486497
}
487498

488-
init.reset(new corehost_init_t(host_command, host_info, deps_file, additional_deps_serialized, probe_realpaths, mode, fx_definitions));
499+
init.reset(new corehost_init_t(host_command, host_info, deps_file, additional_deps_serialized, probe_realpaths, mode, fx_definitions, additional_properties));
489500

490501
return StatusCode::Success;
491502
}
@@ -498,6 +509,7 @@ namespace
498509
int new_argc,
499510
const pal::char_t** new_argv,
500511
host_mode_t mode,
512+
const bool is_sdk_command,
501513
pal::char_t out_buffer[],
502514
int32_t buffer_size,
503515
int32_t* required_buffer_size)
@@ -510,6 +522,7 @@ namespace
510522
app_candidate,
511523
opts,
512524
mode,
525+
is_sdk_command,
513526
hostpolicy_dir,
514527
init);
515528
if (rc != StatusCode::Success)
@@ -572,6 +585,7 @@ int fx_muxer_t::execute(
572585
argv,
573586
new_argoff,
574587
mode,
588+
false /*is_sdk_command*/,
575589
result_buffer,
576590
buffer_size,
577591
required_buffer_size);
@@ -621,7 +635,8 @@ namespace
621635
}
622636

623637
const pal::string_t additional_deps_serialized;
624-
init.reset(new corehost_init_t(pal::string_t{}, host_info, deps_file, additional_deps_serialized, probe_realpaths, mode, fx_definitions));
638+
const std::vector<std::pair<pal::string_t, pal::string_t>> additional_properties;
639+
init.reset(new corehost_init_t(pal::string_t{}, host_info, deps_file, additional_deps_serialized, probe_realpaths, mode, fx_definitions, additional_properties));
625640

626641
return StatusCode::Success;
627642
}
@@ -725,6 +740,7 @@ int fx_muxer_t::initialize_for_app(
725740
host_info.app_path,
726741
opts,
727742
mode,
743+
false /*is_sdk_command*/,
728744
hostpolicy_dir,
729745
init);
730746
if (rc != StatusCode::Success)
@@ -978,6 +994,7 @@ int fx_muxer_t::handle_exec_host_command(
978994
const pal::char_t* argv[],
979995
int argoff,
980996
host_mode_t mode,
997+
const bool is_sdk_command,
981998
pal::char_t result_buffer[],
982999
int32_t buffer_size,
9831000
int32_t* required_buffer_size)
@@ -1006,6 +1023,7 @@ int fx_muxer_t::handle_exec_host_command(
10061023
new_argc,
10071024
new_argv,
10081025
mode,
1026+
is_sdk_command,
10091027
result_buffer,
10101028
buffer_size,
10111029
required_buffer_size);
@@ -1096,6 +1114,7 @@ int fx_muxer_t::handle_cli(
10961114
new_argv.data(),
10971115
new_argoff,
10981116
host_mode_t::muxer,
1117+
true /*is_sdk_command*/,
10991118
nullptr /*result_buffer*/,
11001119
0 /*buffer_size*/,
11011120
nullptr/*required_buffer_size*/);

src/native/corehost/fxr/fx_muxer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class fx_muxer_t
4747
const pal::char_t* argv[],
4848
int argoff,
4949
host_mode_t mode,
50+
const bool is_sdk_command,
5051
pal::char_t result_buffer[],
5152
int32_t buffer_size,
5253
int32_t* required_buffer_size);

0 commit comments

Comments
 (0)