2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <pkgmgr-info.h>
23 #include "multi_target_resolver.h"
25 static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version"; //8.0.0:7.0.0:6.5.0:6.0.0:5.5.0:5.0.0:4.0.0
26 static const char* __TIZEN_TFM_SUPPORT_KEY = "db/dotnet/tizen_tfm_support"; //net6.0-tizen8.0:net6.0-tizen:net6.0:tizen10.0:tizen90:tizen80:tizen70:tizen60:tizen50:tizen40
30 ---------|---------------------|-----------------------
31 1 | tizen.X.Y.Z-{arch} | netX.Y-tizenX.Y ~ 6.5
32 2 | tizen.X.Y.Z | netX.Y-tizen
33 3 | tizen-{arch}, tizen | netX.Y
34 4 | linux-{arch}, linux | tizen10.0 ~ 40
35 5 | unix-{arch}, unix | net5.0
36 6 | any | netcoreapp3.1 ~ 1.0
37 7 | base | netstandard2.1 ~ 1.0
40 // Guided by Appfw, vconf daemon does not run at mic stage.
41 // So vconf_get_* api does not work normally.
42 // Therefore, it is changed to manage as a file instead of using vconf API.
43 // /usr/share/dotnet.tizen/lib/dotnet_resolving.info
44 static std::string getDotnetResolvingInfo(const char* key)
46 std::ifstream ifs(DOTNET_RESOLVING_INFO_PATH);
48 while (std::getline(ifs, line)) {
49 if (!strcmp(line.substr(0, line.find(" ")).c_str(), key)) {
51 return line.substr(line.rfind(" ") + 1);
57 static std::vector<std::string> getRidFallbackGraph()
59 std::string tizen_rid_version = getDotnetResolvingInfo(__TIZEN_RID_VERSION_KEY);
60 std::vector<std::string> rid_version;
61 std::vector<std::string> RID_FALLBACK_GRAPH;
62 splitPath(tizen_rid_version, rid_version);
63 for (auto& ridVersion : rid_version) {
64 RID_FALLBACK_GRAPH.push_back(std::string("tizen." + ridVersion + "-" + ARCHITECTURE_IDENTIFIER));
65 RID_FALLBACK_GRAPH.push_back(std::string("tizen." + ridVersion));
68 std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
69 for (auto& os : RID_FALLBACK_OS) {
70 RID_FALLBACK_GRAPH.push_back(std::string(os + "-" + ARCHITECTURE_IDENTIFIER));
71 RID_FALLBACK_GRAPH.push_back(std::string(os));
73 RID_FALLBACK_GRAPH.push_back("any");
74 RID_FALLBACK_GRAPH.push_back("base");
76 return RID_FALLBACK_GRAPH;
79 static std::vector<std::string> getTfmFallbackGraph()
81 std::string tizen_tfm_support = getDotnetResolvingInfo(__TIZEN_TFM_SUPPORT_KEY);
82 std::vector<std::string> TFM_FALLBACK_GRAPH;
83 splitPath(tizen_tfm_support, TFM_FALLBACK_GRAPH);
84 TFM_FALLBACK_GRAPH.push_back("net5.0");
86 std::vector<std::string> netcoreapp_version = {"3.1", "3.0", "2.2", "2.1", "2.0", "1.1", "1.0"};
87 for (auto& version : netcoreapp_version) {
88 TFM_FALLBACK_GRAPH.push_back(std::string("netcoreapp" + version));
90 std::vector<std::string> netstandard_version = {"2.1", "2.0", "1.6", "1.5", "1.4", "1.3", "1.2", "1.1", "1.0"};
91 for (auto& version : netstandard_version) {
92 TFM_FALLBACK_GRAPH.push_back(std::string("netstandard" + version));
95 return TFM_FALLBACK_GRAPH;
98 // move all files under a certain directory to another directory
99 // ownership / permission / smack label are not changed
100 static bool moveAllFilesTo(const std::string& from, const std::string& to)
102 std::vector<std::string> files;
104 // make file list to move
105 for (auto& path : bf::recursive_directory_iterator(from)) {
106 std::string filePath = path.path().string();
107 if (isFile(filePath)) {
108 files.push_back(filePath);
112 // move files to target directory
113 for (auto& f : files) {
114 bf::rename(f, concatPath(to, getFileName(f)));
116 } catch (const bf::filesystem_error& error) {
117 _ERR("Failed to iterate directory: %s", error.what());
124 int resolvePlatformSpecificFiles(const std::string& rootPath)
126 std::string appBinPath = concatPath(rootPath, "bin");
127 std::string runtimesPath = concatPath(appBinPath, "runtimes");
129 // if runtimes directory doesnot exist, return 0
130 if (!isDirectory(runtimesPath)) {
134 // found best matched rid and tfm directory and copy all files to bin directory
135 std::vector<std::string> ridFallbackGraph = getRidFallbackGraph();
137 for (auto& rid : bf::recursive_directory_iterator(runtimesPath)) {
138 std::string ridPath = rid.path().string();
139 if (bf::is_directory(ridPath) && strstr(ridPath.c_str(), ARCHITECTURE_IDENTIFIER) != NULL) {
140 for (auto& ridFG : ridFallbackGraph) {
141 if (!strcmp(getFileName(ridPath).c_str(), ridFG.c_str())) {
142 std::string nativePath = concatPath(ridPath, "native");
143 if (isDirectory(nativePath)) {
144 _INFO("Found best matched rid (%s)", ridFG.c_str());
145 // copy all files from bin/runtimes/${rid}/native to appBintPath if exist
146 if (!moveAllFilesTo(nativePath, appBinPath)) {
147 _ERR("Failed to copy files from native path");
152 // found best matched tfm folder in the found rid folder
153 std::string libPath = concatPath(ridPath, "lib");
154 std::vector<std::string> tfmFallbackGraph = getTfmFallbackGraph();
155 for (auto& tfmFG : tfmFallbackGraph) {
156 std::string tfmPath = concatPath(libPath, tfmFG);
157 if (isDirectory(tfmPath)) {
158 _INFO("Found best matched tfm (%s)", tfmFG .c_str());
159 // copy all files from bin/runtimes/${rid}/lib/${tfm} to appBintPath if exist
160 if (!moveAllFilesTo(tfmPath, appBinPath)) {
161 _ERR("Failed to copy files from tfm path");
173 } catch (const bf::filesystem_error& error) {
174 _ERR("Failed to recursive directory: %s", error.what());
177 // remove runtimes directory
178 if (!removeAll(runtimesPath)) {
179 _ERR("Failed to remove bin/runtimes directory");
186 // callback function of "pkgmgrinfo_appinfo_filter_foreach_appinfo"
187 static int appResolveCb(pkgmgrinfo_appinfo_h handle, void *user_data)
192 ret = pkgmgrinfo_appinfo_get_root_path(handle, &rootPath);
193 if (ret != PMINFO_R_OK) {
194 _SERR("Failed to get root path");
198 if (resolvePlatformSpecificFiles(rootPath) != 0) {
199 _SERR("Failed to resolve platform specific resources (%s)", rootPath);
206 void resolveAllApps()
210 pkgmgrinfo_appinfo_filter_h handle;
211 ret = pkgmgrinfo_appinfo_filter_create(&handle);
212 if (ret != PMINFO_R_OK) {
213 _SERR("Failed to create pkgmgrinfo");
217 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_TYPE, "dotnet");
218 if (ret != PMINFO_R_OK) {
219 pkgmgrinfo_appinfo_filter_destroy(handle);
220 _SERR("Failed to add pkgmgrinfo filter app type");
224 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, appResolveCb, NULL);
225 if (ret != PMINFO_R_OK) {
226 pkgmgrinfo_appinfo_filter_destroy(handle);
227 _SERR("Failed to remove unused multi-targeting files");
230 pkgmgrinfo_appinfo_filter_destroy(handle);