Separate the code related to the profile data into a profile_common file
[platform/core/dotnet/launcher.git] / NativeLauncher / tool / dotnettool.cc
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "utils.h"
18 #include "ni_common.h"
19 #include "tac_common.h"
20 #include "profile_common.h"
21 #include "multi_target_resolver.h"
22 #include "log.h"
23
24 #include <vector>
25 #include <cstring>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <sys/time.h>
29 #include <app_common.h>
30
31 void DisplayUsage() {
32         _SOUT(
33                 "\n"
34                 "Dotnet Tool Version: 1.0\n"
35                 "\n"
36                 "Commands:\n"
37                 "       -h, --help                - Show this help message\n"
38                 "       --ni-system               - Create NI under System DLLs\n"
39                 "       --ni-dll                  - Create NI for DLL\n"
40                 "       --ni-pkg                  - Create NI for package\n"
41                 "                                   (If package is installed under RO area, NI files are generated under RW area)\n"
42                 "       --ni-dir                  - Create NI for directory\n"
43                 "       --ni-reset-system         - Remove System NI files\n"
44                 "       --ni-reset-pkg            - Remove App NI files\n"
45                 "       --ni-reset-dir            - Remove NI for directory\n"
46                 "       --ni-regen-all-app        - Re-generate All App NI files\n"
47                 "       --tac-regen-all           - Re-generate All TAC files\n"
48                 "       --tac-restore-db          - Restore TAC Database\n"
49                 "       --tac-disable-pkg         - Disable TAC for package\n"
50                 "       --tac-enable-pkg          - Enable TAC for package\n"
51                 "       --resolve-all-app         - Remove unused multi-targeting files of all apps\n"
52                 "                                   (this option is used for FOTA script or test)\n"
53                 "       --rm-app-profile          - Remove application profile of given packages for all users\n"
54                 "                                   (this option should be run as root)\n"
55                 "       --rm-all-app-profile      - Remove application profile of all packages for all users\n"
56                 "                                   (this option should be run as root)\n"
57                 "\n"
58                 "Options:\n"
59                 "       --mibc                    - Specify Mibc files. Sepatated with ':'.\n"
60                 "       --verbose                 - Display verbose information\n"
61                 "       --inputbubble             - Compile input assemblies into one bubble with the assemblies described at --inputbubbleref option\n"
62                 "                                   Note!: If you do not have an accurate understanding of Bubble, do not use this option.\n"
63                 "                                          All assemblies in the bubble must be guaranteed to be compiled to the native image before execution.\n"
64                 "                                          If an uncompiled assembly is included in the bubble during execution, an unknown error may occur.\n"
65                 "                                          If --inputbubbleref option doesnot be set, only input files are included to bubble. \n"
66                 "       --inputbubbleref          - Input bubble reference file(s) to be added to bubble (used with --inputbubble option)\n"
67                 "       --ref                     - Reference file(s) for compilation\n"
68                 "                                   (system paths are set automatically.)\n"
69                 "       --no-pipeline             - Compile the dlls individually\n"
70                 "       --print-cmd               - Print command and options\n"
71                 "       --skip-ro-app             - Skip re-generate NI for apps installed RO area\n"
72                 "                                   (This option works with --ni-regen-all-app only)\n"
73                 "\n"
74                 "Usage: dotnettool [options] [command] [arguments]\n"
75                 "\n"
76                 "Example:\n"
77                 "1. Create native image for dlls and exes under platform directories\n"
78                 "   # dotnettool --ni-system\n"
79                 "2. Create native image for dll\n"
80                 "   # dotnettool --ni-dll /usr/bin/Tizen.Runtime.dll\n"
81                 "3. Create native image under the package's bin and lib directory\n"
82                 "   # dotnettool --ni-pkg org.tizen.FormsGallery\n"
83                 "4. Regenerate native images for all installed .net packages\n"
84                 "   # dotnettool --ni-regen-all-app\n"
85                 "5. Create native image for dll based on the Mibc data\n"
86                 "   # dotnettool --mibc /tmp/ibcdata/in.mibc --ni-dll /usr/bin/Tizen.Runtime.dll\n"
87                 "6. Remove profile for package\n"
88                 "   # dotnettool --rm-app-profile org.tizen.FormsGallery\n"
89                 "\n");
90 }
91
92 int main(int argc, char* argv[])
93 {
94         argc--;
95         argv++;
96
97         long starttime;
98         long endtime;
99         struct timeval tv;
100         gettimeofday(&tv, NULL);
101         starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
102
103         if (argc <= 0) {
104                 DisplayUsage();
105                 return -1;
106         }
107
108         NIOption* opt = getNIOption();
109         if (opt == nullptr) {
110                 _SERR("Fail to create option structure.");
111                 return -1;
112         }
113
114         std::vector<std::string> args;
115         for (int i = 0; i < argc; ++i) {
116                 std::string arg = argv[i];
117
118                 if ((arg == "-?") || (arg == "-h") || (arg == "--h")) {
119                         DisplayUsage();
120                         return 0;
121                 } else if (arg == "--verbose") {
122                         opt->flags |= NI_FLAGS_VERBOSE;
123                 } else if (arg == "--inputbubble") {
124                         opt->flags |= NI_FLAGS_INPUT_BUBBLE;
125                 } else if (arg == "--no-pipeline") {
126                         opt->flags |= NI_FLAGS_NO_PIPELINE;
127                 } else if (arg == "--print-cmd") {
128                         opt->flags |= NI_FLAGS_PRINT_CMD;
129                 } else if (arg == "--skip-ro-app") {
130                         opt->flags |= NI_FLAGS_SKIP_RO_APP;
131                 } else if (arg == "--mibc") {
132                         ++i;
133                         if (i >= argc) {
134                                 _SOUT("File path containing Mibc files should be followed for --mibc option");
135                                 DisplayUsage();
136                                 return 0;
137                         }
138
139                         opt->flags |= NI_FLAGS_MIBC;
140
141                         std::vector<std::string> paths;
142                         splitPath(std::string(argv[i]), paths);
143                         for (const auto &path : paths) {
144                                 if (!isFile(path) || isDirectory(path)) {
145                                         _SERR("Mibc file path is missing or does not exist");
146                                         return -1;
147                                 }
148                                 opt->mibcPath.push_back(path);
149                         }
150                 } else if (arg == "--inputbubbleref") {
151                         ++i;
152                         if (i >= argc) {
153                                 _SOUT("Path for references should be followed for --inputbubbleref option");
154                                 DisplayUsage();
155                                 return 0;
156                         }
157
158                         opt->flags |= NI_FLAGS_INPUT_BUBBLE_REF;
159
160                         std::vector<std::string> files;
161                         splitPath(std::string(argv[i]), files);
162                         for (const auto &f : files) {
163                                 opt->inputBubbleRefFiles.push_back(f);
164                         }
165                 } else if (arg == "--ref") {
166                         ++i;
167                         if (i >= argc) {
168                                 _SOUT("Path for references should be followed for --ref option");
169                                 DisplayUsage();
170                                 return 0;
171                         }
172
173                         std::vector<std::string> files;
174                         splitPath(std::string(argv[i]), files);
175                         for (const auto &f : files) {
176                                 opt->refFiles.push_back(f);
177                         }
178                 } else {
179                         args.push_back(arg);
180                 }
181         }
182
183         if (opt->flags & NI_FLAGS_INPUT_BUBBLE_REF && !(opt->flags & NI_FLAGS_INPUT_BUBBLE)) {
184                 _SERR("--inputbubbleref option should be used with --inputbubble option");
185                 DisplayUsage();
186                 return -1;
187         }
188
189         if (initNICommon() != NI_ERROR_NONE) {
190                 return -1;
191         }
192
193         std::vector<std::string>::iterator it = args.begin();
194         std::string cmd = std::string(*it);
195         it = args.erase(it);
196
197         //sh-3.2# dotnettool --ni-system [AssemblyDirectory] [AssemblyDirectory] ...
198         if (cmd == "--ni-system") {
199                 std::string inputs;
200                 while (it != args.end()) {
201                         const std::string dir = std::string(*it);
202                         inputs = inputs + ":" + dir;
203                         it = args.erase(it);
204                 }
205                 int ret = createNIPlatform(inputs, opt);
206                 if (ret != NI_ERROR_NONE) {
207                         _SERR("Failed to generate system NI");
208                 }
209         }
210         //sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
211         else if (cmd == "--ni-dll") {
212                 if (args.size() < 1) {
213                         _SERR("DLL path is missing");
214                 }
215                 std::vector<std::string> inputs;
216                 while (it != args.end()) {
217                         std::string dll = std::string(*it);
218                         inputs.push_back(dll);
219                         opt->refFiles.push_back(dll);
220                         if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
221                                 opt->inputBubbleRefFiles.push_back(dll);
222                         }
223                         it = args.erase(it);
224                 }
225
226                 for (auto &dll : inputs) {
227                         int ret = createNIDll(dll, opt);
228                         if (ret != NI_ERROR_NONE && ret != NI_ERROR_ALREADY_EXIST) {
229                                 _SERR("Failed to generate NI file [%s]", dll.c_str());
230                                 break;
231                         }
232                 }
233         }
234         //sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
235         else if (cmd == "--ni-pkg") {
236                 if (args.size() < 1) {
237                         _SERR("Package name is missing");
238                 }
239                 while (it != args.end()) {
240                         std::string pkg = std::string(*it);
241                         int ret = createNIUnderPkgRoot(pkg, opt);
242                         if (ret != NI_ERROR_NONE) {
243                                 _SERR("Failed to generate app NI [%s]", pkg.c_str());
244                                 break;
245                         }
246                         it = args.erase(it);
247                 }
248         }
249         //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
250         else if (cmd == "--ni-dir") {
251                 if (args.size() < 1) {
252                         _SERR("Directory path is missing");
253                 }
254                 std::string dir;
255                 while (it != args.end()) {
256                         if (!dir.empty()) {
257                                 dir += std::string(":");
258                         }
259                         dir += std::string(*it);
260                         it = args.erase(it);
261                 }
262                 if (createNIUnderDirs(dir, opt) != NI_ERROR_NONE) {
263                         _SERR("Failed to generate NI directory");
264                 }
265         }
266         //sh-3.2# dotnettool --ni-reset-system
267         else if (cmd == "--ni-reset-system") {
268                 removeNIPlatform();
269         }
270         //sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
271         else if (cmd == "--ni-reset-pkg") {
272                 if (args.size() < 1) {
273                         _SERR("Package name is missing");
274                 }
275                 while (it != args.end()) {
276                         std::string pkg = std::string(*it);
277                         int ret = removeNIUnderPkgRoot(pkg);
278                         if (ret != NI_ERROR_NONE) {
279                                 _SERR("Failed to remove dlls for given package [%s]", pkg.c_str());
280                                 break;
281                         }
282                         it = args.erase(it);
283                 }
284         }
285         //sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
286         else if (cmd == "--ni-reset-dir") {
287                 if (args.size() < 1) {
288                         _SERR("Directory path is missing");
289                 }
290                 while (it != args.end()) {
291                         const std::string dir = std::string(*it);
292                         removeNIUnderDirs(dir);
293                         it = args.erase(it);
294                 }
295         }
296         //sh-3.2# dotnettool --ni-regen-all-app
297         else if (cmd == "--ni-regen-all-app") {
298                 int ret = regenerateAppNI(opt);
299                 if (ret != NI_ERROR_NONE) {
300                         _SERR("Failed to regenerate all app NI");
301                 }
302         }
303         //sh-3.2# dotnettool --tac-regen-all
304         else if (cmd == "--tac-regen-all") {
305                 int ret = regenerateTACNI(opt);
306                 if (ret != NI_ERROR_NONE) {
307                         _SERR("Failed to regenerate all TAC");
308                 }
309         }
310         //sh-3.2# dotnettool --tac-restore-db
311         else if (cmd == "--tac-restore-db") {
312                 int ret = tac_restoreDB();
313                 if (ret != TAC_ERROR_NONE) {
314                         _SERR("Failed to restore TAC db");
315                 }
316                 ret = tlc_restoreDB();
317                 if (ret != TAC_ERROR_NONE) {
318                         _SERR("Failed to restore TLC db");
319                 }
320         }
321         //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
322         else if (cmd == "--tac-enable-pkg") {
323                 if (args.size() < 1) {
324                         _SERR("Package name is missing");
325                 }
326                 while (it != args.end()) {
327                         std::string pkg = std::string(*it);
328                         int ret = enableTACPackage(pkg);
329                         if (ret != TAC_ERROR_NONE) {
330                                 _SERR("Failed to enable tac [%s]", pkg.c_str());
331                                 break;
332                         }
333                         it = args.erase(it);
334                 }
335         }
336         //sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
337         else if (cmd == "--tac-disable-pkg") {
338                 if (args.size() < 1) {
339                         _SERR("Package name is missing");
340                 }
341                 while (it != args.end()) {
342                         std::string pkg = std::string(*it);
343                         int ret = disableTACPackage(pkg);
344                         if (ret != TAC_ERROR_NONE) {
345                                 _SERR("Failed to disable tac [%s]", pkg.c_str());
346                                 break;
347                         }
348                         it = args.erase(it);
349                 }
350         }
351         //sh-3.2# dotnettool --resolve-all-app
352         else if (cmd == "--resolve-all-app") {
353                 int ret = resolveAllApps();
354                 if (ret != 0) {
355                         _SERR("Failed to remove unused multi-targeting files");
356                 }
357         }
358         //sh-3.2# dotnettool --rm-app-profile [pkgId] [pkgId] ...
359         else if (cmd == "--rm-app-profile") {
360                 if (args.size() < 1) {
361                         _SERR("Package name is missing");
362                 }
363                 while (it != args.end()) {
364                         std::string pkg = std::string(*it);
365                         if (removeAppProfileData(pkg) != PROFILE_ERROR_NONE) {
366                                 _SERR("Failed to remove [%s] profile data", pkg.c_str());
367                         }
368                         it = args.erase(it);
369                 }
370         }
371         //sh-3.2# dotnettool --rm-all-app-profile
372         else if (cmd == "--rm-all-app-profile") {
373                 removeAllAppProfileData();
374         }
375         else {
376                 _SERR("Unknown option [%s]", cmd.c_str());
377                 DisplayUsage();
378         }
379
380         finalizeNICommon();
381
382         gettimeofday(&tv, NULL);
383         endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
384         _SOUT("\nSpend time for dotnettool is [%d]ms", (int)(endtime - starttime));
385
386         return 0;
387 }