diff --git a/eng/SignCheckExclusionsFile.txt b/eng/SignCheckExclusionsFile.txt
index 2db3b79a9339e..a78ad401525dd 100644
--- a/eng/SignCheckExclusionsFile.txt
+++ b/eng/SignCheckExclusionsFile.txt
@@ -7,6 +7,7 @@
;; and SCD apps. If they are signed, the file that the SDK produces has an invalid signature and
;; can't be signed again. More info at https://github.com/dotnet/core-setup/pull/7549.
*apphost.exe;;Template, https://github.com/dotnet/core-setup/pull/7549
+*singlefilehost.exe;;Template, https://github.com/dotnet/core-setup/pull/7549
*comhost.dll;;Template, https://github.com/dotnet/core-setup/pull/7549
*apphosttemplateapphostexe.exe;;Template, https://github.com/dotnet/core-setup/pull/7549
*comhosttemplatecomhostdll.dll;;Template, https://github.com/dotnet/core-setup/pull/7549
diff --git a/eng/Signing.props b/eng/Signing.props
index 05f2a8bcb3957..5ceb96ac54bf9 100644
--- a/eng/Signing.props
+++ b/eng/Signing.props
@@ -24,7 +24,7 @@
-
+
diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake
index 060cff8987e35..49b0064499eb4 100644
--- a/eng/native/functions.cmake
+++ b/eng/native/functions.cmake
@@ -175,8 +175,8 @@ function(generate_exports_file)
add_custom_command(
OUTPUT ${outputFilename}
- COMMAND ${AWK} -f ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} ${INPUT_LIST} >${outputFilename}
- DEPENDS ${INPUT_LIST} ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT}
+ COMMAND ${AWK} -f ${CLR_ENG_NATIVE_DIR}/${AWK_SCRIPT} ${INPUT_LIST} >${outputFilename}
+ DEPENDS ${INPUT_LIST} ${CLR_ENG_NATIVE_DIR}/${AWK_SCRIPT}
COMMENT "Generating exports file ${outputFilename}"
)
set_source_files_properties(${outputFilename}
@@ -196,8 +196,8 @@ function(generate_exports_file_prefix inputFilename outputFilename prefix)
add_custom_command(
OUTPUT ${outputFilename}
- COMMAND ${AWK} -f ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} ${AWK_VARS} ${inputFilename} >${outputFilename}
- DEPENDS ${inputFilename} ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT}
+ COMMAND ${AWK} -f ${CLR_ENG_NATIVE_DIR}/${AWK_SCRIPT} ${AWK_VARS} ${inputFilename} >${outputFilename}
+ DEPENDS ${inputFilename} ${CLR_ENG_NATIVE_DIR}/${AWK_SCRIPT}
COMMENT "Generating exports file ${outputFilename}"
)
set_source_files_properties(${outputFilename}
diff --git a/src/coreclr/generateexportedsymbols.awk b/eng/native/generateexportedsymbols.awk
similarity index 100%
rename from src/coreclr/generateexportedsymbols.awk
rename to eng/native/generateexportedsymbols.awk
diff --git a/src/coreclr/generateversionscript.awk b/eng/native/generateversionscript.awk
similarity index 100%
rename from src/coreclr/generateversionscript.awk
rename to eng/native/generateversionscript.awk
diff --git a/src/installer/corehost/cli/CMakeLists.txt b/src/installer/corehost/cli/CMakeLists.txt
index 15ce0fa117721..3c1bdb1f2f0ec 100644
--- a/src/installer/corehost/cli/CMakeLists.txt
+++ b/src/installer/corehost/cli/CMakeLists.txt
@@ -1,10 +1,10 @@
add_subdirectory(hostcommon)
add_subdirectory(apphost)
add_subdirectory(dotnet)
-add_subdirectory(fxr)
-add_subdirectory(hostpolicy)
add_subdirectory(nethost)
add_subdirectory(test_fx_ver)
+add_subdirectory(fxr)
+add_subdirectory(hostpolicy)
add_subdirectory(test)
diff --git a/src/installer/corehost/cli/apphost/CMakeLists.txt b/src/installer/corehost/cli/apphost/CMakeLists.txt
index ba01e32ec47c7..ec7e8e3e2ce4b 100644
--- a/src/installer/corehost/cli/apphost/CMakeLists.txt
+++ b/src/installer/corehost/cli/apphost/CMakeLists.txt
@@ -2,49 +2,5 @@
# The .NET Foundation licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
-project(apphost)
-set(DOTNET_PROJECT_NAME "apphost")
-
-# Add RPATH to the apphost binary that allows using local copies of shared libraries
-# dotnet core depends on for special scenarios when system wide installation of such
-# dependencies is not possible for some reason.
-# This cannot be enabled for MacOS (Darwin) since its RPATH works in a different way,
-# doesn't apply to libraries loaded via dlopen and most importantly, it is not transitive.
-if (NOT CLR_CMAKE_TARGET_OSX)
- set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
- set(CMAKE_INSTALL_RPATH "\$ORIGIN/netcoredeps")
-endif()
-
-set(SKIP_VERSIONING 1)
-
-set(SOURCES
- ./bundle_marker.cpp
-)
-
-set(HEADERS
- ./bundle_marker.h
-)
-
-if(CLR_CMAKE_TARGET_WIN32)
- list(APPEND SOURCES
- apphost.windows.cpp)
-
- list(APPEND HEADERS
- apphost.windows.h)
-endif()
-
-include(../exe.cmake)
-
-add_definitions(-DFEATURE_APPHOST=1)
-
-# Disable manifest generation into the file .exe on Windows
-if(CLR_CMAKE_TARGET_WIN32)
- set_property(TARGET ${PROJECT_NAME} PROPERTY
- LINK_FLAGS "/MANIFEST:NO"
- )
-endif()
-
-# Specify non-default Windows libs to be used for Arm/Arm64 builds
-if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64))
- target_link_libraries(apphost Advapi32.lib shell32.lib)
-endif()
+add_subdirectory(static)
+add_subdirectory(standalone)
diff --git a/src/installer/corehost/cli/apphost/standalone/CMakeLists.txt b/src/installer/corehost/cli/apphost/standalone/CMakeLists.txt
new file mode 100644
index 0000000000000..60d9a103b12fb
--- /dev/null
+++ b/src/installer/corehost/cli/apphost/standalone/CMakeLists.txt
@@ -0,0 +1,54 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+project(apphost)
+set(DOTNET_PROJECT_NAME "apphost")
+
+# Add RPATH to the apphost binary that allows using local copies of shared libraries
+# dotnet core depends on for special scenarios when system wide installation of such
+# dependencies is not possible for some reason.
+# This cannot be enabled for MacOS (Darwin) since its RPATH works in a different way,
+# doesn't apply to libraries loaded via dlopen and most importantly, it is not transitive.
+if (NOT CLR_CMAKE_TARGET_OSX)
+ set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN/netcoredeps")
+endif()
+
+set(SKIP_VERSIONING 1)
+
+include_directories(..)
+
+set(SOURCES
+ ../bundle_marker.cpp
+ ./hostfxr_resolver_t.cpp
+)
+
+set(HEADERS
+ ../bundle_marker.h
+ ../../../hostfxr_resolver_t.h
+)
+
+if(CLR_CMAKE_TARGET_WIN32)
+ list(APPEND SOURCES
+ ../apphost.windows.cpp)
+
+ list(APPEND HEADERS
+ ../apphost.windows.h)
+endif()
+
+include(../../exe.cmake)
+
+add_definitions(-DFEATURE_APPHOST=1)
+
+# Disable manifest generation into the file .exe on Windows
+if(CLR_CMAKE_TARGET_WIN32)
+ set_property(TARGET ${PROJECT_NAME} PROPERTY
+ LINK_FLAGS "/MANIFEST:NO"
+ )
+endif()
+
+# Specify non-default Windows libs to be used for Arm/Arm64 builds
+if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64))
+ target_link_libraries(apphost Advapi32.lib shell32.lib)
+endif()
diff --git a/src/installer/corehost/cli/apphost/standalone/hostfxr_resolver_t.cpp b/src/installer/corehost/cli/apphost/standalone/hostfxr_resolver_t.cpp
new file mode 100644
index 0000000000000..4f3c3888428c5
--- /dev/null
+++ b/src/installer/corehost/cli/apphost/standalone/hostfxr_resolver_t.cpp
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include
+
+#include "pal.h"
+#include "fxr_resolver.h"
+#include "trace.h"
+#include "hostfxr_resolver_t.h"
+
+hostfxr_main_bundle_startupinfo_fn hostfxr_resolver_t::resolve_main_bundle_startupinfo()
+{
+ assert(m_hostfxr_dll != nullptr);
+ return reinterpret_cast(pal::get_symbol(m_hostfxr_dll, "hostfxr_main_bundle_startupinfo"));
+}
+
+hostfxr_set_error_writer_fn hostfxr_resolver_t::resolve_set_error_writer()
+{
+ assert(m_hostfxr_dll != nullptr);
+ return reinterpret_cast(pal::get_symbol(m_hostfxr_dll, "hostfxr_set_error_writer"));
+}
+
+hostfxr_main_startupinfo_fn hostfxr_resolver_t::resolve_main_startupinfo()
+{
+ assert(m_hostfxr_dll != nullptr);
+ return reinterpret_cast(pal::get_symbol(m_hostfxr_dll, "hostfxr_main_startupinfo"));
+}
+
+hostfxr_main_fn hostfxr_resolver_t::resolve_main_v1()
+{
+ assert(m_hostfxr_dll != nullptr);
+ return reinterpret_cast(pal::get_symbol(m_hostfxr_dll, "hostfxr_main"));
+}
+
+hostfxr_resolver_t::hostfxr_resolver_t(const pal::string_t& app_root)
+{
+ if (!fxr_resolver::try_get_path(app_root, &m_dotnet_root, &m_fxr_path))
+ {
+ m_status_code = StatusCode::CoreHostLibMissingFailure;
+ }
+ else if (pal::load_library(&m_fxr_path, &m_hostfxr_dll))
+ {
+ m_status_code = StatusCode::Success;
+ }
+ else
+ {
+ trace::error(_X("The library %s was found, but loading it from %s failed"), LIBFXR_NAME, m_fxr_path.c_str());
+ trace::error(_X(" - Installing .NET prerequisites might help resolve this problem."));
+ trace::error(_X(" %s"), DOTNET_CORE_INSTALL_PREREQUISITES_URL);
+ m_status_code = StatusCode::CoreHostLibLoadFailure;
+ }
+}
+
+hostfxr_resolver_t::~hostfxr_resolver_t()
+{
+ if (m_hostfxr_dll != nullptr)
+ {
+ pal::unload_library(m_hostfxr_dll);
+ }
+}
diff --git a/src/installer/corehost/cli/apphost/static/CMakeLists.txt b/src/installer/corehost/cli/apphost/static/CMakeLists.txt
new file mode 100644
index 0000000000000..967aebb24133a
--- /dev/null
+++ b/src/installer/corehost/cli/apphost/static/CMakeLists.txt
@@ -0,0 +1,63 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+project(singlefilehost)
+set(DOTNET_PROJECT_NAME "singlefilehost")
+
+# Add RPATH to the apphost binary that allows using local copies of shared libraries
+# dotnet core depends on for special scenarios when system wide installation of such
+# dependencies is not possible for some reason.
+# This cannot be enabled for MacOS (Darwin) since its RPATH works in a different way,
+# doesn't apply to libraries loaded via dlopen and most importantly, it is not transitive.
+if (NOT CLR_CMAKE_TARGET_OSX)
+ set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN/netcoredeps")
+endif()
+
+set(SKIP_VERSIONING 1)
+
+include_directories(..)
+include_directories(../../json)
+
+set(SOURCES
+ ../bundle_marker.cpp
+ ./hostfxr_resolver_t.cpp
+ ./hostpolicy_resolver.cpp
+)
+
+set(HEADERS
+ ../bundle_marker.h
+ ../../../hostfxr_resolver_t.h
+)
+
+if(CLR_CMAKE_TARGET_WIN32)
+ list(APPEND SOURCES
+ ../apphost.windows.cpp)
+
+ list(APPEND HEADERS
+ ../apphost.windows.h)
+endif()
+
+include(../../exe.cmake)
+
+add_definitions(-DFEATURE_APPHOST=1)
+add_definitions(-DFEATURE_STATIC_HOST=1)
+
+# Disable manifest generation into the file .exe on Windows
+if(CLR_CMAKE_TARGET_WIN32)
+ set_property(TARGET ${PROJECT_NAME} PROPERTY
+ LINK_FLAGS "/MANIFEST:NO"
+ )
+endif()
+
+# Specify non-default Windows libs to be used for Arm/Arm64 builds
+if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64))
+ target_link_libraries(singlefilehost Advapi32.lib shell32.lib)
+endif()
+
+target_link_libraries(singlefilehost
+ libhostfxr_static
+ libhostpolicy_static
+ libhostcommon
+)
diff --git a/src/installer/corehost/cli/apphost/static/hostfxr_resolver_t.cpp b/src/installer/corehost/cli/apphost/static/hostfxr_resolver_t.cpp
new file mode 100644
index 0000000000000..2c7e2b87a5f6d
--- /dev/null
+++ b/src/installer/corehost/cli/apphost/static/hostfxr_resolver_t.cpp
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include
+#include "trace.h"
+#include "hostfxr.h"
+#include "hostfxr_resolver_t.h"
+
+extern "C"
+{
+ int HOSTFXR_CALLTYPE hostfxr_main_bundle_startupinfo(const int argc, const pal::char_t* argv[], const pal::char_t* host_path, const pal::char_t* dotnet_root, const pal::char_t* app_path, int64_t bundle_header_offset);
+ int HOSTFXR_CALLTYPE hostfxr_main_startupinfo(const int argc, const pal::char_t* argv[], const pal::char_t* host_path, const pal::char_t* dotnet_root, const pal::char_t* app_path);
+ int HOSTFXR_CALLTYPE hostfxr_main(const int argc, const pal::char_t* argv[]);
+ hostfxr_error_writer_fn HOSTFXR_CALLTYPE hostfxr_set_error_writer(hostfxr_error_writer_fn error_writer);
+}
+
+hostfxr_main_bundle_startupinfo_fn hostfxr_resolver_t::resolve_main_bundle_startupinfo()
+{
+ assert(m_hostfxr_dll == nullptr);
+ return hostfxr_main_bundle_startupinfo;
+}
+
+hostfxr_set_error_writer_fn hostfxr_resolver_t::resolve_set_error_writer()
+{
+ assert(m_hostfxr_dll == nullptr);
+ return hostfxr_set_error_writer;
+}
+
+hostfxr_main_startupinfo_fn hostfxr_resolver_t::resolve_main_startupinfo()
+{
+ assert(m_hostfxr_dll == nullptr);
+ return hostfxr_main_startupinfo;
+}
+
+hostfxr_main_fn hostfxr_resolver_t::resolve_main_v1()
+{
+ assert(m_hostfxr_dll == nullptr);
+ assert(!"This function should not be called in a static host");
+ return nullptr;
+}
+
+hostfxr_resolver_t::hostfxr_resolver_t(const pal::string_t& app_root)
+{
+ if (app_root.length() == 0)
+ {
+ trace::info(_X("Application root path is empty. This shouldn't happen"));
+ m_status_code = StatusCode::CoreHostLibMissingFailure;
+ }
+ else
+ {
+ trace::info(_X("Using internal fxr"));
+
+ m_dotnet_root.assign(app_root);
+ m_fxr_path.assign(app_root);
+
+ m_status_code = StatusCode::Success;
+ }
+}
+
+hostfxr_resolver_t::~hostfxr_resolver_t()
+{
+}
diff --git a/src/installer/corehost/cli/apphost/static/hostpolicy_resolver.cpp b/src/installer/corehost/cli/apphost/static/hostpolicy_resolver.cpp
new file mode 100644
index 0000000000000..0b2a35639a2e1
--- /dev/null
+++ b/src/installer/corehost/cli/apphost/static/hostpolicy_resolver.cpp
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include
+#include
+#include
+#include "hostpolicy_resolver.h"
+#include
+#include
+
+extern "C"
+{
+ int HOSTPOLICY_CALLTYPE corehost_load(const host_interface_t* init);
+ int HOSTPOLICY_CALLTYPE corehost_unload();
+ corehost_error_writer_fn HOSTPOLICY_CALLTYPE corehost_set_error_writer(corehost_error_writer_fn error_writer);
+ int HOSTPOLICY_CALLTYPE corehost_initialize(const corehost_initialize_request_t *init_request, int32_t options, /*out*/ corehost_context_contract *context_contract);
+ int HOSTPOLICY_CALLTYPE corehost_main(const int argc, const pal::char_t* argv[]);
+ int HOSTPOLICY_CALLTYPE corehost_main_with_output_buffer(const int argc, const pal::char_t* argv[], pal::char_t buffer[], int32_t buffer_size, int32_t* required_buffer_size);
+}
+
+int hostpolicy_resolver::load(
+ const pal::string_t& lib_dir,
+ pal::dll_t* dll,
+ hostpolicy_contract_t &hostpolicy_contract)
+{
+ static hostpolicy_contract_t contract;
+
+ trace::info(_X("Using internal hostpolicy"));
+
+ contract.load = corehost_load;
+ contract.unload = corehost_unload;
+ contract.set_error_writer = corehost_set_error_writer;
+ contract.initialize = corehost_initialize;
+ contract.corehost_main = corehost_main;
+ contract.corehost_main_with_output_buffer = corehost_main_with_output_buffer;
+
+ hostpolicy_contract = contract;
+ *dll = nullptr;
+
+ return StatusCode::Success;
+}
+
+bool hostpolicy_resolver::try_get_dir(
+ host_mode_t mode,
+ const pal::string_t& dotnet_root,
+ const fx_definition_vector_t& fx_definitions,
+ const pal::string_t& app_candidate,
+ const pal::string_t& specified_deps_file,
+ const std::vector& probe_realpaths,
+ pal::string_t* impl_dir)
+{
+ // static apphost is not supposed to be used in a framework-dependent app
+ assert(!get_app(fx_definitions).get_runtime_config().get_is_framework_dependent());
+ assert(mode == host_mode_t::apphost);
+
+ impl_dir->assign(dotnet_root);
+ return true;
+}
diff --git a/src/installer/corehost/cli/dotnet/CMakeLists.txt b/src/installer/corehost/cli/dotnet/CMakeLists.txt
index 4527986acfe3c..798ae4030ea0a 100644
--- a/src/installer/corehost/cli/dotnet/CMakeLists.txt
+++ b/src/installer/corehost/cli/dotnet/CMakeLists.txt
@@ -10,4 +10,8 @@ if(CLR_CMAKE_TARGET_WIN32)
dotnet.manifest)
endif()
+list(APPEND SOURCES
+ ../apphost/standalone/hostfxr_resolver_t.cpp
+)
+
include(../exe.cmake)
diff --git a/src/installer/corehost/cli/exe.cmake b/src/installer/corehost/cli/exe.cmake
index c9295d5c65f77..3acc130174aa3 100644
--- a/src/installer/corehost/cli/exe.cmake
+++ b/src/installer/corehost/cli/exe.cmake
@@ -18,6 +18,9 @@ list(APPEND SOURCES
${CMAKE_CURRENT_LIST_DIR}/fxr_resolver.cpp
${CMAKE_CURRENT_LIST_DIR}/../corehost.cpp
)
+list(APPEND HEADERS
+ ${CMAKE_CURRENT_LIST_DIR}/../hostfxr_resolver_t.h
+)
add_executable(${DOTNET_PROJECT_NAME} ${SOURCES} ${RESOURCES})
diff --git a/src/installer/corehost/cli/fxr/CMakeLists.txt b/src/installer/corehost/cli/fxr/CMakeLists.txt
index 216ecbf076bb7..ec7e8e3e2ce4b 100644
--- a/src/installer/corehost/cli/fxr/CMakeLists.txt
+++ b/src/installer/corehost/cli/fxr/CMakeLists.txt
@@ -2,46 +2,5 @@
# The .NET Foundation licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
-project(hostfxr)
-
-set(DOTNET_PROJECT_NAME "hostfxr")
-
-# Include directories
-include_directories(../json)
-
-# CMake does not recommend using globbing since it messes with the freshness checks
-set(SOURCES
- ./command_line.cpp
- ./corehost_init.cpp
- ./hostfxr.cpp
- ./fx_muxer.cpp
- ./fx_resolver.cpp
- ./fx_resolver.messages.cpp
- ./framework_info.cpp
- ./host_context.cpp
- ./hostpolicy_resolver.cpp
- ./sdk_info.cpp
- ./sdk_resolver.cpp
-)
-
-set(HEADERS
- ../corehost_context_contract.h
- ../hostpolicy.h
- ../fx_definition.h
- ../fx_reference.h
- ../roll_fwd_on_no_candidate_fx_option.h
- ./command_line.h
- ./corehost_init.h
- ./fx_muxer.h
- ./fx_resolver.h
- ./framework_info.h
- ./host_context.h
- ./hostpolicy_resolver.h
- ./sdk_info.h
- ./sdk_resolver.h
-)
-
-include(../lib.cmake)
-
-install_with_stripped_symbols(hostfxr TARGETS corehost)
-target_link_libraries(hostfxr libhostcommon)
+add_subdirectory(static)
+add_subdirectory(standalone)
diff --git a/src/installer/corehost/cli/fxr/fx_muxer.cpp b/src/installer/corehost/cli/fxr/fx_muxer.cpp
index 31c8c17797807..f41e9095ef064 100644
--- a/src/installer/corehost/cli/fxr/fx_muxer.cpp
+++ b/src/installer/corehost/cli/fxr/fx_muxer.cpp
@@ -66,16 +66,11 @@ namespace
}
}
-template
int load_hostpolicy(
const pal::string_t& lib_dir,
pal::dll_t* h_host,
- hostpolicy_contract_t &hostpolicy_contract,
- const char *main_entry_symbol,
- T* main_fn)
+ hostpolicy_contract_t& hostpolicy_contract)
{
- assert(main_entry_symbol != nullptr && main_fn != nullptr);
-
int rc = hostpolicy_resolver::load(lib_dir, h_host, hostpolicy_contract);
if (rc != StatusCode::Success)
{
@@ -83,11 +78,6 @@ int load_hostpolicy(
return rc;
}
- // Obtain entrypoint symbol
- *main_fn = reinterpret_cast(pal::get_symbol(*h_host, main_entry_symbol));
- if (*main_fn == nullptr)
- return StatusCode::CoreHostEntryPointFailure;
-
return StatusCode::Success;
}
@@ -114,7 +104,18 @@ static int execute_app(
hostpolicy_contract_t hostpolicy_contract{};
corehost_main_fn host_main = nullptr;
- int code = load_hostpolicy(impl_dll_dir, &hostpolicy_dll, hostpolicy_contract, "corehost_main", &host_main);
+ int code = load_hostpolicy(impl_dll_dir, &hostpolicy_dll, hostpolicy_contract);
+
+ // Obtain entrypoint symbol
+ if (code == StatusCode::Success)
+ {
+ host_main = hostpolicy_contract.corehost_main;
+ if (host_main == nullptr)
+ {
+ code = StatusCode::CoreHostEntryPointFailure;
+ }
+ }
+
if (code != StatusCode::Success)
{
handle_initialize_failure_or_abort();
@@ -164,7 +165,18 @@ static int execute_host_command(
hostpolicy_contract_t hostpolicy_contract{};
corehost_main_with_output_buffer_fn host_main = nullptr;
- int code = load_hostpolicy(impl_dll_dir, &hostpolicy_dll, hostpolicy_contract, "corehost_main_with_output_buffer", &host_main);
+ int code = load_hostpolicy(impl_dll_dir, &hostpolicy_dll, hostpolicy_contract);
+
+ // Obtain entrypoint symbol
+ if (code == StatusCode::Success)
+ {
+ host_main = hostpolicy_contract.corehost_main_with_output_buffer;
+ if (host_main == nullptr)
+ {
+ code = StatusCode::CoreHostEntryPointFailure;
+ }
+ }
+
if (code != StatusCode::Success)
return code;
@@ -471,7 +483,7 @@ namespace
if (!hostpolicy_resolver::try_get_dir(mode, host_info.dotnet_root, fx_definitions, app_candidate, deps_file, probe_realpaths, &hostpolicy_dir))
{
- return CoreHostLibMissingFailure;
+ return StatusCode::CoreHostLibMissingFailure;
}
init.reset(new corehost_init_t(host_command, host_info, deps_file, additional_deps_serialized, probe_realpaths, mode, fx_definitions));
diff --git a/src/installer/corehost/cli/fxr/hostpolicy_resolver.h b/src/installer/corehost/cli/fxr/hostpolicy_resolver.h
index 4348a53c778e0..35128327b7bca 100644
--- a/src/installer/corehost/cli/fxr/hostpolicy_resolver.h
+++ b/src/installer/corehost/cli/fxr/hostpolicy_resolver.h
@@ -20,6 +20,10 @@ struct hostpolicy_contract_t
// 3.0+ contracts
corehost_set_error_writer_fn set_error_writer;
corehost_initialize_fn initialize;
+
+ // 5.0+ contracts
+ corehost_main_fn corehost_main;
+ corehost_main_with_output_buffer_fn corehost_main_with_output_buffer;
};
namespace hostpolicy_resolver
@@ -38,4 +42,4 @@ namespace hostpolicy_resolver
pal::string_t* impl_dir);
};
-#endif // __HOSTPOLICY_RESOLVER_H__
\ No newline at end of file
+#endif // __HOSTPOLICY_RESOLVER_H__
diff --git a/src/installer/corehost/cli/fxr/standalone/CMakeLists.txt b/src/installer/corehost/cli/fxr/standalone/CMakeLists.txt
new file mode 100644
index 0000000000000..0a2ea92174b6f
--- /dev/null
+++ b/src/installer/corehost/cli/fxr/standalone/CMakeLists.txt
@@ -0,0 +1,65 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+project(hostfxr)
+
+set(DOTNET_PROJECT_NAME "hostfxr")
+
+# Include directories
+include_directories(../../json)
+include_directories(../../fxr)
+
+# CMake does not recommend using globbing since it messes with the freshness checks
+set(SOURCES
+ ./hostpolicy_resolver.cpp
+)
+
+set(HEADERS
+ ../command_line.h
+ ../corehost_init.h
+ ../fx_muxer.h
+ ../fx_resolver.h
+ ../framework_info.h
+ ../host_context.h
+ ../sdk_info.h
+ ../sdk_resolver.h
+ ../hostpolicy_resolver.h
+)
+
+if(CLR_CMAKE_TARGET_WIN32)
+ list(APPEND SOURCES
+ hostfxr.def)
+else(CLR_CMAKE_TARGET_WIN32)
+ set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hostfxr_unixexports.src)
+ set(EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/hostfxr.exports)
+ generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE})
+
+ if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
+ # Add linker exports file option
+ set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE})
+ endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
+
+ if(CLR_CMAKE_HOST_OSX)
+ # Add linker exports file option
+ set(EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${EXPORTS_FILE})
+ endif(CLR_CMAKE_HOST_OSX)
+
+ if(CLR_CMAKE_HOST_SUNOS)
+ # Add linker exports file option
+ set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE})
+ endif(CLR_CMAKE_HOST_SUNOS)
+endif(CLR_CMAKE_TARGET_WIN32)
+
+include(../../lib.cmake)
+
+if(CLR_CMAKE_HOST_UNIX)
+ add_custom_target(hostfxr_exports DEPENDS ${EXPORTS_FILE})
+ add_dependencies(hostfxr hostfxr_exports)
+
+ set_property(TARGET hostfxr APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION})
+ set_property(TARGET hostfxr APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE})
+endif(CLR_CMAKE_HOST_UNIX)
+
+install_with_stripped_symbols(hostfxr TARGETS corehost)
+target_link_libraries(hostfxr libhostcommon libhostfxr_static)
diff --git a/src/installer/corehost/cli/fxr/standalone/hostfxr.def b/src/installer/corehost/cli/fxr/standalone/hostfxr.def
new file mode 100644
index 0000000000000..c86139a7fb58b
--- /dev/null
+++ b/src/installer/corehost/cli/fxr/standalone/hostfxr.def
@@ -0,0 +1,21 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+EXPORTS
+ hostfxr_main_bundle_startupinfo
+ hostfxr_main_startupinfo
+ hostfxr_main
+ hostfxr_resolve_sdk
+ hostfxr_resolve_sdk2
+ hostfxr_get_available_sdks
+ hostfxr_get_native_search_directories
+ hostfxr_set_error_writer
+ hostfxr_initialize_for_dotnet_command_line
+ hostfxr_initialize_for_runtime_config
+ hostfxr_run_app
+ hostfxr_get_runtime_delegate
+ hostfxr_get_runtime_property_value
+ hostfxr_set_runtime_property_value
+ hostfxr_get_runtime_properties
+ hostfxr_close
diff --git a/src/installer/corehost/cli/fxr/standalone/hostfxr_unixexports.src b/src/installer/corehost/cli/fxr/standalone/hostfxr_unixexports.src
new file mode 100644
index 0000000000000..fcf85d027fa64
--- /dev/null
+++ b/src/installer/corehost/cli/fxr/standalone/hostfxr_unixexports.src
@@ -0,0 +1,20 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+hostfxr_main_bundle_startupinfo
+hostfxr_main_startupinfo
+hostfxr_main
+hostfxr_resolve_sdk
+hostfxr_resolve_sdk2
+hostfxr_get_available_sdks
+hostfxr_get_native_search_directories
+hostfxr_set_error_writer
+hostfxr_initialize_for_dotnet_command_line
+hostfxr_initialize_for_runtime_config
+hostfxr_run_app
+hostfxr_get_runtime_delegate
+hostfxr_get_runtime_property_value
+hostfxr_set_runtime_property_value
+hostfxr_get_runtime_properties
+hostfxr_close
diff --git a/src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp b/src/installer/corehost/cli/fxr/standalone/hostpolicy_resolver.cpp
similarity index 97%
rename from src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp
rename to src/installer/corehost/cli/fxr/standalone/hostpolicy_resolver.cpp
index de3291fecc5b5..67881d207944f 100644
--- a/src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp
+++ b/src/installer/corehost/cli/fxr/standalone/hostpolicy_resolver.cpp
@@ -198,6 +198,9 @@ int hostpolicy_resolver::load(
g_hostpolicy_contract.set_error_writer = reinterpret_cast(pal::get_symbol(g_hostpolicy, "corehost_set_error_writer"));
g_hostpolicy_contract.initialize = reinterpret_cast(pal::get_symbol(g_hostpolicy, "corehost_initialize"));
+ g_hostpolicy_contract.corehost_main = reinterpret_cast(pal::get_symbol(g_hostpolicy, "corehost_main"));
+ g_hostpolicy_contract.corehost_main_with_output_buffer = reinterpret_cast(pal::get_symbol(g_hostpolicy, "corehost_main_with_output_buffer"));
+
// It's possible to not have corehost_set_error_writer and corehost_initialize. These were
// introduced in 3.0, so 2.0 hostpolicy would not have the exports. In this case, we will
// not propagate the error writer and errors will still be reported to stderr. Callers are
diff --git a/src/installer/corehost/cli/fxr/static/CMakeLists.txt b/src/installer/corehost/cli/fxr/static/CMakeLists.txt
new file mode 100644
index 0000000000000..16c0951c5b21b
--- /dev/null
+++ b/src/installer/corehost/cli/fxr/static/CMakeLists.txt
@@ -0,0 +1,45 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+project(hostfxr_static)
+
+set(DOTNET_PROJECT_NAME "hostfxr_static")
+
+# Include directories
+include_directories(../../json)
+include_directories(../../fxr)
+
+# CMake does not recommend using globbing since it messes with the freshness checks
+set(SOURCES
+ ../command_line.cpp
+ ../corehost_init.cpp
+ ../hostfxr.cpp
+ ../fx_muxer.cpp
+ ../fx_resolver.cpp
+ ../fx_resolver.messages.cpp
+ ../framework_info.cpp
+ ../host_context.cpp
+ ../sdk_info.cpp
+ ../sdk_resolver.cpp
+)
+
+set(HEADERS
+ ../../corehost_context_contract.h
+ ../../hostpolicy.h
+ ../../fx_definition.h
+ ../../fx_reference.h
+ ../../roll_fwd_on_no_candidate_fx_option.h
+ ../command_line.h
+ ../corehost_init.h
+ ../fx_muxer.h
+ ../fx_resolver.h
+ ../framework_info.h
+ ../host_context.h
+ ../sdk_info.h
+ ../sdk_resolver.h
+)
+
+set(SKIP_VERSIONING 1)
+set(BUILD_OBJECT_LIBRARY 1)
+include(../../lib_static.cmake)
diff --git a/src/installer/corehost/cli/hostpolicy/CMakeLists.txt b/src/installer/corehost/cli/hostpolicy/CMakeLists.txt
index ca2c78fa27951..ec7e8e3e2ce4b 100644
--- a/src/installer/corehost/cli/hostpolicy/CMakeLists.txt
+++ b/src/installer/corehost/cli/hostpolicy/CMakeLists.txt
@@ -2,47 +2,5 @@
# The .NET Foundation licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
-project(hostpolicy)
-
-set(DOTNET_PROJECT_NAME "hostpolicy")
-
-# Include directories
-include_directories(../fxr)
-include_directories(../json)
-
-# CMake does not recommend using globbing since it messes with the freshness checks
-set(SOURCES
- ./args.cpp
- ./breadcrumbs.cpp
- ./coreclr.cpp
- ./deps_resolver.cpp
- ./hostpolicy_context.cpp
- ./hostpolicy.cpp
- ./hostpolicy_init.cpp
- ../bundle/dir_utils.cpp
- ../bundle/extractor.cpp
- ../bundle/file_entry.cpp
- ../bundle/manifest.cpp
- ../bundle/runner.cpp
-)
-
-set(HEADERS
- ./args.h
- ./breadcrumbs.h
- ./coreclr.h
- ../corehost_context_contract.h
- ./deps_resolver.h
- ./hostpolicy_context.h
- ../hostpolicy.h
- ./hostpolicy_init.h
- ../bundle/dir_utils.h
- ../bundle/extractor.h
- ../bundle/file_entry.h
- ../bundle/manifest.h
- ../bundle/runner.h
-)
-
-include(../lib.cmake)
-
-install_with_stripped_symbols(hostpolicy TARGETS corehost)
-target_link_libraries(hostpolicy libhostcommon)
+add_subdirectory(static)
+add_subdirectory(standalone)
diff --git a/src/installer/corehost/cli/hostpolicy/standalone/CMakeLists.txt b/src/installer/corehost/cli/hostpolicy/standalone/CMakeLists.txt
new file mode 100644
index 0000000000000..d6631543f81b5
--- /dev/null
+++ b/src/installer/corehost/cli/hostpolicy/standalone/CMakeLists.txt
@@ -0,0 +1,59 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+project(hostpolicy)
+
+set(DOTNET_PROJECT_NAME "hostpolicy")
+
+# CMake does not recommend using globbing since it messes with the freshness checks
+
+# Can't call add_library() without source files. Create an empty .c file,
+# then link with the static library just recently built.
+if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/empty.cpp")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/empty.cpp" "")
+endif ()
+
+set(SOURCES
+ ${CMAKE_CURRENT_BINARY_DIR}/empty.cpp
+)
+
+set(HEADERS
+)
+
+if(CLR_CMAKE_TARGET_WIN32)
+ list(APPEND SOURCES
+ hostpolicy.def)
+else(CLR_CMAKE_TARGET_WIN32)
+ set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hostpolicy_unixexports.src)
+ set(EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/hostpolicy.exports)
+ generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE})
+
+ if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
+ # Add linker exports file option
+ set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE})
+ endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
+
+ if(CLR_CMAKE_HOST_OSX)
+ # Add linker exports file option
+ set(EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${EXPORTS_FILE})
+ endif(CLR_CMAKE_HOST_OSX)
+
+ if(CLR_CMAKE_HOST_SUNOS)
+ # Add linker exports file option
+ set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE})
+ endif(CLR_CMAKE_HOST_SUNOS)
+endif(CLR_CMAKE_TARGET_WIN32)
+
+include(../../lib.cmake)
+
+if(CLR_CMAKE_HOST_UNIX)
+ add_custom_target(hostpolicy_exports DEPENDS ${EXPORTS_FILE})
+ add_dependencies(hostpolicy hostpolicy_exports)
+
+ set_property(TARGET hostpolicy APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION})
+ set_property(TARGET hostpolicy APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE})
+endif(CLR_CMAKE_HOST_UNIX)
+
+install_with_stripped_symbols(hostpolicy TARGETS corehost)
+target_link_libraries(hostpolicy libhostcommon libhostpolicy_static)
diff --git a/src/installer/corehost/cli/hostpolicy/standalone/hostpolicy.def b/src/installer/corehost/cli/hostpolicy/standalone/hostpolicy.def
new file mode 100644
index 0000000000000..af03ab9dca68d
--- /dev/null
+++ b/src/installer/corehost/cli/hostpolicy/standalone/hostpolicy.def
@@ -0,0 +1,12 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+EXPORTS
+ corehost_initialize
+ corehost_load
+ corehost_main
+ corehost_main_with_output_buffer
+ corehost_resolve_component_dependencies
+ corehost_set_error_writer
+ corehost_unload
diff --git a/src/installer/corehost/cli/hostpolicy/standalone/hostpolicy_unixexports.src b/src/installer/corehost/cli/hostpolicy/standalone/hostpolicy_unixexports.src
new file mode 100644
index 0000000000000..98f3e616e9499
--- /dev/null
+++ b/src/installer/corehost/cli/hostpolicy/standalone/hostpolicy_unixexports.src
@@ -0,0 +1,11 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+corehost_initialize
+corehost_load
+corehost_main
+corehost_main_with_output_buffer
+corehost_resolve_component_dependencies
+corehost_set_error_writer
+corehost_unload
diff --git a/src/installer/corehost/cli/hostpolicy/static/CMakeLists.txt b/src/installer/corehost/cli/hostpolicy/static/CMakeLists.txt
new file mode 100644
index 0000000000000..6845e369bdac3
--- /dev/null
+++ b/src/installer/corehost/cli/hostpolicy/static/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+project(hostpolicy_static)
+
+set(DOTNET_PROJECT_NAME "hostpolicy_static")
+
+# Include directories
+include_directories(../../fxr)
+include_directories(../../json)
+
+# CMake does not recommend using globbing since it messes with the freshness checks
+set(SOURCES
+ ../args.cpp
+ ../breadcrumbs.cpp
+ ../coreclr.cpp
+ ../deps_resolver.cpp
+ ../hostpolicy_context.cpp
+ ../hostpolicy.cpp
+ ../hostpolicy_init.cpp
+ ../../bundle/dir_utils.cpp
+ ../../bundle/extractor.cpp
+ ../../bundle/file_entry.cpp
+ ../../bundle/manifest.cpp
+ ../../bundle/runner.cpp
+)
+
+set(HEADERS
+ ../args.h
+ ../breadcrumbs.h
+ ../coreclr.h
+ ../deps_resolver.h
+ ../hostpolicy_context.h
+ ../hostpolicy_init.h
+ ../../hostpolicy.h
+ ../../corehost_context_contract.h
+ ../../bundle/dir_utils.h
+ ../../bundle/extractor.h
+ ../../bundle/file_entry.h
+ ../../bundle/manifest.h
+ ../../bundle/runner.h
+)
+
+set(SKIP_VERSIONING 1)
+set(BUILD_OBJECT_LIBRARY 1)
+include(../../lib_static.cmake)
diff --git a/src/installer/corehost/cli/lib_static.cmake b/src/installer/corehost/cli/lib_static.cmake
index 8135e9c19e0e0..00204df3ce9f4 100644
--- a/src/installer/corehost/cli/lib_static.cmake
+++ b/src/installer/corehost/cli/lib_static.cmake
@@ -10,7 +10,11 @@ add_definitions(-D_NO_ASYNCRTIMP)
add_definitions(-D_NO_PPLXIMP)
add_definitions(-DEXPORT_SHARED_API=1)
-add_library(lib${DOTNET_PROJECT_NAME} STATIC ${SOURCES} ${RESOURCES})
+if (BUILD_OBJECT_LIBRARY)
+ add_library(lib${DOTNET_PROJECT_NAME} OBJECT ${SOURCES} ${RESOURCES})
+else ()
+ add_library(lib${DOTNET_PROJECT_NAME} STATIC ${SOURCES} ${RESOURCES})
+endif ()
set_target_properties(lib${DOTNET_PROJECT_NAME} PROPERTIES MACOSX_RPATH TRUE)
set_target_properties(lib${DOTNET_PROJECT_NAME} PROPERTIES PREFIX "")
diff --git a/src/installer/corehost/corehost.cpp b/src/installer/corehost/corehost.cpp
index 55b8ed629827c..65cfb61f3ac64 100644
--- a/src/installer/corehost/corehost.cpp
+++ b/src/installer/corehost/corehost.cpp
@@ -9,6 +9,7 @@
#include "fx_ver.h"
#include "trace.h"
#include "utils.h"
+#include "hostfxr_resolver_t.h"
#if defined(FEATURE_APPHOST)
#include "bundle_marker.h"
@@ -176,51 +177,41 @@ int exe_start(const int argc, const pal::char_t* argv[])
app_path.append(_X(".dll"));
#endif
- pal::string_t dotnet_root;
- pal::string_t fxr_path;
- if (!fxr_resolver::try_get_path(app_root, &dotnet_root, &fxr_path))
- {
- return StatusCode::CoreHostLibMissingFailure;
- }
+ hostfxr_resolver_t fxr{app_root};
- // Load library
- pal::dll_t fxr;
- if (!pal::load_library(&fxr_path, &fxr))
+ // Obtain the entrypoints.
+ int rc = fxr.status_code();
+ if (rc != StatusCode::Success)
{
- trace::error(_X("The library %s was found, but loading it from %s failed"), LIBFXR_NAME, fxr_path.c_str());
- trace::error(_X(" - Installing .NET prerequisites might help resolve this problem."));
- trace::error(_X(" %s"), DOTNET_CORE_INSTALL_PREREQUISITES_URL);
- return StatusCode::CoreHostLibLoadFailure;
+ return rc;
}
- // Obtain the entrypoints.
- int rc;
#if defined(FEATURE_APPHOST)
if (bundle_marker_t::is_bundle())
{
- hostfxr_main_bundle_startupinfo_fn hostfxr_main_bundle_startupinfo = reinterpret_cast(pal::get_symbol(fxr, "hostfxr_main_bundle_startupinfo"));
+ auto hostfxr_main_bundle_startupinfo = fxr.resolve_main_bundle_startupinfo();
if (hostfxr_main_bundle_startupinfo != nullptr)
{
const pal::char_t* host_path_cstr = host_path.c_str();
- const pal::char_t* dotnet_root_cstr = dotnet_root.empty() ? nullptr : dotnet_root.c_str();
+ const pal::char_t* dotnet_root_cstr = fxr.dotnet_root().empty() ? nullptr : fxr.dotnet_root().c_str();
const pal::char_t* app_path_cstr = app_path.empty() ? nullptr : app_path.c_str();
int64_t bundle_header_offset = bundle_marker_t::header_offset();
- trace::info(_X("Invoking fx resolver [%s] hostfxr_main_bundle_startupinfo"), fxr_path.c_str());
+ trace::info(_X("Invoking fx resolver [%s] hostfxr_main_bundle_startupinfo"), fxr.fxr_path().c_str());
trace::info(_X("Host path: [%s]"), host_path.c_str());
- trace::info(_X("Dotnet path: [%s]"), dotnet_root.c_str());
+ trace::info(_X("Dotnet path: [%s]"), fxr.dotnet_root().c_str());
trace::info(_X("App path: [%s]"), app_path.c_str());
trace::info(_X("Bundle Header Offset: [%lx]"), bundle_header_offset);
- hostfxr_set_error_writer_fn set_error_writer_fn = reinterpret_cast(pal::get_symbol(fxr, "hostfxr_set_error_writer"));
- propagate_error_writer_t propagate_error_writer_to_hostfxr(set_error_writer_fn);
+ auto set_error_writer = fxr.resolve_set_error_writer();
+ propagate_error_writer_t propagate_error_writer_to_hostfxr(set_error_writer);
rc = hostfxr_main_bundle_startupinfo(argc, argv, host_path_cstr, dotnet_root_cstr, app_path_cstr, bundle_header_offset);
}
else
{
// The host components will be statically linked with the app-host: https://github.com/dotnet/runtime/issues/32823
// Once this work is completed, an outdated hostfxr can only be found for framework-related apps.
- trace::error(_X("The required library %s does not support single-file apps."), fxr_path.c_str());
+ trace::error(_X("The required library %s does not support single-file apps."), fxr.fxr_path().c_str());
need_newer_framework_error();
rc = StatusCode::FrameworkMissingFailure;
}
@@ -228,60 +219,61 @@ int exe_start(const int argc, const pal::char_t* argv[])
else
#endif // defined(FEATURE_APPHOST)
{
- hostfxr_main_startupinfo_fn hostfxr_main_startupinfo = reinterpret_cast(pal::get_symbol(fxr, "hostfxr_main_startupinfo"));
+ auto hostfxr_main_startupinfo = fxr.resolve_main_startupinfo();
if (hostfxr_main_startupinfo != nullptr)
{
const pal::char_t* host_path_cstr = host_path.c_str();
- const pal::char_t* dotnet_root_cstr = dotnet_root.empty() ? nullptr : dotnet_root.c_str();
+ const pal::char_t* dotnet_root_cstr = fxr.dotnet_root().empty() ? nullptr : fxr.dotnet_root().c_str();
const pal::char_t* app_path_cstr = app_path.empty() ? nullptr : app_path.c_str();
- trace::info(_X("Invoking fx resolver [%s] hostfxr_main_startupinfo"), fxr_path.c_str());
+ trace::info(_X("Invoking fx resolver [%s] hostfxr_main_startupinfo"), fxr.fxr_path().c_str());
trace::info(_X("Host path: [%s]"), host_path.c_str());
- trace::info(_X("Dotnet path: [%s]"), dotnet_root.c_str());
+ trace::info(_X("Dotnet path: [%s]"), fxr.dotnet_root().c_str());
trace::info(_X("App path: [%s]"), app_path.c_str());
- hostfxr_set_error_writer_fn set_error_writer_fn = reinterpret_cast(pal::get_symbol(fxr, "hostfxr_set_error_writer"));
- propagate_error_writer_t propagate_error_writer_to_hostfxr(set_error_writer_fn);
+ auto set_error_writer = fxr.resolve_set_error_writer();
+ propagate_error_writer_t propagate_error_writer_to_hostfxr(set_error_writer);
rc = hostfxr_main_startupinfo(argc, argv, host_path_cstr, dotnet_root_cstr, app_path_cstr);
// This check exists to provide an error message for UI apps when running 3.0 apps on 2.0 only hostfxr, which doesn't support error writer redirection.
- if (trace::get_error_writer() != nullptr && rc == static_cast(StatusCode::FrameworkMissingFailure) && !set_error_writer_fn)
+ if (trace::get_error_writer() != nullptr && rc == static_cast(StatusCode::FrameworkMissingFailure) && set_error_writer == nullptr)
{
need_newer_framework_error();
}
}
+#if !defined(FEATURE_STATIC_HOST)
else
{
if (requires_hostfxr_startupinfo_interface)
{
- trace::error(_X("The required library %s does not support relative app dll paths."), fxr_path.c_str());
+ trace::error(_X("The required library %s does not support relative app dll paths."), fxr.fxr_path().c_str());
rc = StatusCode::CoreHostEntryPointFailure;
}
else
{
- trace::info(_X("Invoking fx resolver [%s] v1"), fxr_path.c_str());
+ trace::info(_X("Invoking fx resolver [%s] v1"), fxr.fxr_path().c_str());
// Previous corehost trace messages must be printed before calling trace::setup in hostfxr
trace::flush();
// For compat, use the v1 interface. This requires additional file I\O to re-parse parameters and
// for apphost, does not support DOTNET_ROOT or dll with different name for exe.
- hostfxr_main_fn main_fn_v1 = reinterpret_cast(pal::get_symbol(fxr, "hostfxr_main"));
+ auto main_fn_v1 = fxr.resolve_main_v1();
if (main_fn_v1 != nullptr)
{
rc = main_fn_v1(argc, argv);
}
else
{
- trace::error(_X("The required library %s does not contain the expected entry point."), fxr_path.c_str());
+ trace::error(_X("The required library %s does not contain the expected entry point."), fxr.fxr_path().c_str());
rc = StatusCode::CoreHostEntryPointFailure;
}
}
}
+#endif // defined(FEATURE_STATIC_HOST)
}
- pal::unload_library(fxr);
return rc;
}
diff --git a/src/installer/corehost/hostfxr_resolver_t.h b/src/installer/corehost/hostfxr_resolver_t.h
new file mode 100644
index 0000000000000..21047b56a3c89
--- /dev/null
+++ b/src/installer/corehost/hostfxr_resolver_t.h
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#ifndef __HOSTFXR_RESOLVER_T_H__
+#define __HOSTFXR_RESOLVER_T_H__
+
+#include "hostfxr.h"
+#include "pal.h"
+#include "error_codes.h"
+
+class hostfxr_resolver_t
+{
+ public:
+ hostfxr_resolver_t(const pal::string_t& app_root);
+ ~hostfxr_resolver_t();
+
+ StatusCode status_code() const { return m_status_code; }
+
+ const pal::string_t& host_path() const { return m_host_path; }
+ const pal::string_t& dotnet_root() const { return m_dotnet_root; }
+ const pal::string_t& fxr_path() const { return m_fxr_path; }
+
+ hostfxr_main_bundle_startupinfo_fn resolve_main_bundle_startupinfo();
+ hostfxr_set_error_writer_fn resolve_set_error_writer();
+ hostfxr_main_startupinfo_fn resolve_main_startupinfo();
+ hostfxr_main_fn resolve_main_v1();
+
+ private:
+ pal::dll_t m_hostfxr_dll{nullptr};
+
+ pal::string_t m_host_path;
+ pal::string_t m_dotnet_root;
+ pal::string_t m_fxr_path;
+
+ bool m_requires_startupinfo_iface{false};
+ StatusCode m_status_code;
+};
+
+#endif // __HOSTFXR_RESOLVER_T_H__
diff --git a/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/runtime.Windows_NT.Microsoft.NETCore.DotNetAppHost.props b/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/runtime.Windows_NT.Microsoft.NETCore.DotNetAppHost.props
index c74da91a0f25c..6d52e1984f8ce 100644
--- a/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/runtime.Windows_NT.Microsoft.NETCore.DotNetAppHost.props
+++ b/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/runtime.Windows_NT.Microsoft.NETCore.DotNetAppHost.props
@@ -2,6 +2,7 @@
+
diff --git a/src/installer/pkg/projects/netcoreapp/pkg/Microsoft.NETCore.App.Host.pkgproj b/src/installer/pkg/projects/netcoreapp/pkg/Microsoft.NETCore.App.Host.pkgproj
index 10915e8d504d4..8daa78d3ec711 100644
--- a/src/installer/pkg/projects/netcoreapp/pkg/Microsoft.NETCore.App.Host.pkgproj
+++ b/src/installer/pkg/projects/netcoreapp/pkg/Microsoft.NETCore.App.Host.pkgproj
@@ -15,6 +15,7 @@
-->
+
@@ -29,4 +30,4 @@
true
-
\ No newline at end of file
+
diff --git a/src/installer/test/Assets/TestProjects/StaticHostApp/Program.cs b/src/installer/test/Assets/TestProjects/StaticHostApp/Program.cs
new file mode 100644
index 0000000000000..c631d81d54048
--- /dev/null
+++ b/src/installer/test/Assets/TestProjects/StaticHostApp/Program.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace StaticHostApp
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Hello World!");
+ }
+ }
+}
diff --git a/src/installer/test/Assets/TestProjects/StaticHostApp/StaticHostApp.csproj b/src/installer/test/Assets/TestProjects/StaticHostApp/StaticHostApp.csproj
new file mode 100644
index 0000000000000..eff31e8532b40
--- /dev/null
+++ b/src/installer/test/Assets/TestProjects/StaticHostApp/StaticHostApp.csproj
@@ -0,0 +1,13 @@
+
+
+
+ $(NETCoreAppFramework)
+ Exe
+ $(TestTargetRid)
+ $(MNAVersion)
+
+
+
+
+
+
diff --git a/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/StaticHost.cs b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/StaticHost.cs
new file mode 100644
index 0000000000000..78b5c9449fe1b
--- /dev/null
+++ b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/StaticHost.cs
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using BundleTests.Helpers;
+using Microsoft.DotNet.Cli.Build.Framework;
+using Microsoft.DotNet.CoreSetup.Test;
+using Microsoft.NET.HostModel.AppHost;
+using Microsoft.NET.HostModel.Bundle;
+using System;
+using System.IO;
+using System.Threading;
+using Xunit;
+
+namespace AppHost.Bundle.Tests
+{
+ public class StaticHost : IClassFixture
+ {
+ private SharedTestState sharedTestState;
+
+ public StaticHost(SharedTestState fixture)
+ {
+ sharedTestState = fixture;
+ }
+
+ // This helper is used in lieu of SDK support for publishing apps using the singlefilehost.
+ // It replaces the apphost with singlefilehost, and along with appropriate app.dll updates in the host.
+ // For now, we leave behind the hostpolicy and hostfxr DLLs in the publish directory, because
+ // removing them requires deps.json update.
+ void ReplaceApphostWithStaticHost(TestProjectFixture fixture)
+ {
+ var staticHost = Path.Combine(fixture.RepoDirProvider.HostArtifacts,
+ RuntimeInformationExtensions.GetExeFileNameForCurrentPlatform("singlefilehost"));
+ HostWriter.CreateAppHost(staticHost,
+ BundleHelper.GetHostPath(fixture),
+ BundleHelper.GetAppPath(fixture));
+
+ }
+
+ [Fact]
+ private void Can_Run_App_With_StatiHost()
+ {
+ var fixture = sharedTestState.TestFixture.Copy();
+ var appExe = BundleHelper.GetHostPath(fixture);
+
+ ReplaceApphostWithStaticHost(fixture);
+
+ Command.Create(appExe)
+ .CaptureStdErr()
+ .CaptureStdOut()
+ .Execute()
+ .Should()
+ .Pass()
+ .And
+ .HaveStdOutContaining("Hello World");
+ }
+
+ [Fact]
+ private void Can_Run_SingleFile_App_With_StatiHost()
+ {
+ var fixture = sharedTestState.TestFixture.Copy();
+
+ ReplaceApphostWithStaticHost(fixture);
+
+ string singleFile = BundleHelper.BundleApp(fixture);
+
+ Command.Create(singleFile)
+ .CaptureStdErr()
+ .CaptureStdOut()
+ .Execute()
+ .Should()
+ .Pass()
+ .And
+ .HaveStdOutContaining("Hello World");
+ }
+
+ public class SharedTestState : IDisposable
+ {
+ public TestProjectFixture TestFixture { get; set; }
+ public RepoDirectoriesProvider RepoDirectories { get; set; }
+
+ public SharedTestState()
+ {
+ RepoDirectories = new RepoDirectoriesProvider();
+ TestFixture = new TestProjectFixture("StaticHostApp", RepoDirectories);
+ TestFixture
+ .EnsureRestoredForRid(TestFixture.CurrentRid, RepoDirectories.CorehostPackages)
+ .PublishProject(runtime: TestFixture.CurrentRid,
+ outputDirectory: BundleHelper.GetPublishPath(TestFixture));
+ }
+
+ public void Dispose()
+ {
+ TestFixture.Dispose();
+ }
+ }
+ }
+}