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.
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
)
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
)
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)
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})
--- /dev/null
+/*
+ * 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__ */
#include "log.h"
#include "utils.h"
+#include "multi_target_resolver.h"
-#include <vconf.h>
#include <vector>
#ifdef LOG_TAG
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<std::string> getRidFallbackGraph()
-{
- std::vector<std::string> RID_FALLBACK_GRAPH;
- char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
- if (tizen_rid) {
- std::vector<std::string> 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<std::string> 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<std::string> getTfmFallbackGraph()
-{
- std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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)
{
return 0;
}
- std::string appBinPath = concatPath(rootPath, "bin");
- if (!resolvePlatformSpecificFiles(appBinPath)) {
+ if (resolvePlatformSpecificFiles(rootPath) != 0) {
_ERR("Failed to resolve platform specific resources of nuget");
}
#include "utils.h"
#include "ni_common.h"
#include "tac_common.h"
+#include "multi_target_resolver.h"
#include <vector>
#include <cstring>
" --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"
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();
--- /dev/null
+/*
+ * 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 <string>
+
+#include <pkgmgr-info.h>
+#include <vconf.h>
+
+#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<std::string> getRidFallbackGraph()
+{
+ std::vector<std::string> RID_FALLBACK_GRAPH;
+ char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
+ if (tizen_rid) {
+ std::vector<std::string> 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<std::string> 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<std::string> getTfmFallbackGraph()
+{
+ std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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;
+}
+
/usr/bin/dotnettool --tac-regen-all
/usr/bin/dotnettool --ni-regen-all-app
-
+/usr/bin/dotnettool --resolve-all-app
%{_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