From 28f35c1cfa37fd2d329e273b4c76433e86a95c05 Mon Sep 17 00:00:00 2001 From: Senthil Date: Thu, 4 Feb 2016 21:10:13 -0800 Subject: [PATCH] Remove DOTNET_HOME from the CoreCLR probe path --- src/Microsoft.DotNet.Cli.Utils/Constants.cs | 3 +- src/corehost/cli/deps_resolver.cpp | 99 +++++++++++++++++-- src/corehost/cli/deps_resolver.h | 13 +++ src/corehost/cli/hostpolicy.cpp | 75 +++----------- src/corehost/cli/setup.cmake | 1 - src/corehost/common/pal.h | 11 ++- src/corehost/common/utils.cpp | 2 +- .../commands/dotnet-build/CompileContext.cs | 27 +++++ src/dotnet/commands/dotnet-build/Program.cs | 1 + 9 files changed, 155 insertions(+), 77 deletions(-) diff --git a/src/Microsoft.DotNet.Cli.Utils/Constants.cs b/src/Microsoft.DotNet.Cli.Utils/Constants.cs index 2a58ba8b6..6d2da7bfa 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Constants.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Constants.cs @@ -24,7 +24,8 @@ namespace Microsoft.DotNet.Cli.Utils public static readonly string DynamicLibSuffix = CurrentPlatform == Platform.Windows ? ".dll" : CurrentPlatform == Platform.Darwin ? ".dylib" : ".so"; - public static readonly string LibCoreClrName = (CurrentPlatform == Platform.Windows ? "coreclr" : "libcoreclr") + DynamicLibSuffix; + public static readonly string LibCoreClrFileName = (CurrentPlatform == Platform.Windows ? "coreclr" : "libcoreclr"); + public static readonly string LibCoreClrName = LibCoreClrFileName + DynamicLibSuffix; public static readonly string RuntimeIdentifier = CurrentPlatform == Platform.Windows ? "win7-x64" : CurrentPlatform == Platform.Darwin ? "osx.10.10-x64" : "ubuntu.14.04-x64"; diff --git a/src/corehost/cli/deps_resolver.cpp b/src/corehost/cli/deps_resolver.cpp index 1a7ff6720..a43fdab34 100644 --- a/src/corehost/cli/deps_resolver.cpp +++ b/src/corehost/cli/deps_resolver.cpp @@ -123,7 +123,7 @@ void add_mscorlib_to_tpa(const pal::string_t& clr_dir, std::set* pal::string_t mscorlib_path = clr_dir + DIR_SEPARATOR + _X("mscorlib.dll"); if (pal::file_exists(mscorlib_path)) { - add_tpa_asset(_X("mscorlib"), mscorlib_ni_path, items, output); + add_tpa_asset(_X("mscorlib"), mscorlib_path, items, output); return; } } @@ -346,6 +346,20 @@ bool deps_resolver_t::load() replace_char(&entry.relative_path, _X('\\'), _X('/')); m_deps_entries.push_back(entry); + + trace::verbose(_X("Added deps entry [%d] [%s, %s, %s]"), m_deps_entries.size() - 1, entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str()); + + static_assert(std::is_same, decltype(m_deps_entries)>::value, "decltype(m_deps_entries) not a vector, took index based on size."); + if (entry.asset_type == _X("native") && + entry.asset_name == LIBCORECLR_FILENAME) + { + m_coreclr_index = m_deps_entries.size() - 1; + trace::verbose(_X("Found coreclr from deps entry [%d] [%s, %s, %s]"), + m_coreclr_index, + entry.library_name.c_str(), + entry.library_version.c_str(), + entry.relative_path.c_str()); + } } return true; } @@ -379,9 +393,9 @@ void deps_resolver_t::get_local_assemblies(const pal::string_t& dir) std::vector files; pal::readdir(dir, &files); - for (const auto& file : files) + for (const auto& ext : managed_ext) { - for (const auto& ext : managed_ext) + for (const auto& file : files) { // Nothing to do if file length is smaller than expected ext. if (file.length() <= ext.length()) @@ -414,6 +428,67 @@ void deps_resolver_t::get_local_assemblies(const pal::string_t& dir) } } +// ----------------------------------------------------------------------------- +// 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( + const pal::string_t& app_dir, + const pal::string_t& package_dir, + const pal::string_t& package_cache_dir) +{ + // Runtime servicing + trace::verbose(_X("Probing for CoreCLR in servicing dir=[%s]"), m_runtime_svc.c_str()); + if (!m_runtime_svc.empty()) + { + pal::string_t svc_clr = m_runtime_svc; + append_path(&svc_clr, _X("runtime")); + append_path(&svc_clr, _X("coreclr")); + + if (coreclr_exists_in_dir(svc_clr)) + { + return svc_clr; + } + } + + // Package cache. + trace::verbose(_X("Probing for CoreCLR in package cache=[%s] deps index: [%d]"), package_cache_dir.c_str(), m_coreclr_index); + pal::string_t coreclr_cache; + if (m_coreclr_index >= 0 && !package_cache_dir.empty() && + m_deps_entries[m_coreclr_index].to_hash_matched_path(package_cache_dir, &coreclr_cache)) + { + return get_directory(coreclr_cache); + } + + // App dir. + trace::verbose(_X("Probing for CoreCLR in app directory=[%s]"), app_dir.c_str()); + if (coreclr_exists_in_dir(app_dir)) + { + return app_dir; + } + + // Packages dir + trace::verbose(_X("Probing for CoreCLR in packages=[%s] deps index: [%d]"), package_dir.c_str(), m_coreclr_index); + pal::string_t coreclr_package; + if (m_coreclr_index >= 0 && !package_dir.empty() && + m_deps_entries[m_coreclr_index].to_full_path(package_dir, &coreclr_package)) + { + return get_directory(coreclr_package); + } + + // Use platform-specific search algorithm + pal::string_t install_dir; + if (pal::find_coreclr(&install_dir)) + { + return install_dir; + } + + return pal::string_t(); +} + // ----------------------------------------------------------------------------- // Resolve the TPA list order. // @@ -549,11 +624,14 @@ void deps_resolver_t::resolve_probe_dirs( pal::string_t candidate; // Take care of the secondary cache path - for (const deps_entry_t& entry : m_deps_entries) + if (!package_cache_dir.empty()) { - if (entry.asset_type == asset_type && entry.to_hash_matched_path(package_cache_dir, &candidate)) + for (const deps_entry_t& entry : m_deps_entries) { - add_unique_path(asset_type, action(candidate), &items, output); + if (entry.asset_type == asset_type && entry.to_hash_matched_path(package_cache_dir, &candidate)) + { + add_unique_path(asset_type, action(candidate), &items, output); + } } } @@ -561,11 +639,14 @@ void deps_resolver_t::resolve_probe_dirs( add_unique_path(asset_type, app_dir, &items, output); // Take care of the package restore path - for (const deps_entry_t& entry : m_deps_entries) + if (!package_dir.empty()) { - if (entry.asset_type == asset_type && entry.to_full_path(package_dir, &candidate)) + for (const deps_entry_t& entry : m_deps_entries) { - add_unique_path(asset_type, action(candidate), &items, output); + if (entry.asset_type == asset_type && entry.to_full_path(package_dir, &candidate)) + { + add_unique_path(asset_type, action(candidate), &items, output); + } } } diff --git a/src/corehost/cli/deps_resolver.h b/src/corehost/cli/deps_resolver.h index 3bf3cd08c..309fce686 100644 --- a/src/corehost/cli/deps_resolver.h +++ b/src/corehost/cli/deps_resolver.h @@ -43,6 +43,8 @@ class deps_resolver_t public: deps_resolver_t(const arguments_t& args) : m_svc(args.dotnet_servicing) + , m_runtime_svc(args.dotnet_runtime_servicing) + , m_coreclr_index(-1) { m_deps_valid = parse_deps_file(args); } @@ -56,6 +58,11 @@ public: const pal::string_t& clr_dir, probe_paths_t* probe_paths); + pal::string_t resolve_coreclr_dir( + const pal::string_t& app_dir, + const pal::string_t& package_dir, + const pal::string_t& package_cache_dir); + private: bool load(); @@ -85,6 +92,9 @@ private: // Servicing index to resolve serviced assembly paths. servicing_index_t m_svc; + // Runtime servicing directory. + pal::string_t m_runtime_svc; + // Map of simple name -> full path of local assemblies populated in priority // order of their extensions. std::unordered_map m_local_assemblies; @@ -92,6 +102,9 @@ private: // Entries in the dep file std::vector m_deps_entries; + // Special entry for coreclr in the deps entries + int m_coreclr_index; + // The dep file path pal::string_t m_deps_path; diff --git a/src/corehost/cli/hostpolicy.cpp b/src/corehost/cli/hostpolicy.cpp index ead5f5da0..b087357c8 100644 --- a/src/corehost/cli/hostpolicy.cpp +++ b/src/corehost/cli/hostpolicy.cpp @@ -20,59 +20,7 @@ enum StatusCode ResolverResolveFailure = 0x87, }; -// ---------------------------------------------------------------------- -// resolve_clr_path: Resolve CLR Path in priority order -// -// Description: -// Check if CoreCLR library exists in runtime servicing dir or app -// local or DOTNET_HOME directory in that order of priority. If these -// fail to locate CoreCLR, then check platform-specific search. -// -// Returns: -// "true" if path to the CoreCLR dir can be resolved in "clr_path" -// parameter. Else, returns "false" with "clr_path" unmodified. -// -bool resolve_clr_path(const arguments_t& args, pal::string_t* clr_path) -{ - const pal::string_t* dirs[] = { - &args.dotnet_runtime_servicing, // DOTNET_RUNTIME_SERVICING - &args.app_dir, // APP LOCAL - &args.dotnet_home // DOTNET_HOME - }; - for (int i = 0; i < sizeof(dirs) / sizeof(dirs[0]); ++i) - { - if (dirs[i]->empty()) - { - continue; - } - - // App dir should contain coreclr, so skip appending path. - pal::string_t cur_dir = *dirs[i]; - if (dirs[i] != &args.app_dir) - { - append_path(&cur_dir, _X("runtime")); - append_path(&cur_dir, _X("coreclr")); - } - - // Found coreclr in priority order. - if (coreclr_exists_in_dir(cur_dir)) - { - clr_path->assign(cur_dir); - return true; - } - } - - // Use platform-specific search algorithm - pal::string_t home_dir = args.dotnet_home; - if (pal::find_coreclr(&home_dir)) - { - clr_path->assign(home_dir); - return true; - } - return false; -} - -int run(const arguments_t& args, const pal::string_t& clr_path) +int run(const arguments_t& args) { // Load the deps resolver deps_resolver_t resolver(args); @@ -90,6 +38,17 @@ int run(const arguments_t& args, const pal::string_t& clr_path) } trace::info(_X("Package directory: %s"), packages_dir.empty() ? _X("not specified") : packages_dir.c_str()); + pal::string_t clr_path = resolver.resolve_coreclr_dir(args.app_dir, packages_dir, args.dotnet_packages_cache); + if (clr_path.empty() || !pal::realpath(&clr_path)) + { + trace::error(_X("Could not resolve coreclr path")); + return StatusCode::CoreClrResolveFailure; + } + else + { + trace::info(_X("CoreCLR directory: %s"), clr_path.c_str()); + } + probe_paths_t probe_paths; if (!resolver.resolve_probe_paths(args.app_dir, packages_dir, args.dotnet_packages_cache, clr_path, &probe_paths)) { @@ -240,13 +199,5 @@ SHARED_API int corehost_main(const int argc, const pal::char_t* argv[]) return StatusCode::InvalidArgFailure; } - // Resolve CLR path - pal::string_t clr_path; - if (!resolve_clr_path(args, &clr_path)) - { - trace::error(_X("Could not resolve coreclr path")); - return StatusCode::CoreClrResolveFailure; - } - pal::realpath(&clr_path); - return run(args, clr_path); + return run(args); } diff --git a/src/corehost/cli/setup.cmake b/src/corehost/cli/setup.cmake index 3cc0115c5..ef2028035 100644 --- a/src/corehost/cli/setup.cmake +++ b/src/corehost/cli/setup.cmake @@ -9,7 +9,6 @@ if(WIN32) endif() add_compile_options($<$:-DDEBUG>) add_compile_options($<$:/Od>) - add_compile_options($<$:/Gm>) add_compile_options(/DEBUG) add_compile_options(/GS) add_compile_options(/W1) diff --git a/src/corehost/common/pal.h b/src/corehost/common/pal.h index 2e6536744..826f26426 100644 --- a/src/corehost/common/pal.h +++ b/src/corehost/common/pal.h @@ -48,14 +48,19 @@ #endif + #if defined(_WIN32) +#define LIB_PREFIX #define MAKE_LIBNAME(NAME) (_X(NAME) _X(".dll")) #elif defined(__APPLE__) -#define MAKE_LIBNAME(NAME) (_X("lib") _X(NAME) _X(".dylib")) +#define LIB_PREFIX _X("lib") +#define MAKE_LIBNAME(NAME) (LIB_PREFIX _X(NAME) _X(".dylib")) #else -#define MAKE_LIBNAME(NAME) (_X("lib") _X(NAME) _X(".so")) +#define LIB_PREFIX _X("lib") +#define MAKE_LIBNAME(NAME) (LIB_PREFIX _X(NAME) _X(".so")) #endif +#define LIBCORECLR_FILENAME (LIB_PREFIX _X("coreclr")) #define LIBCORECLR_NAME MAKE_LIBNAME("coreclr") #if !defined(PATH_MAX) && !defined(_WIN32) @@ -118,7 +123,7 @@ namespace pal inline pal::string_t to_palstring(const std::string& str) { return str; } inline std::string to_stdstring(const pal::string_t& str) { return str; } inline void to_palstring(const char* str, pal::string_t* out) { out->assign(str); } - inline void to_stdstring(const pal::char_t* str, std::string* out) { out->assign(str); } + inline void to_stdstring(const char_t* str, std::string* out) { out->assign(str); } #endif bool realpath(string_t* path); bool file_exists(const string_t& path); diff --git a/src/corehost/common/utils.cpp b/src/corehost/common/utils.cpp index 930250507..8d4016481 100644 --- a/src/corehost/common/utils.cpp +++ b/src/corehost/common/utils.cpp @@ -8,7 +8,7 @@ bool coreclr_exists_in_dir(const pal::string_t& candidate) { pal::string_t test(candidate); append_path(&test, LIBCORECLR_NAME); - trace::verbose(_X("checking for CoreCLR in default location: %s"), test.c_str()); + trace::verbose(_X("Checking if CoreCLR path exists=[%s]"), test.c_str()); return pal::file_exists(test); } diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index 6c2906386..55352ce0a 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -404,6 +404,33 @@ namespace Microsoft.DotNet.Tools.Build var libraryExporter = _rootProject.CreateExporter(_args.ConfigValue, _args.BuildBasePathValue); var executable = new Executable(_rootProject, outputPaths, libraryExporter); executable.MakeCompilationOutputRunnable(); + + PatchMscorlibNextToCoreClr(_rootProject, _args.ConfigValue); + } + + // Workaround: CoreCLR packaging doesn't include side by side mscorlib, so copy it at build + // time. See: https://github.com/dotnet/cli/issues/1374 + private static void PatchMscorlibNextToCoreClr(ProjectContext context, string config) + { + { + foreach (var exp in context.CreateExporter(config).GetAllExports()) + { + var coreclrLib = exp.NativeLibraries.FirstOrDefault(nLib => + string.Equals(Constants.LibCoreClrFileName, nLib.Name)); + if (string.IsNullOrEmpty(coreclrLib.ResolvedPath)) + { + continue; + } + var coreclrDir = Path.GetDirectoryName(coreclrLib.ResolvedPath); + if (File.Exists(Path.Combine(coreclrDir, "mscorlib.dll")) || + File.Exists(Path.Combine(coreclrDir, "mscorlib.ni.dll"))) + { + continue; + } + var mscorlibFile = exp.RuntimeAssemblies.FirstOrDefault(r => r.Name.Equals("mscorlib") || r.Name.Equals("mscorlib.ni")).ResolvedPath; + File.Copy(mscorlibFile, Path.Combine(coreclrDir, Path.GetFileName(mscorlibFile)), overwrite: true); + } + } } private static ISet Sort(Dictionary projects) diff --git a/src/dotnet/commands/dotnet-build/Program.cs b/src/dotnet/commands/dotnet-build/Program.cs index c44ac6471..62a0725e0 100644 --- a/src/dotnet/commands/dotnet-build/Program.cs +++ b/src/dotnet/commands/dotnet-build/Program.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.IO; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ProjectModel;