Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Sadov <vsadov@microsoft.com>2020-05-06 04:05:50 +0300
committerGitHub <noreply@github.com>2020-05-06 04:05:50 +0300
commitf6e5219b13f4bb9d6c1c9f80fd6ca6c594c6c7f8 (patch)
treef7c07a41edfbcf6fc4315dd15ff15d31a37e2c93
parentd70a2a62092f0ac86a574be81274dc50e0cbf62f (diff)
Build an apphost with hostfxr and hostpolicy linked in (#35368)
* hostfxr: Build most of hostfxr as a static library This is part of the work to create an apphost that bundles both hostfxr and hostpolicy. The main distinction between the static and shared versions of hostfxr is that the static version contains a hostpolicy resolver that references the hostpolicy symbols directly rather than loading them from a DLL. * hostpolicy: Build as a static library This change is part of the work to enable an apphost that bundles both hostfxr and hostpolicy. There's no distinction between hostpolicy that's built as a shared library and as a static library: the shared library is built by linking an empty object file with the static library. * corehost: Allow linking of hostfxr and hostpolicy with apphost Provide a hostfxr_iface class, that abstracts how the hostfxr functions called by the early stage in the hosting layer is resolved. * dotnet: Teach the muxer binary about hostfxr_iface * apphost: Teach apphost about hostfxr_iface This provides two implementations of hostfxr_iface: one for the static apphost, which bundles hostfxr and hostpolicy, and another for the conventional apphost, which loads them dynamically on startup. * Add exports for hostfxr and policy * Exports for unix * EXPORTS_LINKER_OPTION * use generateversionscript.awk from ENG * Move fxr files out of static * Fixes for Linux * Fix for win-x86 * move HEADERS next to SOURCES similarly to other files. * PR feedback (simplifying hostpolicy_resolver::try_get_dir for static host) * Publish static_apphost to Microsoft.NETCore.App.Host * bind to entry points without probing, when in a static host. * Add a test case * renamed hostfxr_iface --> hostfxr_resolver_t * renamed shared --> standalone * rename static_apphost --> singlefilehost * Signing exclusions for singlefilehost * switched StaticHost tst to a different asset (mostly a copy of StandaloneApp) Co-authored-by: Leandro Pereira <leandro.pereira@microsoft.com> Co-authored-by: Swaroop Sridhar <swaroop.sridhar@microsoft.com>
-rw-r--r--eng/SignCheckExclusionsFile.txt1
-rw-r--r--eng/Signing.props2
-rw-r--r--eng/native/functions.cmake8
-rw-r--r--eng/native/generateexportedsymbols.awk (renamed from src/coreclr/generateexportedsymbols.awk)0
-rw-r--r--eng/native/generateversionscript.awk (renamed from src/coreclr/generateversionscript.awk)0
-rw-r--r--src/installer/corehost/cli/CMakeLists.txt4
-rw-r--r--src/installer/corehost/cli/apphost/CMakeLists.txt48
-rw-r--r--src/installer/corehost/cli/apphost/standalone/CMakeLists.txt54
-rw-r--r--src/installer/corehost/cli/apphost/standalone/hostfxr_resolver_t.cpp61
-rw-r--r--src/installer/corehost/cli/apphost/static/CMakeLists.txt63
-rw-r--r--src/installer/corehost/cli/apphost/static/hostfxr_resolver_t.cpp63
-rw-r--r--src/installer/corehost/cli/apphost/static/hostpolicy_resolver.cpp59
-rw-r--r--src/installer/corehost/cli/dotnet/CMakeLists.txt4
-rw-r--r--src/installer/corehost/cli/exe.cmake3
-rw-r--r--src/installer/corehost/cli/fxr/CMakeLists.txt45
-rw-r--r--src/installer/corehost/cli/fxr/fx_muxer.cpp40
-rw-r--r--src/installer/corehost/cli/fxr/hostpolicy_resolver.h6
-rw-r--r--src/installer/corehost/cli/fxr/standalone/CMakeLists.txt65
-rw-r--r--src/installer/corehost/cli/fxr/standalone/hostfxr.def21
-rw-r--r--src/installer/corehost/cli/fxr/standalone/hostfxr_unixexports.src20
-rw-r--r--src/installer/corehost/cli/fxr/standalone/hostpolicy_resolver.cpp (renamed from src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp)3
-rw-r--r--src/installer/corehost/cli/fxr/static/CMakeLists.txt45
-rw-r--r--src/installer/corehost/cli/hostpolicy/CMakeLists.txt46
-rw-r--r--src/installer/corehost/cli/hostpolicy/standalone/CMakeLists.txt59
-rw-r--r--src/installer/corehost/cli/hostpolicy/standalone/hostpolicy.def12
-rw-r--r--src/installer/corehost/cli/hostpolicy/standalone/hostpolicy_unixexports.src11
-rw-r--r--src/installer/corehost/cli/hostpolicy/static/CMakeLists.txt47
-rw-r--r--src/installer/corehost/cli/lib_static.cmake6
-rw-r--r--src/installer/corehost/corehost.cpp60
-rw-r--r--src/installer/corehost/hostfxr_resolver_t.h40
-rw-r--r--src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/runtime.Windows_NT.Microsoft.NETCore.DotNetAppHost.props1
-rw-r--r--src/installer/pkg/projects/netcoreapp/pkg/Microsoft.NETCore.App.Host.pkgproj3
-rw-r--r--src/installer/test/Assets/TestProjects/StaticHostApp/Program.cs16
-rw-r--r--src/installer/test/Assets/TestProjects/StaticHostApp/StaticHostApp.csproj13
-rw-r--r--src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/StaticHost.cs98
35 files changed, 836 insertions, 191 deletions
diff --git a/eng/SignCheckExclusionsFile.txt b/eng/SignCheckExclusionsFile.txt
index 2db3b79a933..a78ad401525 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 05f2a8bcb39..5ceb96ac54b 100644
--- a/eng/Signing.props
+++ b/eng/Signing.props
@@ -24,7 +24,7 @@
<BundleInstallerExeArtifact Include="$(ArtifactsPackagesDir)**/*.exe" />
<!-- apphost and comhost template files are not signed, by design. -->
- <FileSignInfo Include="apphost.exe;comhost.dll" CertificateName="None" />
+ <FileSignInfo Include="apphost.exe;singlefilehost.exe;comhost.dll" CertificateName="None" />
</ItemGroup>
<ItemGroup Condition="'$(CrossTargetComponentFolder)' != ''">
diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake
index 060cff8987e..49b0064499e 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
index 69a8a8e6df5..69a8a8e6df5 100644
--- a/src/coreclr/generateexportedsymbols.awk
+++ b/eng/native/generateexportedsymbols.awk
diff --git a/src/coreclr/generateversionscript.awk b/eng/native/generateversionscript.awk
index 7efc537325a..7efc537325a 100644
--- a/src/coreclr/generateversionscript.awk
+++ b/eng/native/generateversionscript.awk
diff --git a/src/installer/corehost/cli/CMakeLists.txt b/src/installer/corehost/cli/CMakeLists.txt
index 15ce0fa1177..3c1bdb1f2f0 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 ba01e32ec47..ec7e8e3e2ce 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 00000000000..60d9a103b12
--- /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 00000000000..4f3c3888428
--- /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 <assert.h>
+
+#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<hostfxr_main_bundle_startupinfo_fn>(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<hostfxr_set_error_writer_fn>(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<hostfxr_main_startupinfo_fn>(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<hostfxr_main_fn>(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 00000000000..967aebb2413
--- /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 00000000000..2c7e2b87a5f
--- /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 <assert.h>
+#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 00000000000..0b2a35639a2
--- /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 <cassert>
+#include <error_codes.h>
+#include <fx_definition.h>
+#include "hostpolicy_resolver.h"
+#include <pal.h>
+#include <trace.h>
+
+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<pal::string_t>& 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 4527986acfe..798ae4030ea 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 c9295d5c65f..3acc130174a 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 216ecbf076b..ec7e8e3e2ce 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 31c8c177978..f41e9095ef0 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<typename T>
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<T>(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 4348a53c778..35128327b7b 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 00000000000..0a2ea92174b
--- /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 00000000000..c86139a7fb5
--- /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 00000000000..fcf85d027fa
--- /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
index de3291fecc5..67881d20794 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<corehost_set_error_writer_fn>(pal::get_symbol(g_hostpolicy, "corehost_set_error_writer"));
g_hostpolicy_contract.initialize = reinterpret_cast<corehost_initialize_fn>(pal::get_symbol(g_hostpolicy, "corehost_initialize"));
+ g_hostpolicy_contract.corehost_main = reinterpret_cast<corehost_main_fn>(pal::get_symbol(g_hostpolicy, "corehost_main"));
+ g_hostpolicy_contract.corehost_main_with_output_buffer = reinterpret_cast<corehost_main_with_output_buffer_fn>(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 00000000000..16c0951c5b2
--- /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 ca2c78fa279..ec7e8e3e2ce 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 00000000000..d6631543f81
--- /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 00000000000..af03ab9dca6
--- /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 00000000000..98f3e616e94
--- /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 00000000000..6845e369bda
--- /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 8135e9c19e0..00204df3ce9 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 55b8ed62982..65cfb61f3ac 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<hostfxr_main_bundle_startupinfo_fn>(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<hostfxr_set_error_writer_fn>(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<hostfxr_main_startupinfo_fn>(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<hostfxr_set_error_writer_fn>(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<int>(StatusCode::FrameworkMissingFailure) && !set_error_writer_fn)
+ if (trace::get_error_writer() != nullptr && rc == static_cast<int>(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<hostfxr_main_fn>(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 00000000000..21047b56a3c
--- /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 c74da91a0f2..6d52e1984f8 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 @@
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ArchitectureSpecificNativeFile Include="$(DotNetHostBinDir)/apphost.exe" />
+ <ArchitectureSpecificNativeFile Include="$(DotNetHostBinDir)/singlefilehost.exe" />
<ArchitectureSpecificNativeFile Include="$(DotNetHostBinDir)/comhost.dll" />
<ArchitectureSpecificNativeFile Include="$(DotNetHostBinDir)/ijwhost.dll" />
<ArchitectureSpecificNativeFile Include="$(DotNetHostBinDir)/ijwhost.lib" />
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 10915e8d504..8daa78d3ec7 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 @@
-->
<ItemGroup>
<HeatOutputFileElementToStabilize Include="native\apphost.exe" ReplacementId="apphosttemplateapphostexe" />
+ <HeatOutputFileElementToStabilize Include="native\singlefilehost.exe" ReplacementId="staticapphosttemplateapphostexe" />
<HeatOutputFileElementToStabilize Include="native\comhost.dll" ReplacementId="comhosttemplatecomhostdll" />
</ItemGroup>
@@ -29,4 +30,4 @@
<PropertyGroup>
<SkipBuildOnRuntimePackOnlyOS>true</SkipBuildOnRuntimePackOnlyOS>
</PropertyGroup>
-</Project> \ No newline at end of file
+</Project>
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 00000000000..c631d81d540
--- /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 00000000000..eff31e8532b
--- /dev/null
+++ b/src/installer/test/Assets/TestProjects/StaticHostApp/StaticHostApp.csproj
@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>$(NETCoreAppFramework)</TargetFramework>
+ <OutputType>Exe</OutputType>
+ <RuntimeIdentifier>$(TestTargetRid)</RuntimeIdentifier>
+ <RuntimeFrameworkVersion>$(MNAVersion)</RuntimeFrameworkVersion>
+ </PropertyGroup>
+
+ <ItemGroup>
+ </ItemGroup>
+
+</Project>
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 00000000000..78b5c9449fe
--- /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<StaticHost.SharedTestState>
+ {
+ 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();
+ }
+ }
+ }
+}