Exemplo n.º 1
0
// -----------------------------------------------------------------------------
// Resolve coreclr directory from the deps file.
//
// Description:
//    Look for CoreCLR from the dependency list in the package cache and then
//    the packages directory.
//
pal::string_t deps_resolver_t::resolve_coreclr_dir()
{
    auto process_coreclr = [&]
        (bool is_portable, const pal::string_t& deps_dir, deps_json_t* deps) -> pal::string_t
    {
        pal::string_t candidate;

        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())
    {
        return clr_dir;
    }

    // Use platform-specific search algorithm
    pal::string_t install_dir;
    if (pal::find_coreclr(&install_dir))
    {
        return install_dir;
    }

    return pal::string_t();
}
Exemplo n.º 2
0
/**
 * 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,
 *     1. RID specific entries are present in the package relative structure.
 *     2. Non-RID entries are present in the directory path.
 */
bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::string_t& deps_dir, pal::string_t* candidate)
{
    if (probe_entry_in_configs(entry, candidate))
    {
        return true;
    }
    if (entry.is_rid_specific && entry.to_rel_path(deps_dir, candidate))
    {
        return true;
    }
    if (!entry.is_rid_specific && entry.to_dir_path(deps_dir, candidate))
    {
        return true;
    }
    return false;
}
Exemplo n.º 3
0
// -----------------------------------------------------------------------------
// Resolve the directories order for resources/native lookup
//
// Description:
//    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,
        const pal::string_t& clr_dir,
        pal::string_t* output)
{
    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);
    };
    std::function<pal::string_t(const pal::string_t&)>& action = is_resources ? resources : native;
    std::unordered_set<pal::string_t> items;

    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;

    bool track_api_sets = true;
    auto add_package_cache_entry = [&](const deps_entry_t& entry)
    {
        if (probe_entry_in_configs(entry, &candidate))
        {
            // For standalone apps, on win7, coreclr needs ApiSets which has to be in the DLL search path.
            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);
        }
    };
    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.
    if (m_portable)
    {
        std::for_each(entries.begin(), entries.end(), [&](const deps_entry_t& entry)
        {
            if (entry.is_rid_specific && entry.asset_type == asset_type && entry.to_rel_path(m_app_dir, &candidate))
            {
                add_unique_path(asset_type, action(candidate), &items, output);
            }

            // 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);

    // 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);
    }

    // CLR path
    add_unique_path(asset_type, clr_dir, &items, output);
}
Exemplo n.º 4
0
void deps_resolver_t::resolve_tpa_list(
        const pal::string_t& clr_dir,
        pal::string_t* output)
{
    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;

    auto process_entry = [&](const pal::string_t& deps_dir, deps_json_t* deps, const dir_assemblies_t& dir_assemblies, const deps_entry_t& entry)
    {
        if (items.count(entry.asset_name))
        {
            return;
        }

        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());

        // Try to probe from the shared locations.
        if (probe_entry_in_configs(entry, &candidate))
        {
            add_tpa_asset(entry.asset_name, candidate, &items, output);
        }
        // The rid asset should be picked up from app relative subpath.
        else if (entry.is_rid_specific && entry.to_rel_path(deps_dir, &candidate))
        {
            add_tpa_asset(entry.asset_name, candidate, &items, output);
        }
        // The rid-less asset should be picked up from the app base.
        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::verbose(_X("Error: Could not resolve path to assembly: [%s, %s, %s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str());
        }
    };
    
    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) {
        process_entry(m_app_dir, m_deps.get(), m_local_assemblies, entry);
    });

    // Finally, if the deps file wasn't present or has missing entries, then
    // add the app local assemblies to the TPA.
    for (const auto& kv : m_local_assemblies)
    {
        add_tpa_asset(kv.first, kv.second, &items, output);
    }

    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) {
        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);
    }
}