From ebad648f17029c908403b945f4c04631a25e4312 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Tue, 22 Dec 2020 13:16:52 +0900 Subject: [PATCH] Add "--resolve-all-app" option to dotnettool A patch that resolves the "bin/runtimes" directory to support multi-targeting at the app installation time was added after Tizen 6.0. After applying this patch, it has been changed to no longer refer to the "bin/runtimes" directory of the application. However, if the target is upgraded by FOTA, installed applications may have "bin/runtimes" directory. To solve this problem, "--resolve-all-app" option is added to dotnettool and the FOTA script is also updated. When you run below command, all installed .net application's platform specific files are resolved. --- NativeLauncher/CMakeLists.txt | 13 +- NativeLauncher/inc/multi_target_resolver.h | 34 ++++ .../delete_unused_library_plugin.cc | 123 +------------ NativeLauncher/tool/dotnettool.cc | 10 ++ NativeLauncher/tool/multi_target_resolver.cc | 192 +++++++++++++++++++++ packaging/715.dotnet_regen_app_ni.patch.sh | 2 +- packaging/dotnet-launcher.spec | 1 + 7 files changed, 251 insertions(+), 124 deletions(-) create mode 100644 NativeLauncher/inc/multi_target_resolver.h create mode 100644 NativeLauncher/tool/multi_target_resolver.cc diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index e3254ee..c344aab 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -191,6 +191,14 @@ ADD_LIBRARY(${NI_COMMON} SHARED ${${NI_COMMON}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${NI_COMMON} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB}) TARGET_LINK_LIBRARIES(${NI_COMMON} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL} ${TAC_COMMON}) +SET(MULTI_TARGET_RESOLVER "multi_target_resolver") +SET(${MULTI_TARGET_RESOLVER}_SOURCE_FILES + tool/multi_target_resolver.cc +) +ADD_LIBRARY(${MULTI_TARGET_RESOLVER} SHARED ${${MULTI_TARGET_RESOLVER}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${MULTI_TARGET_RESOLVER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB}) +TARGET_LINK_LIBRARIES(${MULTI_TARGET_RESOLVER} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL}) + SET(TPATOOL "tpatool") SET(${TPATOOL}_SOURCE_FILES tool/tpatool.cc @@ -205,7 +213,7 @@ SET(${DOTNETTOOL}_SOURCE_FILES ) ADD_EXECUTABLE(${DOTNETTOOL} ${${DOTNETTOOL}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${DOTNETTOOL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE}) -TARGET_LINK_LIBRARIES(${DOTNETTOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON} ${TAC_COMMON}) +TARGET_LINK_LIBRARIES(${DOTNETTOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON} ${TAC_COMMON} ${MULTI_TARGET_RESOLVER}) SET(PREFER_DOTNET_AOT_PLUGIN "prefer_dotnet_aot_plugin") SET(${PREFER_DOTNET_AOT_PLUGIN}_SOURCE_FILES @@ -229,7 +237,7 @@ SET(${DELETE_UNUSED_LIBRARY_PLUGIN}_SOURCE_FILES ) ADD_LIBRARY(${DELETE_UNUSED_LIBRARY_PLUGIN} SHARED ${${DELETE_UNUSED_LIBRARY_PLUGIN}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${DELETE_UNUSED_LIBRARY_PLUGIN} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB}) -TARGET_LINK_LIBRARIES(${DELETE_UNUSED_LIBRARY_PLUGIN} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL}) +TARGET_LINK_LIBRARIES(${DELETE_UNUSED_LIBRARY_PLUGIN} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL} ${MULTI_TARGET_RESOLVER}) CONFIGURE_FILE(dotnet-launcher.pc.in dotnet-launcher.pc @ONLY) @@ -241,6 +249,7 @@ INSTALL(TARGETS ${DOTNET_CORERUN} DESTINATION ${BINDIR}) INSTALL(TARGETS ${DOTNET_HYDRA_LOADER} DESTINATION ${BINDIR}) INSTALL(TARGETS ${TAC_COMMON} DESTINATION ${LIBDIR}) INSTALL(TARGETS ${NI_COMMON} DESTINATION ${LIBDIR}) +INSTALL(TARGETS ${MULTI_TARGET_RESOLVER} DESTINATION ${LIBDIR}) INSTALL(TARGETS ${TPATOOL} DESTINATION ${BINDIR}) INSTALL(TARGETS ${DOTNETTOOL} DESTINATION ${BINDIR}) INSTALL(TARGETS ${PREFER_DOTNET_AOT_PLUGIN} DESTINATION ${INSTALL_MDPLUGIN_DIR}) diff --git a/NativeLauncher/inc/multi_target_resolver.h b/NativeLauncher/inc/multi_target_resolver.h new file mode 100644 index 0000000..380fcd0 --- /dev/null +++ b/NativeLauncher/inc/multi_target_resolver.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MULTI_TAEGET_RESOLVER_H__ +#define __MULTI_TAEGET_RESOLVER_H__ + +/** + * @brief Resolve platform specific files which is in bin/runtimes directory + All contents which is in best matched RID and TFM path are moved to the "bin" folder. + * @param[in] application root path + * @return 0 if success, otherwise -1 + */ +int resolvePlatformSpecificFiles(const std::string& appRootPath); + +/** + * @brief resolve bin/runtimes directory if exist. + * @return 0 if success, otherwise -1 + */ +int resolveAllApps(); + +#endif /* __MULTI_TAEGET_RESOLVER_H__ */ diff --git a/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc b/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc index bd248ac..139d70e 100644 --- a/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc +++ b/NativeLauncher/installer-plugin/delete_unused_library_plugin.cc @@ -16,8 +16,8 @@ #include "log.h" #include "utils.h" +#include "multi_target_resolver.h" -#include #include #ifdef LOG_TAG @@ -29,124 +29,6 @@ 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) { @@ -173,8 +55,7 @@ extern "C" int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc, const char* pkgId) return 0; } - std::string appBinPath = concatPath(rootPath, "bin"); - if (!resolvePlatformSpecificFiles(appBinPath)) { + if (resolvePlatformSpecificFiles(rootPath) != 0) { _ERR("Failed to resolve platform specific resources of nuget"); } diff --git a/NativeLauncher/tool/dotnettool.cc b/NativeLauncher/tool/dotnettool.cc index 4b9e579..c5d5af2 100644 --- a/NativeLauncher/tool/dotnettool.cc +++ b/NativeLauncher/tool/dotnettool.cc @@ -17,6 +17,7 @@ #include "utils.h" #include "ni_common.h" #include "tac_common.h" +#include "multi_target_resolver.h" #include #include @@ -44,6 +45,8 @@ void DisplayUsage() { " --tac-disable-pkg - Disable TAC for package\n" " --tac-enable-pkg - Enable TAC for package\n" " --ibc-dir - Specify a directory containing IBC files\n" + " --resolve-all-app - Remove unused multi-targeting files of all apps\n" + " (this option is used for FOTA script or test)\n" "\n" "Options:\n" " --r2r - Generate a Ready-To-Run image (disable: /FragileNonVersionable)\n" @@ -269,6 +272,13 @@ int main(int argc, char* argv[]) it = args.erase(it); } } + //sh-3.2# dotnettool --resolve-all-app + else if (cmd == "--resolve-all-app") { + int ret = resolveAllApps(); + if (ret != 0) { + fprintf(stderr, "Failed to remove unused multi-targeting files\n"); + } + } else { fprintf(stderr, "Unknown option [%s]\n", cmd.c_str()); DisplayUsage(); diff --git a/NativeLauncher/tool/multi_target_resolver.cc b/NativeLauncher/tool/multi_target_resolver.cc new file mode 100644 index 0000000..317aae4 --- /dev/null +++ b/NativeLauncher/tool/multi_target_resolver.cc @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include "log.h" +#include "utils.h" +#include "multi_target_resolver.h" + +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; +} + +// move all files under a certain directory to another directory +// ownership / permission / smack label are not changed +static bool moveAllFilesTo(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 iterate directory: %s", error.what()); + return false; + } + + return true; +} + +int resolvePlatformSpecificFiles(const std::string& rootPath) +{ + std::string appBinPath = concatPath(rootPath, "bin"); + std::string runtimesPath = concatPath(appBinPath, "runtimes"); + + // if runtimes directory doesnot exist, return 0 + if (!isDirectory(runtimesPath)) { + return 0; + } + + // 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 (%s)", rid.c_str()); + // 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 (!moveAllFilesTo(nativePath, appBinPath)) { + _ERR("Failed to copy files from native path"); + return -1; + } + } + + // 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 (%s)", tfm .c_str()); + // copy all files from tfmPath to appBintPath + if (!moveAllFilesTo(tfmPath, appBinPath)) { + _ERR("Failed to copy files from tfm path"); + return -1; + } + } + } + + break; + } + } + + // remove runtimes directory + if (!removeAll(runtimesPath)) { + _ERR("Failed to remove bin/runtimes directory"); + return -1; + } + + return 0; +} + +// callback function of "pkgmgrinfo_appinfo_filter_foreach_appinfo" +static int appResolveCb(pkgmgrinfo_appinfo_h handle, void *user_data) +{ + int ret = 0; + char* rootPath; + + ret = pkgmgrinfo_appinfo_get_root_path(handle, &rootPath); + if (ret != PMINFO_R_OK) { + fprintf(stderr, "Failed to get root path"); + return -1; + } + + if (resolvePlatformSpecificFiles(rootPath) != 0) { + fprintf(stderr, "Failed to resolve platform specific resources (%s)\n", rootPath); + return -1; + } + + return 0; +} + +int resolveAllApps() +{ + int ret = 0; + + pkgmgrinfo_appinfo_filter_h handle; + ret = pkgmgrinfo_appinfo_filter_create(&handle); + if (ret != PMINFO_R_OK) { + return -1; + } + + ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_TYPE, "dotnet"); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_filter_destroy(handle); + return -1; + } + + ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, appResolveCb, NULL); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_filter_destroy(handle); + return -1; + } + pkgmgrinfo_appinfo_filter_destroy(handle); + + return 0; +} + diff --git a/packaging/715.dotnet_regen_app_ni.patch.sh b/packaging/715.dotnet_regen_app_ni.patch.sh index 1a6dda6..85008df 100644 --- a/packaging/715.dotnet_regen_app_ni.patch.sh +++ b/packaging/715.dotnet_regen_app_ni.patch.sh @@ -6,4 +6,4 @@ PATH=/usr/bin:/bin:/usr/sbin:/sbin /usr/bin/dotnettool --tac-regen-all /usr/bin/dotnettool --ni-regen-all-app - +/usr/bin/dotnettool --resolve-all-app diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index 7d1ee19..80685dc 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -196,6 +196,7 @@ chsmack -a User /usr/bin/dotnet-nui-loader %{_libdir}/libdotnet_launcher_core.so %{_libdir}/libni_common.so %{_libdir}/libtac_common.so +%{_libdir}/libmulti_target_resolver.so %{_tmpfilesdir}/%{name}.conf /usr/share/parser-plugins/dotnet-launcher.info %{_framework_dir}/Tizen.Runtime.dll -- 2.7.4