From: Woongsuk Cho Date: Wed, 21 Oct 2020 05:12:26 +0000 (+0900) Subject: Resolve platform specific path at install time X-Git-Tag: submit/tizen/20201224.021710~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f94a2ac1b626eb05abfda98452b5ea3414420100;p=platform%2Fcore%2Fdotnet%2Flauncher.git Resolve platform specific path at install time If you publish .NET Application without RID designation, it is generated to cross-platform type. If the .NET application uses a NuGet package that has platform-specific implementations, all platforms' dependencies are copied to the publish folder along with the app. (refer to https://docs.microsoft.com/en-us/dotnet/core/deploying) Libraries and assemblies used for each platform are stored in different locations according to RID and TFM as follows. (refer to https://natemcmaster.com/blog/2016/05/19/nuget3-rid-graph) .NET Runtime finds the most suitable paths for its execution environment and uses it by setting APP_PATH and NATIVE_LIBRARY_SEASRCHING_PATH. These path is set in the coreclr_initializae() function. Unfortunately, in the case of the candidate process, we cannot specify these kind of paths because a application has not been fixed yet. So, in the current implementation, all possible combinations of paths are added in priority order. For this reason, unnecessarily long path settings are being transferred to runtime. To solve this problem, at the time of installation, I try to change it as if the application was published with the RID setting. In detail, find the best matched RID and TFM path in the application, and move all contents in them to the "bin" folder. After then, we can remove runtimes foldr. The results after resolving are the same as those performed by specifying RID during publish. --- diff --git a/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc b/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc index 1e2fdbd..bd248ac 100644 --- a/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc +++ b/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc @@ -17,7 +17,7 @@ #include "log.h" #include "utils.h" -#include +#include #include #ifdef LOG_TAG @@ -29,6 +29,124 @@ typedef struct _xmlDoc xmlDoc; typedef xmlDoc* xmlDocPtr; bool pluginInstalled = false; +static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version"; +static const char* __TIZEN_TFM_SUPPORT_KEY = "db/dotnet/tizen_tfm_support"; + +static std::vector getRidFallbackGraph() +{ + std::vector RID_FALLBACK_GRAPH; + char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY); + if (tizen_rid) { + std::vector version; + splitPath(tizen_rid, version); + std::reverse(std::begin(version), std::end(version)); + for (unsigned int i = 0; i < version.size(); i++) { + RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER)); + RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i])); + } + free(tizen_rid); + } + + std::vector RID_FALLBACK_OS = {"tizen", "linux", "unix"}; + for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) { + RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" + ARCHITECTURE_IDENTIFIER)); + RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i])); + } + RID_FALLBACK_GRAPH.push_back("any"); + RID_FALLBACK_GRAPH.push_back("base"); + + return RID_FALLBACK_GRAPH; +} + +static std::vector getTfmFallbackGraph() +{ + std::vector tfmList; + char* tizen_tfm = vconf_get_str(__TIZEN_TFM_SUPPORT_KEY); + if (tizen_tfm) { + splitPath(tizen_tfm, tfmList); + free(tizen_tfm); + } + + return tfmList; +} + +static bool copyAllFilesTo(const std::string& from, const std::string& to) +{ + std::vector files; + try { + // make file list to move + for (auto& path : bf::recursive_directory_iterator(from)) { + std::string filePath = path.path().string(); + if (isFile(filePath)) { + files.push_back(filePath); + } + } + + // move files to target directory + for (auto& f : files) { + bf::rename(f, concatPath(to, getFileName(f))); + } + } catch (const bf::filesystem_error& error) { + _ERR("Failed to recursive directory: %s", error.what()); + return false; + } + + return true; +} + +static bool resolvePlatformSpecificFiles(const std::string& appBinPath) +{ + std::string runtimesPath = concatPath(appBinPath, "runtimes"); + + // if runtimes directory doesnot exist, return true + if (!isDirectory(runtimesPath)) { + return true; + } + + // found best matched rid and tfm directory and copy all files to bin directory + std::vector ridFallbackGraph = getRidFallbackGraph(); + for (auto& rid : ridFallbackGraph) { + std::string ridPath = concatPath(runtimesPath, rid); + if (isDirectory(ridPath)) { + _INFO("Found best matched rid path"); + // copy all files from /runtimes/${rid}/native to appBintPath if exist + std::string nativePath = concatPath(ridPath, "native"); + if (isDirectory(nativePath)) { + _INFO("Found best matched native path"); + if (!copyAllFilesTo(nativePath, appBinPath)) { + _ERR("Failed to copy files from native path"); + return false; + } + } + + // found best matched tfm folder in the found rid folder + std::string libPath = concatPath(ridPath, "lib"); + std::vector tfmFallbackGraph = getTfmFallbackGraph(); + for (auto& tfm : tfmFallbackGraph) { + std::string tfmPath = concatPath(libPath, tfm); + if (isDirectory(tfmPath)) { + _INFO("Found best matched tfm path"); + // copy all files from tfmPath to appBintPath + if (!copyAllFilesTo(tfmPath, appBinPath)) { + _ERR("Failed to copy files from tfm path"); + return false; + } + } + } + + // finish iteration + break; + } + } + + // remove runtimes directory + if (!removeAll(runtimesPath)) { + _ERR("Failed to remove bin/runtimes directory"); + return false; + } + + return true; +} extern "C" int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc, const char* pkgId) { @@ -55,36 +173,10 @@ extern "C" int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc, const char* pkgId) return 0; } - std::string runtimesDir = concatPath(rootPath, "bin/runtimes"); - if (!exist(runtimesDir)) { - return 0; - } - - char buffer[128]; - sprintf(buffer, "(tizen|linux|unix|base|any)(.\\d.\\d.\\d)?(-%s)?", ARCHITECTURE_IDENTIFIER); - std::regex pattern(buffer); - - std::vector unusedDir; - try { - for (auto& path : bf::recursive_directory_iterator(runtimesDir)) { - std::string filepath = path.path().string(); - std::string targetDir = filepath.substr(filepath.rfind("/runtimes/") + 10); - if (!std::regex_match(targetDir.substr(0, targetDir.find('/')), pattern)) { - if (isDirectory(filepath)) { - unusedDir.push_back(filepath); - } - } - } - } catch (const bf::filesystem_error& error) { - _ERR("Failed to recursive directory: %s", error.what()); - } - - for (auto& path : unusedDir) { - if (!removeAll(path)) { - _ERR("Failed to remove of %s", path.c_str()); - } + std::string appBinPath = concatPath(rootPath, "bin"); + if (!resolvePlatformSpecificFiles(appBinPath)) { + _ERR("Failed to resolve platform specific resources of nuget"); } - unusedDir.clear(); return 0; } diff --git a/NativeLauncher/tool/tac_common.cc b/NativeLauncher/tool/tac_common.cc index 92dbc78..54da934 100644 --- a/NativeLauncher/tool/tac_common.cc +++ b/NativeLauncher/tool/tac_common.cc @@ -427,8 +427,8 @@ std::vector depsJsonParser(const std::string& rootPath, const std:: std::vector getLibrariesInfo(const std::string& rootPath) { std::vector LibrariesInfo; - std::string runtimesDir = concatPath(rootPath, "bin/runtimes"); - if (!exist(runtimesDir)) + std::string binDir = concatPath(rootPath, "bin"); + if (!exist(binDir)) return LibrariesInfo; auto convert = [&LibrariesInfo](const std::string& filepath, const std::string& filename) { @@ -438,7 +438,7 @@ std::vector getLibrariesInfo(const std::string& rootPath) _INFO("Library : [%s] / SHA256 : [%s]", filename.c_str(), buffer.c_str()); } }; - scanFilesInDirectory(runtimesDir, convert, -1); + scanFilesInDirectory(binDir, convert, -1); return LibrariesInfo; } diff --git a/NativeLauncher/util/path_manager.cc b/NativeLauncher/util/path_manager.cc index fbd2b3e..ee456f3 100644 --- a/NativeLauncher/util/path_manager.cc +++ b/NativeLauncher/util/path_manager.cc @@ -30,8 +30,6 @@ #include "log.h" static const char* __TIZEN_API_PATH_KEY = "db/dotnet/tizen_api_path"; -static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version"; -static const char* __TIZEN_TFM_SUPPORT_KEY = "db/dotnet/tizen_tfm_support"; #define __XSTR(x) #x #define __STR(x) __XSTR(x) @@ -41,53 +39,10 @@ static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR); #undef __STR #undef __XSTR -// The sequence of RID_FALLBACK graphs must be: -// 1. Tizen + Version + Architecture -// 2. Tizen + Version -// 3. OS(tizen, linux, unix) + Architecture -// 4. OS(tizen, linux, unix) -// 5. any, base -static std::string getRidFallbackGraphDirs(const std::string& appRoot) -{ - std::vector RID_FALLBACK_GRAPH; - char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY); - if (tizen_rid) { - std::vector version; - splitPath(tizen_rid, version); - std::reverse(std::begin(version), std::end(version)); - for (unsigned int i = 0; i < version.size(); i++) { - RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER)); - RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i])); - } - free(tizen_rid); - } - - std::vector RID_FALLBACK_OS = {"tizen", "linux", "unix"}; - for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) { - RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" + ARCHITECTURE_IDENTIFIER)); - RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i])); - } - RID_FALLBACK_GRAPH.push_back("any"); - RID_FALLBACK_GRAPH.push_back("base"); - - std::string candidate; - for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) { - if (!candidate.empty()) { - candidate += ":"; - } - candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native"); - } - - return candidate; -} - -// 1. /appRoot/runtimes/{Platform}-{Architecture}/native/xxxxx.so -// 2. /appRoot/lib/{Architecture}/xxxxx.so +// /appRoot/lib/{Architecture}/xxxxx.so static std::string getExtraNativeLibDirs(const std::string& appRoot) { - std::string candidate = getRidFallbackGraphDirs(appRoot); - - candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER); + std::string candidate = concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER); if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) { candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64"); } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) { @@ -97,49 +52,15 @@ static std::string getExtraNativeLibDirs(const std::string& appRoot) return candidate; } -// 1. /appRoot/runtimes/{Platform}-{Architecture}/lib/{TFMs}/xxxxx.dll -static std::string getExtraTfmDirs(const std::string& appRoot) -{ - std::string candidate; - std::vector tfmList; - char* tizen_tfm = vconf_get_str(__TIZEN_TFM_SUPPORT_KEY); - if (tizen_tfm) { - splitPath(tizen_tfm, tfmList); - free(tizen_tfm); - } - - std::vector paths; - splitPath(replaceAll(getRidFallbackGraphDirs(appRoot), "/native", "/lib"), paths); - - if (tfmList.empty() || paths.empty()) - return candidate; - - std::vector tfmDirectoryList; - for (unsigned int i = 0; i < paths.size(); i++) { - for (unsigned int j = 0; j < tfmList.size(); j++) { - tfmDirectoryList.push_back(concatPath(paths[i], tfmList[j])); - } - } - - for (unsigned int i = 0; i < tfmDirectoryList.size(); i++) { - if (!candidate.empty()) { - candidate += ":"; - } - candidate += tfmDirectoryList[i]; - } - - return candidate; -} - void PathManager::updateAppRelatedPath(const std::string& appRootPath) { std::string appBinPath = concatPath(appRootPath, "bin"); std::string appLibPath = concatPath(appRootPath, "lib"); appTacPath = concatPath(appBinPath, TAC_SYMLINK_SUB_DIR); - appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath + ":" + getExtraTfmDirs(appRootPath); + appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath; appNIPaths = concatPath(appBinPath, APP_NI_SUB_DIR) + ":" + concatPath(appLibPath, APP_NI_SUB_DIR) + ":"+ appTacPath; - nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" + getExtraNativeLibDirs(appRootPath) + ":" + appBinPath + ":" + appLibPath; + nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" + appBinPath + ":" + appLibPath + ":" + getExtraNativeLibDirs(appRootPath); } PathManager::PathManager() :