Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Add support for framework-dependent apphost #3888

Merged
merged 3 commits into from
Mar 27, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 12 additions & 39 deletions src/corehost/cli/args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

arguments_t::arguments_t() :
managed_application(_X("")),
own_path(_X("")),
app_dir(_X("")),
host_path(_X("")),
app_root(_X("")),
app_argc(0),
app_argv(nullptr),
core_servicing(_X("")),
Expand Down Expand Up @@ -62,34 +62,11 @@ bool parse_arguments(
{
arguments_t& args = *arg_out;

// Try to use argv[0] as own_path to allow for hosts located elsewhere
if (argc >= 1)
{
args.own_path = argv[0];
if (!args.own_path.empty())
{
trace::info(_X("Attempting to use argv[0] as path [%s]"), args.own_path.c_str());
if (!get_path_from_argv(&args.own_path))
{
trace::warning(_X("Failed to resolve argv[0] as path [%s]. Using location of current executable instead."), args.own_path.c_str());
args.own_path.clear();
}
}
}
args.host_path = init.host_info.host_path;

// Get the full name of the application
if (args.own_path.empty() && (!pal::get_own_executable_path(&args.own_path) || !pal::realpath(&args.own_path)))
if (init.host_mode != host_mode_t::apphost)
{
trace::error(_X("Failed to resolve full path of the current executable [%s]"), args.own_path.c_str());
return false;
}

auto own_name = get_filename(args.own_path);
auto own_dir = get_directory(args.own_path);

if (init.host_mode != host_mode_t::standalone)
{
// corerun mode. First argument is managed app
// First argument is managed app
if (argc < 2)
{
return false;
Expand All @@ -100,32 +77,28 @@ bool parse_arguments(
trace::error(_X("Failed to locate managed application [%s]"), args.managed_application.c_str());
return false;
}
args.app_dir = get_directory(args.managed_application);
args.app_root = get_directory(args.managed_application);
args.app_argc = argc - 2;
args.app_argv = &argv[2];
}
else
{
// coreconsole mode. Find the managed app in the same directory
pal::string_t managed_app(own_dir);

managed_app.append(get_executable(own_name));
managed_app.append(_X(".dll"));
args.managed_application = managed_app;
// Find the managed app in the same directory
args.managed_application = init.host_info.app_path;
if (!pal::realpath(&args.managed_application))
{
trace::error(_X("Failed to locate managed application [%s]"), args.managed_application.c_str());
return false;
}
args.app_dir = own_dir;
args.app_root = init.host_info.dotnet_root;
args.app_argv = &argv[1];
args.app_argc = argc - 1;
}

if (!init.deps_file.empty())
{
args.deps_path = init.deps_file;
args.app_dir = get_directory(args.deps_path);
args.app_root = get_directory(args.deps_path);
}

for (const auto& probe : init.probe_paths)
Expand All @@ -135,7 +108,7 @@ bool parse_arguments(

if (args.deps_path.empty())
{
const auto& app_base = args.app_dir;
const auto& app_base = args.app_root;
auto app_name = get_filename(args.managed_application);

args.deps_path.reserve(app_base.length() + 1 + app_name.length() + 5);
Expand All @@ -151,7 +124,7 @@ bool parse_arguments(

pal::get_default_servicing_directory(&args.core_servicing);

setup_shared_store_paths(init, own_dir, &args);
setup_shared_store_paths(init, get_directory(args.host_path), &args);

return true;
}
8 changes: 4 additions & 4 deletions src/corehost/cli/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ struct probe_config_t

struct arguments_t
{
pal::string_t own_path;
pal::string_t app_dir;
pal::string_t host_path;
pal::string_t app_root;
pal::string_t deps_path;
pal::string_t core_servicing;
std::vector<pal::string_t> probe_paths;
Expand All @@ -108,8 +108,8 @@ struct arguments_t
{
if (trace::is_enabled())
{
trace::verbose(_X("-- arguments_t: own_path='%s' app_dir='%s' deps='%s' core_svc='%s' mgd_app='%s'"),
own_path.c_str(), app_dir.c_str(), deps_path.c_str(), core_servicing.c_str(), managed_application.c_str());
trace::verbose(_X("-- arguments_t: host_path='%s' app_root='%s' deps='%s' core_svc='%s' mgd_app='%s'"),
host_path.c_str(), app_root.c_str(), deps_path.c_str(), core_servicing.c_str(), managed_application.c_str());
for (const auto& probe : probe_paths)
{
trace::verbose(_X("-- arguments_t: probe dir: '%s'"), probe.c_str());
Expand Down
10 changes: 5 additions & 5 deletions src/corehost/cli/deps_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ bool deps_json_t::process_targets(const json_value& json, const pal::string_t& t
return true;
}

bool deps_json_t::load_portable(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name, const rid_fallback_graph_t& rid_fallback_graph)
bool deps_json_t::load_framework_dependent(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name, const rid_fallback_graph_t& rid_fallback_graph)
{
if (!process_runtime_targets(json, target_name, rid_fallback_graph, &m_rid_assets))
{
Expand Down Expand Up @@ -367,7 +367,7 @@ bool deps_json_t::load_portable(const pal::string_t& deps_path, const json_value
return true;
}

bool deps_json_t::load_standalone(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name)
bool deps_json_t::load_self_contained(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name)
{
if (!process_targets(json, target_name, &m_assets))
{
Expand Down Expand Up @@ -438,7 +438,7 @@ bool deps_json_t::has_package(const pal::string_t& name, const pal::string_t& ve
// Load the deps file and parse its "entry" lines which contain the "fields" of
// the entry. Populate an array of these entries.
//
bool deps_json_t::load(bool portable, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph)
bool deps_json_t::load(bool is_framework_dependent, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph)
{
m_deps_file = deps_path;
m_file_exists = pal::file_exists(deps_path);
Expand Down Expand Up @@ -473,9 +473,9 @@ bool deps_json_t::load(bool portable, const pal::string_t& deps_path, const rid_
runtime_target.as_string():
runtime_target.at(_X("name")).as_string();

trace::verbose(_X("Loading deps file... %s as portable=[%d]"), deps_path.c_str(), portable);
trace::verbose(_X("Loading deps file... %s as framework dependent=[%d]"), deps_path.c_str(), is_framework_dependent);

return (portable) ? load_portable(deps_path, json, name, rid_fallback_graph) : load_standalone(deps_path, json, name);
return (is_framework_dependent) ? load_framework_dependent(deps_path, json, name, rid_fallback_graph) : load_self_contained(deps_path, json, name);
}
catch (const std::exception& je)
{
Expand Down
22 changes: 11 additions & 11 deletions src/corehost/cli/deps_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,25 @@ class deps_json_t
{
}

deps_json_t(bool portable, const pal::string_t& deps_path)
: deps_json_t(portable, deps_path, m_rid_fallback_graph /* dummy */)
deps_json_t(bool is_framework_dependent, const pal::string_t& deps_path)
: deps_json_t(is_framework_dependent, deps_path, m_rid_fallback_graph /* dummy */)
{
}

deps_json_t(bool portable, const pal::string_t& deps_path, const rid_fallback_graph_t& graph)
deps_json_t(bool is_framework_dependent, const pal::string_t& deps_path, const rid_fallback_graph_t& graph)
: deps_json_t()
{
m_valid = load(portable, deps_path, graph);
m_valid = load(is_framework_dependent, deps_path, graph);
}

void parse(bool portable, const pal::string_t& deps_path)
void parse(bool is_framework_dependent, const pal::string_t& deps_path)
{
m_valid = load(portable, deps_path, m_rid_fallback_graph /* dummy */);
m_valid = load(is_framework_dependent, deps_path, m_rid_fallback_graph /* dummy */);
}

void parse(bool portable, const pal::string_t& deps_path, const rid_fallback_graph_t& graph)
void parse(bool is_framework_dependent, const pal::string_t& deps_path, const rid_fallback_graph_t& graph)
{
m_valid = load(portable, deps_path, graph);
m_valid = load(is_framework_dependent, deps_path, graph);
}

const std::vector<deps_entry_t>& get_entries(deps_entry_t::asset_types type) const
Expand Down Expand Up @@ -85,9 +85,9 @@ class deps_json_t
}

private:
bool load_standalone(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name);
bool load_portable(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name, const rid_fallback_graph_t& rid_fallback_graph);
bool load(bool portable, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph);
bool load_self_contained(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name);
bool load_framework_dependent(const pal::string_t& deps_path, const json_value& json, const pal::string_t& target_name, const rid_fallback_graph_t& rid_fallback_graph);
bool load(bool is_framework_dependent, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph);
bool process_runtime_targets(const json_value& json, const pal::string_t& target_name, const rid_fallback_graph_t& rid_fallback_graph, rid_specific_assets_t* p_assets);
bool process_targets(const json_value& json, const pal::string_t& target_name, deps_assets_t* p_assets);

Expand Down
14 changes: 7 additions & 7 deletions src/corehost/cli/deps_resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ bool deps_resolver_t::resolve_tpa_list(
// A minor\major roll-forward affects which layer wins
bool is_minor_or_major_roll_forward = m_fx_definitions[i]->did_minor_or_major_roll_forward_occur();

const auto& deps_entries = m_portable ? m_fx_definitions[i]->get_deps().get_entries(deps_entry_t::asset_types::runtime) : empty;
const auto& deps_entries = m_is_framework_dependent ? m_fx_definitions[i]->get_deps().get_entries(deps_entry_t::asset_types::runtime) : empty;
for (const auto& entry : deps_entries)
{
if (!process_entry(m_fx_definitions[i]->get_dir(), entry, i, is_minor_or_major_roll_forward))
Expand Down Expand Up @@ -588,12 +588,12 @@ void deps_resolver_t::init_known_entry_path(const deps_entry_t& entry, const pal

void deps_resolver_t::resolve_additional_deps(const hostpolicy_init_t& init)
{
if (!m_portable)
if (!m_is_framework_dependent)
{
// Additional deps.json support is only available for portable apps due to the following constraints:
// Additional deps.json support is only available for framework-dependent apps due to the following constraints:
//
// 1) Unlike Portable Apps, Standalone apps do not have details of the SharedFX and Version they target.
// 2) Unlike Portable Apps, Standalone apps do not have RID fallback graph that is required for looking up
// 1) Unlike framework-dependent Apps, self-contained apps do not have details of the SharedFX and Version they target.
// 2) Unlike framework-dependent Apps, self-contained apps do not have RID fallback graph that is required for looking up
// the correct native assets from nuget packages.

return;
Expand Down Expand Up @@ -727,7 +727,7 @@ bool deps_resolver_t::resolve_probe_dirs(
}
else
{
// For standalone apps, apphost.exe will be renamed. Do not use the full package name
// For self-contained apps do not use the full package name
// because of rid-fallback could happen (ex: CentOS falling back to RHEL)
if ((entry.asset.name == _X("apphost")) && ends_with(entry.library_name, _X(".Microsoft.NETCore.DotNetAppHost"), false))
{
Expand Down Expand Up @@ -797,7 +797,7 @@ bool deps_resolver_t::resolve_probe_dirs(
// Entrypoint to resolve TPA, native and resources path ordering to pass to CoreCLR.
//
// Parameters:
// app_dir - The application local directory
// app_root - The application local directory
// package_dir - The directory path to where packages are restored
// package_cache_dir - The directory path to secondary cache for packages
// clr_dir - The directory where the host loads the CLR
Expand Down
8 changes: 4 additions & 4 deletions src/corehost/cli/deps_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ class deps_resolver_t
public:
deps_resolver_t(hostpolicy_init_t& init, const arguments_t& args)
: m_fx_definitions(init.fx_definitions)
, m_app_dir(args.app_dir)
, m_app_dir(args.app_root)
, m_managed_app(args.managed_application)
, m_portable(init.is_portable)
, m_is_framework_dependent(init.is_framework_dependent)
, m_core_servicing(args.core_servicing)
{
int root_framework = m_fx_definitions.size() - 1;
Expand Down Expand Up @@ -218,8 +218,8 @@ class deps_resolver_t
// Fallback probe dir
std::vector<pal::string_t> m_additional_probes;

// Is the deps file portable app?
bool m_portable;
// Is the deps file for an app using shared frameworks?
bool m_is_framework_dependent;
};

#endif // DEPS_RESOLVER_H
1 change: 1 addition & 0 deletions src/corehost/cli/dll/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ set(SOURCES
../breadcrumbs.cpp
../args.cpp
../hostpolicy.cpp
../host_startup_info.cpp
../coreclr.cpp
../deps_resolver.cpp
../deps_format.cpp
Expand Down
15 changes: 14 additions & 1 deletion src/corehost/cli/exe/apphost/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,21 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL Darwin)
endif()

set(SKIP_VERSIONING 1)

include_directories(./)
include_directories(../../json/casablanca/include)

set(SOURCES
startup_config.cpp
../../json/casablanca/src/json/json.cpp
../../json/casablanca/src/json/json_parsing.cpp
../../json/casablanca/src/json/json_serialization.cpp
../../json/casablanca/src/utilities/asyncrt_utils.cpp
../../fxr/fx_ver.cpp
)

include(../exe.cmake)
set(SOURCES)

add_definitions(-DFEATURE_APPHOST=1)

install_library_and_symbols (apphost)
72 changes: 72 additions & 0 deletions src/corehost/cli/exe/apphost/startup_config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal.h"
#include "trace.h"
#include "utils.h"
#include "cpprest/json.h"
#include "startup_config.h"

startup_config_t::startup_config_t()
: m_valid(false)
{
}

void startup_config_t::parse(const pal::string_t& path)
{
trace::verbose(_X("Attempting to read startup config: %s"), path.c_str());

m_valid = parse_internal(path);
if (!m_valid)
{
trace::verbose(_X("Did not successfully parse the startup.config.json"));
}
}

bool startup_config_t::parse_internal(const pal::string_t& path)
{
pal::string_t retval;
if (!pal::file_exists(path))
{
// Not existing is not an error.
return true;
}

pal::ifstream_t file(path);
if (!file.good())
{
trace::verbose(_X("File stream not good %s"), path.c_str());
return false;
}

if (skip_utf8_bom(&file))
{
trace::verbose(_X("UTF-8 BOM skipped while reading [%s]"), path.c_str());
}

try
{
const auto root = web::json::value::parse(file);
const auto& json = root.as_object();
const auto options = json.find(_X("startupOptions"));
if (options != json.end())
{
const auto& prop_obj = options->second.as_object();

auto appRoot = prop_obj.find(_X("appRoot"));
if (appRoot != prop_obj.end())
{
m_app_root = appRoot->second.as_string();
}
}
}
catch (const std::exception& je)
{
pal::string_t jes;
(void)pal::utf8_palstring(je.what(), &jes);
trace::error(_X("A JSON parsing exception occurred in [%s]: %s"), path.c_str(), jes.c_str());
return false;
}

return true;
}