Revert "Merge pull request #3191 from schellap/deps-clean"
This reverts commitb2c7140b2a
, reversing changes made tod307537eb8
.
This commit is contained in:
parent
40a2b495ba
commit
c037cf321e
11 changed files with 284 additions and 206 deletions
|
@ -396,7 +396,8 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
File.Copy(Path.Combine(Dirs.CorehostLocked, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), Path.Combine(outputDir, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), overwrite: true);
|
File.Copy(Path.Combine(Dirs.CorehostLocked, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), Path.Combine(outputDir, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), overwrite: true);
|
||||||
File.Copy(Path.Combine(Dirs.CorehostLatest, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(outputDir, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), overwrite: true);
|
File.Copy(Path.Combine(Dirs.CorehostLatest, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(outputDir, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), overwrite: true);
|
||||||
|
|
||||||
var binaryToCorehostifyOutDir = Path.Combine(outputDir, "runtimes", "any", "native");
|
var binaryToCorehostifyRelDir = Path.Combine("runtimes", "any", "native");
|
||||||
|
var binaryToCorehostifyOutDir = Path.Combine(outputDir, binaryToCorehostifyRelDir);
|
||||||
// Corehostify binaries
|
// Corehostify binaries
|
||||||
foreach (var binaryToCorehostify in BinariesForCoreHost)
|
foreach (var binaryToCorehostify in BinariesForCoreHost)
|
||||||
{
|
{
|
||||||
|
@ -407,7 +408,13 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
File.Delete(Path.Combine(binaryToCorehostifyOutDir, $"{binaryToCorehostify}.exe"));
|
File.Delete(Path.Combine(binaryToCorehostifyOutDir, $"{binaryToCorehostify}.exe"));
|
||||||
File.Copy(compilersDeps, Path.Combine(outputDir, binaryToCorehostify + ".deps.json"));
|
File.Copy(compilersDeps, Path.Combine(outputDir, binaryToCorehostify + ".deps.json"));
|
||||||
File.Copy(compilersRuntimeConfig, Path.Combine(outputDir, binaryToCorehostify + ".runtimeconfig.json"));
|
File.Copy(compilersRuntimeConfig, Path.Combine(outputDir, binaryToCorehostify + ".runtimeconfig.json"));
|
||||||
ChangeEntryPointLibraryName(Path.Combine(outputDir, binaryToCorehostify + ".deps.json"), binaryToCorehostify);
|
var binaryToCoreHostifyDeps = Path.Combine(outputDir, binaryToCorehostify + ".deps.json");
|
||||||
|
ChangeEntryPointLibraryName(binaryToCoreHostifyDeps, binaryToCorehostify);
|
||||||
|
foreach (var binaryToRemove in new string[] { "csc", "vbc" })
|
||||||
|
{
|
||||||
|
var assetPath = Path.Combine(binaryToCorehostifyRelDir, $"{binaryToRemove}.exe").Replace(Path.DirectorySeparatorChar, '/');
|
||||||
|
RemoveAssetFromDepsPackages(binaryToCoreHostifyDeps, "runtimeTargets", assetPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -430,6 +437,40 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
return c.Success();
|
return c.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RemoveAssetFromDepsPackages(string depsFile, string sectionName, string assetPath)
|
||||||
|
{
|
||||||
|
JToken deps;
|
||||||
|
using (var file = File.OpenText(depsFile))
|
||||||
|
using (JsonTextReader reader = new JsonTextReader(file))
|
||||||
|
{
|
||||||
|
deps = JObject.ReadFrom(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (JProperty target in deps["targets"])
|
||||||
|
{
|
||||||
|
foreach (JProperty pv in target.Value.Children<JProperty>())
|
||||||
|
{
|
||||||
|
var section = pv.Value[sectionName];
|
||||||
|
if (section != null)
|
||||||
|
{
|
||||||
|
foreach (JProperty relPath in section)
|
||||||
|
{
|
||||||
|
if (assetPath.Equals(relPath.Name))
|
||||||
|
{
|
||||||
|
relPath.Remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var file = File.CreateText(depsFile))
|
||||||
|
using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented })
|
||||||
|
{
|
||||||
|
deps.WriteTo(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void ChangeEntryPointLibraryName(string depsFile, string newName)
|
private static void ChangeEntryPointLibraryName(string depsFile, string newName)
|
||||||
{
|
{
|
||||||
JToken deps;
|
JToken deps;
|
||||||
|
|
|
@ -56,7 +56,7 @@ if (!(Test-Path $env:DOTNET_INSTALL_DIR))
|
||||||
|
|
||||||
# Install a stage 0
|
# Install a stage 0
|
||||||
Write-Host "Installing .NET Core CLI Stage 0 from branchinfo channel"
|
Write-Host "Installing .NET Core CLI Stage 0 from branchinfo channel"
|
||||||
& "$RepoRoot\scripts\obtain\dotnet-install.ps1" -Channel $env:CHANNEL -Architecture $Architecture -Verbose -Version 1.0.0-preview2-002818
|
& "$RepoRoot\scripts\obtain\dotnet-install.ps1" -Channel $env:CHANNEL -Architecture $Architecture -Verbose
|
||||||
if($LASTEXITCODE -ne 0) { throw "Failed to install stage0" }
|
if($LASTEXITCODE -ne 0) { throw "Failed to install stage0" }
|
||||||
|
|
||||||
# Put the stage0 on the path
|
# Put the stage0 on the path
|
||||||
|
|
|
@ -85,7 +85,7 @@ done < "$REPOROOT/branchinfo.txt"
|
||||||
[ -z "$DOTNET_INSTALL_DIR" ] && export DOTNET_INSTALL_DIR=$REPOROOT/.dotnet_stage0/$(uname)
|
[ -z "$DOTNET_INSTALL_DIR" ] && export DOTNET_INSTALL_DIR=$REPOROOT/.dotnet_stage0/$(uname)
|
||||||
[ -d "$DOTNET_INSTALL_DIR" ] || mkdir -p $DOTNET_INSTALL_DIR
|
[ -d "$DOTNET_INSTALL_DIR" ] || mkdir -p $DOTNET_INSTALL_DIR
|
||||||
|
|
||||||
$REPOROOT/scripts/obtain/dotnet-install.sh --channel $CHANNEL --verbose --version 1.0.0-preview2-002818
|
$REPOROOT/scripts/obtain/dotnet-install.sh --channel $CHANNEL --verbose
|
||||||
|
|
||||||
# Put stage 0 on the PATH (for this shell only)
|
# Put stage 0 on the PATH (for this shell only)
|
||||||
PATH="$DOTNET_INSTALL_DIR:$PATH"
|
PATH="$DOTNET_INSTALL_DIR:$PATH"
|
||||||
|
|
|
@ -56,7 +56,7 @@ if (!(Test-Path $env:DOTNET_INSTALL_DIR))
|
||||||
|
|
||||||
# Install a stage 0
|
# Install a stage 0
|
||||||
Write-Host "Installing .NET Core CLI Stage 0 from branchinfo channel"
|
Write-Host "Installing .NET Core CLI Stage 0 from branchinfo channel"
|
||||||
& "$RepoRoot\scripts\obtain\dotnet-install.ps1" -Channel $env:CHANNEL -Architecture $Architecture -Verbose -Version 1.0.0-preview2-002818
|
& "$RepoRoot\scripts\obtain\dotnet-install.ps1" -Channel $env:CHANNEL -Architecture $Architecture -Verbose
|
||||||
if($LASTEXITCODE -ne 0) { throw "Failed to install stage0" }
|
if($LASTEXITCODE -ne 0) { throw "Failed to install stage0" }
|
||||||
|
|
||||||
# Put the stage0 on the path
|
# Put the stage0 on the path
|
||||||
|
|
|
@ -85,7 +85,7 @@ done < "$REPOROOT/branchinfo.txt"
|
||||||
[ -z "$DOTNET_INSTALL_DIR" ] && export DOTNET_INSTALL_DIR=$REPOROOT/.dotnet_stage0/$(uname)
|
[ -z "$DOTNET_INSTALL_DIR" ] && export DOTNET_INSTALL_DIR=$REPOROOT/.dotnet_stage0/$(uname)
|
||||||
[ -d "$DOTNET_INSTALL_DIR" ] || mkdir -p $DOTNET_INSTALL_DIR
|
[ -d "$DOTNET_INSTALL_DIR" ] || mkdir -p $DOTNET_INSTALL_DIR
|
||||||
|
|
||||||
$REPOROOT/scripts/obtain/dotnet-install.sh --channel $CHANNEL --verbose --version 1.0.0-preview2-002818
|
$REPOROOT/scripts/obtain/dotnet-install.sh --channel $CHANNEL --verbose
|
||||||
|
|
||||||
# Put stage 0 on the PATH (for this shell only)
|
# Put stage 0 on the PATH (for this shell only)
|
||||||
PATH="$DOTNET_INSTALL_DIR:$PATH"
|
PATH="$DOTNET_INSTALL_DIR:$PATH"
|
||||||
|
|
|
@ -349,8 +349,10 @@ bool deps_json_t::has_package(const pal::string_t& name, const pal::string_t& ve
|
||||||
//
|
//
|
||||||
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 portable, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph)
|
||||||
{
|
{
|
||||||
|
m_file_exists = pal::file_exists(deps_path);
|
||||||
|
|
||||||
// If file doesn't exist, then assume parsed.
|
// If file doesn't exist, then assume parsed.
|
||||||
if (!pal::file_exists(deps_path))
|
if (!m_file_exists)
|
||||||
{
|
{
|
||||||
trace::verbose(_X("Could not locate the dependencies manifest file [%s]. Some libraries may fail to resolve."), deps_path.c_str());
|
trace::verbose(_X("Could not locate the dependencies manifest file [%s]. Some libraries may fail to resolve."), deps_path.c_str());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -28,6 +28,7 @@ class deps_json_t
|
||||||
public:
|
public:
|
||||||
deps_json_t()
|
deps_json_t()
|
||||||
: m_valid(false)
|
: m_valid(false)
|
||||||
|
, m_file_exists(false)
|
||||||
, m_coreclr_index(-1)
|
, m_coreclr_index(-1)
|
||||||
, m_hostpolicy_index(-1)
|
, m_hostpolicy_index(-1)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +63,11 @@ public:
|
||||||
return m_hostpolicy_index >= 0;
|
return m_hostpolicy_index >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool exists()
|
||||||
|
{
|
||||||
|
return m_file_exists;
|
||||||
|
}
|
||||||
|
|
||||||
const deps_entry_t& get_coreclr_entry()
|
const deps_entry_t& get_coreclr_entry()
|
||||||
{
|
{
|
||||||
assert(has_coreclr_entry());
|
assert(has_coreclr_entry());
|
||||||
|
@ -109,6 +115,7 @@ private:
|
||||||
rid_fallback_graph_t m_rid_fallback_graph;
|
rid_fallback_graph_t m_rid_fallback_graph;
|
||||||
int m_coreclr_index;
|
int m_coreclr_index;
|
||||||
int m_hostpolicy_index;
|
int m_hostpolicy_index;
|
||||||
|
bool m_file_exists;
|
||||||
bool m_valid;
|
bool m_valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -330,89 +330,95 @@ bool deps_resolver_t::probe_entry_in_configs(const deps_entry_t& entry, pal::str
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
/**
|
||||||
// Resolve coreclr directory from the deps file.
|
* Probe helper for a deps entry. Lookup all probe configurations and then
|
||||||
//
|
* lookup in the directory where the deps file is present. For app dirs,
|
||||||
// Description:
|
* 1. RID specific entries are present in the package relative structure.
|
||||||
// Look for CoreCLR from the dependency list in the package cache and then
|
* 2. Non-RID entries are present in the directory path.
|
||||||
// the packages directory.
|
*/
|
||||||
//
|
bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::string_t& deps_dir, pal::string_t* candidate)
|
||||||
pal::string_t deps_resolver_t::resolve_coreclr_dir()
|
|
||||||
{
|
{
|
||||||
trace::verbose(_X("--- Resolving CoreCLR directory ---"));
|
if (probe_entry_in_configs(entry, candidate))
|
||||||
|
|
||||||
auto process_coreclr = [&]
|
|
||||||
(bool is_portable, const pal::string_t& deps_dir, deps_json_t* deps) -> pal::string_t
|
|
||||||
{
|
{
|
||||||
pal::string_t candidate;
|
return true;
|
||||||
|
|
||||||
if (deps->has_coreclr_entry())
|
|
||||||
{
|
|
||||||
const deps_entry_t& entry = deps->get_coreclr_entry();
|
|
||||||
if (probe_entry_in_configs(entry, &candidate))
|
|
||||||
{
|
|
||||||
return get_directory(candidate);
|
|
||||||
}
|
|
||||||
else if (entry.is_rid_specific && entry.to_rel_path(deps_dir, &candidate))
|
|
||||||
{
|
|
||||||
return get_directory(candidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
trace::verbose(_X("Deps has no CoreCLR entry."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// App/FX main dir or standalone app dir.
|
|
||||||
trace::verbose(_X("Probing for CoreCLR in deps directory=[%s]"), deps_dir.c_str());
|
|
||||||
if (coreclr_exists_in_dir(deps_dir))
|
|
||||||
{
|
|
||||||
return deps_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pal::string_t();
|
|
||||||
};
|
|
||||||
|
|
||||||
trace::info(_X("-- Starting CoreCLR Probe from app deps.json"));
|
|
||||||
pal::string_t clr_dir = process_coreclr(m_portable, m_app_dir, m_deps.get());
|
|
||||||
if (clr_dir.empty() && m_portable)
|
|
||||||
{
|
|
||||||
trace::info(_X("-- Starting CoreCLR Probe from FX deps.json"));
|
|
||||||
clr_dir = process_coreclr(false, m_fx_dir, m_fx_deps.get());
|
|
||||||
}
|
}
|
||||||
if (!clr_dir.empty())
|
if (entry.is_rid_specific && entry.to_rel_path(deps_dir, candidate))
|
||||||
{
|
{
|
||||||
return clr_dir;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!entry.is_rid_specific && entry.to_dir_path(deps_dir, candidate))
|
||||||
// Use platform-specific search algorithm
|
|
||||||
pal::string_t install_dir;
|
|
||||||
if (pal::find_coreclr(&install_dir))
|
|
||||||
{
|
{
|
||||||
return install_dir;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
return pal::string_t();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void deps_resolver_t::resolve_tpa_list(
|
/**
|
||||||
const pal::string_t& clr_dir,
|
* Helper for obtaining CoreCLR from a given deps file and the deps file's directory.
|
||||||
|
*/
|
||||||
|
bool deps_resolver_t::get_coreclr_dir_from_deps(const pal::string_t& deps_dir, deps_json_t* deps, pal::string_t* candidate)
|
||||||
|
{
|
||||||
|
if (!deps->has_coreclr_entry())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pal::string_t coreclr;
|
||||||
|
if (probe_deps_entry(deps->get_coreclr_entry(), deps_dir, &coreclr))
|
||||||
|
{
|
||||||
|
*candidate = get_directory(coreclr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe for coreclr relative to the app and then from the framework root.
|
||||||
|
* If deps does not exist, then just use the app base.
|
||||||
|
*/
|
||||||
|
bool deps_resolver_t::resolve_coreclr_dir(pal::string_t* clr_dir)
|
||||||
|
{
|
||||||
|
trace::info(_X("-- Starting CoreCLR Probe from app deps.json"));
|
||||||
|
|
||||||
|
if (get_coreclr_dir_from_deps(m_app_dir, m_deps.get(), clr_dir))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_portable)
|
||||||
|
{
|
||||||
|
trace::info(_X("-- Starting CoreCLR Probe from FX deps.json"));
|
||||||
|
if (get_coreclr_dir_from_deps(m_fx_dir, m_fx_deps.get(), clr_dir))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_deps->exists())
|
||||||
|
{
|
||||||
|
if (coreclr_exists_in_dir(m_app_dir))
|
||||||
|
{
|
||||||
|
*clr_dir = m_app_dir;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resovle the TPA assembly locations
|
||||||
|
*/
|
||||||
|
bool deps_resolver_t::resolve_tpa_list(
|
||||||
pal::string_t* output,
|
pal::string_t* output,
|
||||||
std::unordered_set<pal::string_t>* breadcrumb)
|
std::unordered_set<pal::string_t>* breadcrumb)
|
||||||
{
|
{
|
||||||
const std::vector<deps_entry_t> empty(0);
|
const std::vector<deps_entry_t> empty(0);
|
||||||
|
|
||||||
// Obtain the local assemblies in the app dir.
|
|
||||||
get_dir_assemblies(m_app_dir, _X("local"), &m_local_assemblies);
|
|
||||||
if (m_portable)
|
|
||||||
{
|
|
||||||
// For portable also obtain FX dir assemblies.
|
|
||||||
get_dir_assemblies(m_fx_dir, _X("fx"), &m_fx_assemblies);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unordered_set<pal::string_t> items;
|
std::unordered_set<pal::string_t> items;
|
||||||
|
|
||||||
auto process_entry = [&](const pal::string_t& deps_dir, deps_json_t* deps, const dir_assemblies_t& dir_assemblies, const deps_entry_t& entry)
|
auto process_entry = [&](const pal::string_t& deps_dir, deps_json_t* deps, const deps_entry_t& entry) -> bool
|
||||||
{
|
{
|
||||||
if (entry.is_serviceable)
|
if (entry.is_serviceable)
|
||||||
{
|
{
|
||||||
|
@ -421,81 +427,81 @@ void deps_resolver_t::resolve_tpa_list(
|
||||||
}
|
}
|
||||||
if (items.count(entry.asset_name))
|
if (items.count(entry.asset_name))
|
||||||
{
|
{
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Ignore placeholders
|
||||||
|
if (ends_with(entry.relative_path, _X("/_._"), false))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pal::string_t candidate;
|
pal::string_t candidate;
|
||||||
|
|
||||||
trace::info(_X("Processing TPA for deps entry [%s, %s, %s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
|
trace::info(_X("Processing TPA for deps entry [%s, %s, %s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
|
||||||
|
|
||||||
// Try to probe from the shared locations.
|
if (probe_deps_entry(entry, deps_dir, &candidate))
|
||||||
if (probe_entry_in_configs(entry, &candidate))
|
|
||||||
{
|
{
|
||||||
add_tpa_asset(entry.asset_name, candidate, &items, output);
|
add_tpa_asset(entry.asset_name, candidate, &items, output);
|
||||||
}
|
}
|
||||||
// The rid asset should be picked up from app relative subpath.
|
// Leave the mscorlib error handling to the CoreCLR -- this is because apps might choose to use mscorlib.ni.dll
|
||||||
else if (entry.is_rid_specific && entry.to_rel_path(deps_dir, &candidate))
|
// and delete mscorlib.dll and vice-versa.
|
||||||
|
else if (entry.asset_name != _X("mscorlib"))
|
||||||
{
|
{
|
||||||
add_tpa_asset(entry.asset_name, candidate, &items, output);
|
trace::error(_X("Error: assembly specified in the dependencies manifest was not found -- package: '%s', version: '%s', path: '%s'"),
|
||||||
}
|
entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
|
||||||
// The rid-less asset should be picked up from the app base.
|
return false;
|
||||||
else if (dir_assemblies.count(entry.asset_name))
|
|
||||||
{
|
|
||||||
add_tpa_asset(entry.asset_name, dir_assemblies.find(entry.asset_name)->second, &items, output);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// FIXME: Consider this error as a fail fast?
|
|
||||||
trace::warning(_X("Could not resolve path to assembly: [%s, %s, %s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// First add managed assembly to the TPA.
|
||||||
|
// TODO: Remove: the deps should contain the managed DLL.
|
||||||
|
// Workaround for: csc.deps.json doesn't have the csc.dll
|
||||||
|
pal::string_t managed_app_asset = get_filename_without_ext(m_managed_app);
|
||||||
|
add_tpa_asset(managed_app_asset, m_managed_app, &items, output);
|
||||||
|
|
||||||
const auto& deps_entries = m_deps->get_entries(deps_entry_t::asset_types::runtime);
|
const auto& deps_entries = m_deps->get_entries(deps_entry_t::asset_types::runtime);
|
||||||
std::for_each(deps_entries.begin(), deps_entries.end(), [&](const deps_entry_t& entry) {
|
for (const auto& entry : deps_entries)
|
||||||
process_entry(m_app_dir, m_deps.get(), m_local_assemblies, entry);
|
{
|
||||||
});
|
if (!process_entry(m_app_dir, m_deps.get(), entry))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, if the deps file wasn't present or has missing entries, then
|
// Finally, if the deps file wasn't present or has missing entries, then
|
||||||
// add the app local assemblies to the TPA.
|
// add the app local assemblies to the TPA.
|
||||||
for (const auto& kv : m_local_assemblies)
|
if (!m_deps->exists())
|
||||||
{
|
{
|
||||||
add_tpa_asset(kv.first, kv.second, &items, output);
|
dir_assemblies_t local_assemblies;
|
||||||
|
|
||||||
|
// Obtain the local assemblies in the app dir.
|
||||||
|
get_dir_assemblies(m_app_dir, _X("local"), &local_assemblies);
|
||||||
|
for (const auto& kv : local_assemblies)
|
||||||
|
{
|
||||||
|
add_tpa_asset(kv.first, kv.second, &items, output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Probe FX deps entries after app assemblies are added.
|
||||||
const auto& fx_entries = m_portable ? m_fx_deps->get_entries(deps_entry_t::asset_types::runtime) : empty;
|
const auto& fx_entries = m_portable ? m_fx_deps->get_entries(deps_entry_t::asset_types::runtime) : empty;
|
||||||
std::for_each(fx_entries.begin(), fx_entries.end(), [&](const deps_entry_t& entry) {
|
for (const auto& entry : fx_entries)
|
||||||
process_entry(m_fx_dir, m_fx_deps.get(), m_fx_assemblies, entry);
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const auto& kv : m_fx_assemblies)
|
|
||||||
{
|
{
|
||||||
add_tpa_asset(kv.first, kv.second, &items, output);
|
if (!process_entry(m_fx_dir, m_fx_deps.get(), entry))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
/**
|
||||||
// Resolve the directories order for resources/native lookup
|
* Resolve native and culture assembly directories based on "asset_type" parameter.
|
||||||
//
|
*/
|
||||||
// Description:
|
bool deps_resolver_t::resolve_probe_dirs(
|
||||||
// This general purpose function specifies priority order of directory lookup
|
|
||||||
// for both native images and resources specific resource images. Lookup for
|
|
||||||
// resources assemblies is done by looking up two levels above from the file
|
|
||||||
// path. Lookup for native images is done by looking up one level from the
|
|
||||||
// file path.
|
|
||||||
//
|
|
||||||
// Parameters:
|
|
||||||
// asset_type - The type of the asset that needs lookup, currently
|
|
||||||
// supports "resources" and "native"
|
|
||||||
// app_dir - 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
|
|
||||||
//
|
|
||||||
// Returns:
|
|
||||||
// output - Pointer to a string that will hold the resolved lookup dirs
|
|
||||||
//
|
|
||||||
void deps_resolver_t::resolve_probe_dirs(
|
|
||||||
deps_entry_t::asset_types asset_type,
|
deps_entry_t::asset_types asset_type,
|
||||||
const pal::string_t& clr_dir,
|
|
||||||
pal::string_t* output,
|
pal::string_t* output,
|
||||||
std::unordered_set<pal::string_t>* breadcrumb)
|
std::unordered_set<pal::string_t>* breadcrumb)
|
||||||
{
|
{
|
||||||
|
@ -511,10 +517,16 @@ void deps_resolver_t::resolve_probe_dirs(
|
||||||
std::function<pal::string_t(const pal::string_t&)> native = [] (const pal::string_t& str) {
|
std::function<pal::string_t(const pal::string_t&)> native = [] (const pal::string_t& str) {
|
||||||
return get_directory(str);
|
return get_directory(str);
|
||||||
};
|
};
|
||||||
|
// Action for post processing the resolved path
|
||||||
std::function<pal::string_t(const pal::string_t&)>& action = is_resources ? resources : native;
|
std::function<pal::string_t(const pal::string_t&)>& action = is_resources ? resources : native;
|
||||||
|
|
||||||
|
// Set for de-duplication
|
||||||
std::unordered_set<pal::string_t> items;
|
std::unordered_set<pal::string_t> items;
|
||||||
|
|
||||||
pal::string_t core_servicing = m_core_servicing;
|
pal::string_t core_servicing = m_core_servicing;
|
||||||
pal::realpath(&core_servicing);
|
pal::realpath(&core_servicing);
|
||||||
|
|
||||||
|
// Filter out non-serviced assets so the paths can be added after servicing paths.
|
||||||
pal::string_t non_serviced;
|
pal::string_t non_serviced;
|
||||||
|
|
||||||
std::vector<deps_entry_t> empty(0);
|
std::vector<deps_entry_t> empty(0);
|
||||||
|
@ -523,85 +535,80 @@ void deps_resolver_t::resolve_probe_dirs(
|
||||||
|
|
||||||
pal::string_t candidate;
|
pal::string_t candidate;
|
||||||
|
|
||||||
bool track_api_sets = true;
|
auto add_package_cache_entry = [&](const deps_entry_t& entry, const pal::string_t& deps_dir) -> bool
|
||||||
auto add_package_cache_entry = [&](const deps_entry_t& entry)
|
|
||||||
{
|
{
|
||||||
if (entry.is_serviceable)
|
if (entry.is_serviceable)
|
||||||
{
|
{
|
||||||
breadcrumb->insert(entry.library_name + _X(",") + entry.library_version);
|
breadcrumb->insert(entry.library_name + _X(",") + entry.library_version);
|
||||||
breadcrumb->insert(entry.library_name);
|
breadcrumb->insert(entry.library_name);
|
||||||
}
|
}
|
||||||
|
if (items.count(entry.asset_name))
|
||||||
if (probe_entry_in_configs(entry, &candidate))
|
|
||||||
{
|
{
|
||||||
// For standalone apps, on win7, coreclr needs ApiSets which has to be in the DLL search path.
|
return true;
|
||||||
const pal::string_t result_dir = action(candidate);
|
|
||||||
|
|
||||||
if (track_api_sets && pal::need_api_sets() &&
|
|
||||||
ends_with(entry.library_name, _X("Microsoft.NETCore.Windows.ApiSets"), false))
|
|
||||||
{
|
|
||||||
// For standalone and portable apps, get the ApiSets DLL directory,
|
|
||||||
// as they could come from servicing or other probe paths.
|
|
||||||
// Note: in portable apps, the API set would come from FX deps
|
|
||||||
// which is actually a standalone deps (rid specific API set).
|
|
||||||
// If the portable app relied on its version of API sets, then
|
|
||||||
// the rid selection fallback would have already been performed
|
|
||||||
// by the host (deps_format.cpp)
|
|
||||||
m_api_set_paths.insert(result_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
add_unique_path(asset_type, result_dir, &items, output, &non_serviced, core_servicing);
|
|
||||||
}
|
}
|
||||||
|
// Ignore placeholders
|
||||||
|
if (ends_with(entry.relative_path, _X("/_._"), false))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace::verbose(_X("Processing native/culture for deps entry [%s, %s, %s]"),
|
||||||
|
entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
|
||||||
|
|
||||||
|
if (probe_deps_entry(entry, deps_dir, &candidate))
|
||||||
|
{
|
||||||
|
add_unique_path(asset_type, action(candidate), &items, output, &non_serviced, core_servicing);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For standalone apps, dotnet.exe will be renamed. Do not use the full package name
|
||||||
|
// because of rid-fallback could happen (ex: CentOS falling back to RHEL)
|
||||||
|
if (ends_with(entry.library_name, _X(".Microsoft.NETCore.DotNetHost"), false) && entry.asset_name == _X("dotnet"))
|
||||||
|
{
|
||||||
|
trace::warning(_X("Warning: assembly specified in the dependencies manifest was not found -- package: '%s', version: '%s', path: '%s'"),
|
||||||
|
entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
trace::error(_X("Error: assembly specified in the dependencies manifest was not found -- package: '%s', version: '%s', path: '%s'"),
|
||||||
|
entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_api_set_paths.empty() && pal::need_api_sets() &&
|
||||||
|
ends_with(entry.library_name, _X("Microsoft.NETCore.Windows.ApiSets"), false))
|
||||||
|
{
|
||||||
|
m_api_set_paths.insert(action(candidate));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
std::for_each(entries.begin(), entries.end(), add_package_cache_entry);
|
|
||||||
track_api_sets = m_api_set_paths.empty();
|
|
||||||
std::for_each(fx_entries.begin(), fx_entries.end(), add_package_cache_entry);
|
|
||||||
track_api_sets = m_api_set_paths.empty();
|
|
||||||
|
|
||||||
// For portable rid specific assets, the app relative directory must be used.
|
for (const auto& entry : entries)
|
||||||
if (m_portable)
|
|
||||||
{
|
{
|
||||||
std::for_each(entries.begin(), entries.end(), [&](const deps_entry_t& entry)
|
if (!add_package_cache_entry(entry, m_app_dir))
|
||||||
{
|
{
|
||||||
if (entry.is_rid_specific && entry.asset_type == asset_type && entry.to_rel_path(m_app_dir, &candidate))
|
return false;
|
||||||
{
|
|
||||||
add_unique_path(asset_type, action(candidate), &items, output, &non_serviced, core_servicing);
|
|
||||||
}
|
|
||||||
|
|
||||||
// App called out an explicit API set dependency.
|
|
||||||
if (track_api_sets && entry.is_rid_specific && pal::need_api_sets() &&
|
|
||||||
ends_with(entry.library_name, _X("Microsoft.NETCore.Windows.ApiSets"), false))
|
|
||||||
{
|
|
||||||
m_api_set_paths.insert(action(candidate));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
track_api_sets = m_api_set_paths.empty();
|
|
||||||
|
|
||||||
// App local path
|
|
||||||
add_unique_path(asset_type, m_app_dir, &items, output, &non_serviced, core_servicing);
|
|
||||||
|
|
||||||
// If API sets is not found (i.e., empty) in the probe paths above:
|
|
||||||
// 1. For standalone app, do nothing as all are sxs.
|
|
||||||
// 2. For portable app, add FX dir.
|
|
||||||
|
|
||||||
// FX path if present
|
|
||||||
if (!m_fx_dir.empty())
|
|
||||||
{
|
|
||||||
// For portable apps, if we didn't find api sets in probe paths
|
|
||||||
// add the FX directory.
|
|
||||||
if (track_api_sets && pal::need_api_sets())
|
|
||||||
{
|
|
||||||
m_api_set_paths.insert(m_fx_dir);
|
|
||||||
}
|
}
|
||||||
add_unique_path(asset_type, m_fx_dir, &items, output, &non_serviced, core_servicing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLR path
|
// If the deps file is missing add known locations.
|
||||||
add_unique_path(asset_type, clr_dir, &items, output, &non_serviced, core_servicing);
|
if (!m_deps->exists())
|
||||||
|
{
|
||||||
|
// App local path
|
||||||
|
add_unique_path(asset_type, m_app_dir, &items, output, &non_serviced, core_servicing);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& entry : fx_entries)
|
||||||
|
{
|
||||||
|
if (!add_package_cache_entry(entry, m_fx_dir))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
output->append(non_serviced);
|
output->append(non_serviced);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -617,10 +624,19 @@ void deps_resolver_t::resolve_probe_dirs(
|
||||||
// resolved path ordering.
|
// resolved path ordering.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
bool deps_resolver_t::resolve_probe_paths(const pal::string_t& clr_dir, probe_paths_t* probe_paths, std::unordered_set<pal::string_t>* breadcrumb)
|
bool deps_resolver_t::resolve_probe_paths(probe_paths_t* probe_paths, std::unordered_set<pal::string_t>* breadcrumb)
|
||||||
{
|
{
|
||||||
resolve_tpa_list(clr_dir, &probe_paths->tpa, breadcrumb);
|
if (!resolve_tpa_list(&probe_paths->tpa, breadcrumb))
|
||||||
resolve_probe_dirs(deps_entry_t::asset_types::native, clr_dir, &probe_paths->native, breadcrumb);
|
{
|
||||||
resolve_probe_dirs(deps_entry_t::asset_types::resources, clr_dir, &probe_paths->resources, breadcrumb);
|
return false;
|
||||||
|
}
|
||||||
|
if (!resolve_probe_dirs(deps_entry_t::asset_types::native, &probe_paths->native, breadcrumb))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!resolve_probe_dirs(deps_entry_t::asset_types::resources, &probe_paths->resources, breadcrumb))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
deps_resolver_t(const hostpolicy_init_t& init, const arguments_t& args)
|
deps_resolver_t(const hostpolicy_init_t& init, const arguments_t& args)
|
||||||
: m_fx_dir(init.fx_dir)
|
: m_fx_dir(init.fx_dir)
|
||||||
, m_app_dir(args.app_dir)
|
, m_app_dir(args.app_dir)
|
||||||
|
, m_managed_app(args.managed_application)
|
||||||
, m_coreclr_index(-1)
|
, m_coreclr_index(-1)
|
||||||
, m_portable(init.is_portable)
|
, m_portable(init.is_portable)
|
||||||
, m_deps(nullptr)
|
, m_deps(nullptr)
|
||||||
|
@ -58,6 +59,11 @@ public:
|
||||||
errors->assign(_X("An error occurred while parsing ") + m_deps_file);
|
errors->assign(_X("An error occurred while parsing ") + m_deps_file);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (m_portable && !m_fx_deps->exists())
|
||||||
|
{
|
||||||
|
errors->assign(_X("A fatal error was encountered, missing dependencies manifest at: ") + m_fx_deps_file);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (m_portable && !m_fx_deps->is_valid())
|
if (m_portable && !m_fx_deps->is_valid())
|
||||||
{
|
{
|
||||||
errors->assign(_X("An error occurred while parsing ") + m_fx_deps_file);
|
errors->assign(_X("An error occurred while parsing ") + m_fx_deps_file);
|
||||||
|
@ -73,11 +79,12 @@ public:
|
||||||
void setup_additional_probes(const std::vector<pal::string_t>& probe_paths);
|
void setup_additional_probes(const std::vector<pal::string_t>& probe_paths);
|
||||||
|
|
||||||
bool resolve_probe_paths(
|
bool resolve_probe_paths(
|
||||||
const pal::string_t& clr_dir,
|
|
||||||
probe_paths_t* probe_paths,
|
probe_paths_t* probe_paths,
|
||||||
std::unordered_set<pal::string_t>* breadcrumb);
|
std::unordered_set<pal::string_t>* breadcrumb);
|
||||||
|
|
||||||
pal::string_t resolve_coreclr_dir();
|
bool get_coreclr_dir_from_deps(const pal::string_t& deps_dir, deps_json_t* deps, pal::string_t* candidate);
|
||||||
|
|
||||||
|
bool resolve_coreclr_dir(pal::string_t* clr_dir);
|
||||||
|
|
||||||
const pal::string_t& get_fx_deps_file() const
|
const pal::string_t& get_fx_deps_file() const
|
||||||
{
|
{
|
||||||
|
@ -104,15 +111,13 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve order for TPA lookup.
|
// Resolve order for TPA lookup.
|
||||||
void resolve_tpa_list(
|
bool resolve_tpa_list(
|
||||||
const pal::string_t& clr_dir,
|
|
||||||
pal::string_t* output,
|
pal::string_t* output,
|
||||||
std::unordered_set<pal::string_t>* breadcrumb);
|
std::unordered_set<pal::string_t>* breadcrumb);
|
||||||
|
|
||||||
// Resolve order for culture and native DLL lookup.
|
// Resolve order for culture and native DLL lookup.
|
||||||
void resolve_probe_dirs(
|
bool resolve_probe_dirs(
|
||||||
deps_entry_t::asset_types asset_type,
|
deps_entry_t::asset_types asset_type,
|
||||||
const pal::string_t& clr_dir,
|
|
||||||
pal::string_t* output,
|
pal::string_t* output,
|
||||||
std::unordered_set<pal::string_t>* breadcrumb);
|
std::unordered_set<pal::string_t>* breadcrumb);
|
||||||
|
|
||||||
|
@ -122,6 +127,12 @@ private:
|
||||||
const pal::string_t& dir_name,
|
const pal::string_t& dir_name,
|
||||||
std::unordered_map<pal::string_t, pal::string_t>* dir_assemblies);
|
std::unordered_map<pal::string_t, pal::string_t>* dir_assemblies);
|
||||||
|
|
||||||
|
// Probe entry in probe configurations and deps dir.
|
||||||
|
bool probe_deps_entry(
|
||||||
|
const deps_entry_t& entry,
|
||||||
|
const pal::string_t& deps_dir,
|
||||||
|
pal::string_t* candidate);
|
||||||
|
|
||||||
// Probe entry in probe configurations.
|
// Probe entry in probe configurations.
|
||||||
bool probe_entry_in_configs(
|
bool probe_entry_in_configs(
|
||||||
const deps_entry_t& entry,
|
const deps_entry_t& entry,
|
||||||
|
@ -143,14 +154,15 @@ private:
|
||||||
// Map of simple name -> full path of local/fx assemblies populated
|
// Map of simple name -> full path of local/fx assemblies populated
|
||||||
// in priority order of their extensions.
|
// in priority order of their extensions.
|
||||||
typedef std::unordered_map<pal::string_t, pal::string_t> dir_assemblies_t;
|
typedef std::unordered_map<pal::string_t, pal::string_t> dir_assemblies_t;
|
||||||
dir_assemblies_t m_local_assemblies;
|
|
||||||
dir_assemblies_t m_fx_assemblies;
|
|
||||||
|
|
||||||
std::unordered_map<pal::string_t, pal::string_t> m_patch_roll_forward_cache;
|
std::unordered_map<pal::string_t, pal::string_t> m_patch_roll_forward_cache;
|
||||||
std::unordered_map<pal::string_t, pal::string_t> m_prerelease_roll_forward_cache;
|
std::unordered_map<pal::string_t, pal::string_t> m_prerelease_roll_forward_cache;
|
||||||
|
|
||||||
pal::string_t m_package_cache;
|
pal::string_t m_package_cache;
|
||||||
|
|
||||||
|
// The managed application the dependencies are being resolved for.
|
||||||
|
pal::string_t m_managed_app;
|
||||||
|
|
||||||
// Servicing root, could be empty on platforms that don't support or when errors occur.
|
// Servicing root, could be empty on platforms that don't support or when errors occur.
|
||||||
pal::string_t m_core_servicing;
|
pal::string_t m_core_servicing;
|
||||||
|
|
||||||
|
|
|
@ -85,9 +85,9 @@ pal::string_t resolve_hostpolicy_version_from_deps(const pal::string_t& deps_jso
|
||||||
const auto& json = root.as_object();
|
const auto& json = root.as_object();
|
||||||
const auto& libraries = json.at(_X("libraries")).as_object();
|
const auto& libraries = json.at(_X("libraries")).as_object();
|
||||||
|
|
||||||
// Walk through the libraries section and check any library that starts with:
|
// Look up the root package instead of the "runtime" package because we can't do a full rid resolution.
|
||||||
// "runtime.win7-x64.Microsoft.NETCore.DotNetHostPolicy/" followed by version.
|
// i.e., look for "Microsoft.NETCore.DotNetHostPolicy/" followed by version.
|
||||||
pal::string_t prefix = _STRINGIFY(HOST_POLICY_PKG_NAME) + pal::string_t(_X("/"));
|
pal::string_t prefix = _X("Microsoft.NETCore.DotNetHostPolicy/");
|
||||||
for (const auto& library : libraries)
|
for (const auto& library : libraries)
|
||||||
{
|
{
|
||||||
if (starts_with(library.first, prefix, false))
|
if (starts_with(library.first, prefix, false))
|
||||||
|
|
|
@ -27,8 +27,8 @@ int run(const arguments_t& args)
|
||||||
return StatusCode::ResolverInitFailure;
|
return StatusCode::ResolverInitFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
pal::string_t clr_path = resolver.resolve_coreclr_dir();
|
pal::string_t clr_path;
|
||||||
if (clr_path.empty() || !pal::realpath(&clr_path))
|
if (!resolver.resolve_coreclr_dir(&clr_path) || clr_path.empty() || !pal::realpath(&clr_path))
|
||||||
{
|
{
|
||||||
trace::error(_X("Could not resolve CoreCLR path. For more details, enable tracing by setting COREHOST_TRACE environment variable to 1"));;
|
trace::error(_X("Could not resolve CoreCLR path. For more details, enable tracing by setting COREHOST_TRACE environment variable to 1"));;
|
||||||
return StatusCode::CoreClrResolveFailure;
|
return StatusCode::CoreClrResolveFailure;
|
||||||
|
@ -49,7 +49,7 @@ int run(const arguments_t& args)
|
||||||
breadcrumbs.insert(policy_name + _X(",") + policy_version);
|
breadcrumbs.insert(policy_name + _X(",") + policy_version);
|
||||||
|
|
||||||
probe_paths_t probe_paths;
|
probe_paths_t probe_paths;
|
||||||
if (!resolver.resolve_probe_paths(clr_path, &probe_paths, &breadcrumbs))
|
if (!resolver.resolve_probe_paths(&probe_paths, &breadcrumbs))
|
||||||
{
|
{
|
||||||
return StatusCode::ResolverResolveFailure;
|
return StatusCode::ResolverResolveFailure;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue