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