/** * Resolve native and culture assembly directories based on "asset_type" parameter. */ bool deps_resolver_t::resolve_probe_dirs( deps_entry_t::asset_types asset_type, pal::string_t* output, std::unordered_set<pal::string_t>* breadcrumb) { bool is_resources = asset_type == deps_entry_t::asset_types::resources; assert(is_resources || asset_type == deps_entry_t::asset_types::native); // For resources assemblies, we need to provide the base directory of the resources path. // For example: .../Foo/en-US/Bar.dll, then, the resolved path is .../Foo std::function<pal::string_t(const pal::string_t&)> resources = [] (const pal::string_t& str) { return get_directory(get_directory(str)); }; // For native assemblies, obtain the directory path from the file path std::function<pal::string_t(const pal::string_t&)> native = [] (const pal::string_t& 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; // Set for de-duplication std::unordered_set<pal::string_t> items; pal::string_t core_servicing = m_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; std::vector<deps_entry_t> empty(0); const auto& entries = m_deps->get_entries(asset_type); const auto& fx_entries = m_portable ? m_fx_deps->get_entries(asset_type) : empty; pal::string_t candidate; auto add_package_cache_entry = [&](const deps_entry_t& entry, const pal::string_t& deps_dir) -> bool { if (entry.is_serviceable) { breadcrumb->insert(entry.library_name + _X(",") + entry.library_version); breadcrumb->insert(entry.library_name); } if (items.count(entry.asset_name)) { return true; } // 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)) { init_known_entry_path(entry, candidate); add_unique_path(asset_type, action(candidate), &items, output, &non_serviced, core_servicing); } else { // For standalone apps, apphost.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")) || (ends_with(entry.library_name, _X(".Microsoft.NETCore.DotNetAppHost"), false) && entry.asset_name == _X("apphost"))) { 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; }; for (const auto& entry : entries) { if (!add_package_cache_entry(entry, m_app_dir)) { return false; } } // If the deps file is missing add known locations. if (!m_deps->exists()) { // App local path add_unique_path(asset_type, m_app_dir, &items, output, &non_serviced, core_servicing); (void) library_exists_in_dir(m_app_dir, LIBCORECLR_NAME, &m_coreclr_path); (void) library_exists_in_dir(m_app_dir, LIBCLRJIT_NAME, &m_clrjit_path); } for (const auto& entry : fx_entries) { if (!add_package_cache_entry(entry, m_fx_dir)) { return false; } } output->append(non_serviced); return true; }
/** * Resolve native and culture assembly directories based on "asset_type" parameter. */ bool deps_resolver_t::resolve_probe_dirs( deps_entry_t::asset_types asset_type, pal::string_t* output, std::unordered_set<pal::string_t>* breadcrumb) { bool is_resources = asset_type == deps_entry_t::asset_types::resources; assert(is_resources || asset_type == deps_entry_t::asset_types::native); // For resources assemblies, we need to provide the base directory of the resources path. // For example: .../Foo/en-US/Bar.dll, then, the resolved path is .../Foo std::function<pal::string_t(const pal::string_t&)> resources = [] (const pal::string_t& str) { return get_directory(get_directory(str)); }; // For native assemblies, obtain the directory path from the file path std::function<pal::string_t(const pal::string_t&)> native = [] (const pal::string_t& 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; // Set for de-duplication std::unordered_set<pal::string_t> items; pal::string_t core_servicing = m_core_servicing; pal::realpath(&core_servicing, true); // Filter out non-serviced assets so the paths can be added after servicing paths. pal::string_t non_serviced; std::vector<deps_entry_t> empty(0); pal::string_t candidate; auto add_package_cache_entry = [&](const deps_entry_t& entry, const pal::string_t& deps_dir, int fx_level) -> bool { if (breadcrumb != nullptr && entry.is_serviceable) { breadcrumb->insert(entry.library_name + _X(",") + entry.library_version); breadcrumb->insert(entry.library_name); } if (items.count(entry.asset.name)) { return true; } // Ignore placeholders if (ends_with(entry.asset.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.asset.relative_path.c_str()); if (probe_deps_entry(entry, deps_dir, fx_level, &candidate)) { init_known_entry_path(entry, candidate); add_unique_path(asset_type, action(candidate), &items, output, &non_serviced, core_servicing); } else { // 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)) { return report_missing_assembly_in_manifest(entry, true); } return report_missing_assembly_in_manifest(entry); } return true; }; // Add app entries const auto& entries = get_deps().get_entries(asset_type); for (const auto& entry : entries) { if (!add_package_cache_entry(entry, m_app_dir, 0)) { return false; } } // If the deps file is missing add known locations. if (!get_deps().exists()) { // App local path add_unique_path(asset_type, m_app_dir, &items, output, &non_serviced, core_servicing); (void) library_exists_in_dir(m_app_dir, LIBCORECLR_NAME, &m_coreclr_path); (void) library_exists_in_dir(m_app_dir, LIBCLRJIT_NAME, &m_clrjit_path); } // Handle any additional deps.json that were specified. for (const auto& additional_deps : m_additional_deps) { const auto additional_deps_entries = additional_deps->get_entries(asset_type); for (const auto entry : additional_deps_entries) { if (!add_package_cache_entry(entry, m_app_dir, 0)) { return false; } } } // Add fx package locations to fx_dir for (int i = 1; i < m_fx_definitions.size(); ++i) { const auto& fx_entries = m_fx_definitions[i]->get_deps().get_entries(asset_type); for (const auto& entry : fx_entries) { if (!add_package_cache_entry(entry, m_fx_definitions[i]->get_dir(), i)) { return false; } } } output->append(non_serviced); return true; }