Modified to support crossgen2 (#330)
[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                 "       --ibc-dir                 - Specify a directory containing IBC files\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                 "       --r2r                     - Generate a Ready-To-Run image (disable: /FragileNonVersionable)\n"
60                 "       --compatibility           - Compatibility mode for older versions of crossgen\n"
61                 "                                   (replaces /r with /Trusted_Platform_Assemblies)\n"
62                 "       --verbose                 - Display verbose information\n"
63                 "       --instrument              - Generate an instrumented image for profiling (enable: /Tuning)\n"
64                 "       --crossgen2               - Use crossgen2\n"
65                 "       --inputbubble             - Use inputbubble (run with --crossgen2 option)\n"
66                 "       --no-pipeline             - Compile the dlls individually (run with --crossgen2 option)\n"
67
68                 "\n"
69                 "Usage: dotnettool [options] [command] [arguments]\n"
70                 "\n"
71                 "Example:\n"
72                 "1. Create native image for dlls and exes under platform directories\n"
73                 "   # dotnettool --ni-system\n"
74                 "2. Create native image for dll\n"
75                 "   # dotnettool --ni-dll /usr/bin/Tizen.Runtime.dll\n"
76                 "3. Create native image under the package's bin and lib directory\n"
77                 "   # dotnettool --ni-pkg org.tizen.FormsGallery\n"
78                 "4. Regenerate native images for all installed .net packages with ready-to-run option\n"
79                 "   # dotnettool --r2r --ni-regen-all-app\n"
80                 "5. Create native image for dll based on the IBC data\n"
81                 "   # dotnettool --ibc-dir /tmp/ibcdata/ --ni-dll /usr/bin/Tizen.Runtime.dll\n"
82                 "6. Remove profile for package\n"
83                 "   # dotnettool --rm-app-profile org.tizen.FormsGallery\n"
84                 "\n");
85 }
86
87 int main(int argc, char* argv[])
88 {
89         argc--;
90         argv++;
91
92         long starttime;
93         long endtime;
94         struct timeval tv;
95         gettimeofday(&tv, NULL);
96         starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
97
98         if (argc <= 0) {
99                 DisplayUsage();
100                 return -1;
101         }
102
103         //sh-3.2# dotnettool --[r2r|compatibility|instrument|verbose]
104         DWORD flags = 0;
105         std::vector<std::string> args;
106         for (char** it = argv; it != argv+argc; it++) {
107                 if (!strncmp(*it, "-?", 2) || !strncmp(*it, "-h", 2) || !strncmp(*it, "--help", 6)) {
108                         DisplayUsage();
109                         return 0;
110                 } else if (!strncmp(*it, "--r2r", 5)) {
111                         flags |= NI_FLAGS_ENABLER2R;
112                 } else if (!strncmp(*it, "--compatibility", 15)) {
113                         flags |= NI_FLAGS_COMPATIBILITY;
114                 } else if (!strncmp(*it, "--instrument", 12)) {
115                         flags |= NI_FLAGS_INSTRUMENT;
116                 } else if (!strncmp(*it, "--verbose", 9)) {
117                         flags |= NI_FLAGS_VERBOSE;
118                 } else if (!strncmp(*it, "--crossgen2", 11)) {
119                         flags |= NI_FLAGS_USE_CROSSGEN2;
120                 } else if (!strncmp(*it, "--inputbubble", 13)) {
121                         flags |= NI_FLAGS_INPUT_BUBBLE;
122                 } else if (!strncmp(*it, "--no-pipeline", 13)) {
123                         flags |= NI_FLAGS_NO_PIPELINE;
124                 } else {
125                         args.push_back(*it);
126                 }
127         }
128
129         //sh-3.2# dotnettool --ibc-dir [ibcDirectory]
130         for (auto it = args.begin(); it != args.end(); ) {
131                 if (*it == "--ibc-dir") {
132                         it = args.erase(it);
133
134                         std::string ibcFilePath = std::string(*it);
135                         if (!isDirectory(ibcFilePath)) {
136                                 _SERR("IBC path is missing or not exist");
137                                 return -1;
138                         }
139
140                         setenv("COMPlus_IBCFileDir", const_cast<char *>(ibcFilePath.c_str()), 1);
141                         setenv("COMPlus_UseIBCFile", const_cast<char *>("1"), 1);
142                         it = args.erase(it);
143                 } else {
144                         ++it;
145                 }
146         }
147
148         if (initNICommon() != NI_ERROR_NONE) {
149                 return -1;
150         }
151
152         std::vector<std::string>::iterator it = args.begin();
153         std::string cmd = std::string(*it);
154         it = args.erase(it);
155
156         //sh-3.2# dotnettool --ni-system
157         if (cmd == "--ni-system") {
158                 int ret = createNIPlatform(flags);
159                 if (ret != NI_ERROR_NONE) {
160                         _SERR("Failed to generate system NI");
161                 }
162         }
163         //sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
164         else if (cmd == "--ni-dll") {
165                 if (args.size() < 1) {
166                         _SERR("DLL path is missing");
167                 }
168                 while (it != args.end()) {
169                         std::string dll = std::string(*it);
170                         int ret = createNIDll(dll, flags);
171                         if (ret != NI_ERROR_NONE) {
172                                 _SERR("Failed to generate NI file [%s]", dll.c_str());
173                                 break;
174                         }
175                         it = args.erase(it);
176                 }
177         }
178         //sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
179         else if (cmd == "--ni-pkg") {
180                 if (args.size() < 1) {
181                         _SERR("Package name is missing");
182                 }
183                 while (it != args.end()) {
184                         std::string pkg = std::string(*it);
185                         int ret = createNIUnderPkgRoot(pkg, flags);
186                         if (ret != NI_ERROR_NONE) {
187                                 _SERR("Failed to generate app NI [%s]", pkg.c_str());
188                                 break;
189                         }
190                         it = args.erase(it);
191                 }
192         }
193         //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
194         else if (cmd == "--ni-dir") {
195                 if (args.size() < 1) {
196                         _SERR("Directory path is missing");
197                 }
198                 while (it != args.end()) {
199                         const std::string dir = std::string(*it);
200                         int ret = createNIUnderDirs(dir, flags);
201                         if (ret != NI_ERROR_NONE) {
202                                 _SERR("Failed to generate NI directory");
203                                 break;
204                         }
205                         it = args.erase(it);
206                 }
207         }
208         //sh-3.2# dotnettool --ni-reset-system
209         else if (cmd == "--ni-reset-system") {
210                 removeNIPlatform();
211         }
212         //sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
213         else if (cmd == "--ni-reset-pkg") {
214                 if (args.size() < 1) {
215                         _SERR("Package name is missing");
216                 }
217                 while (it != args.end()) {
218                         std::string pkg = std::string(*it);
219                         int ret = removeNIUnderPkgRoot(pkg);
220                         if (ret != NI_ERROR_NONE) {
221                                 _SERR("Failed to remove dlls for given package [%s]", pkg.c_str());
222                                 break;
223                         }
224                         it = args.erase(it);
225                 }
226         }
227         //sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
228         else if (cmd == "--ni-reset-dir") {
229                 if (args.size() < 1) {
230                         _SERR("Directory path is missing");
231                 }
232                 while (it != args.end()) {
233                         const std::string dir = std::string(*it);
234                         removeNIUnderDirs(dir);
235                         it = args.erase(it);
236                 }
237         }
238         //sh-3.2# dotnettool --ni-regen-all-app
239         else if (cmd == "--ni-regen-all-app") {
240                 int ret = regenerateAppNI(flags);
241                 if (ret != NI_ERROR_NONE) {
242                         _SERR("Failed to regenerate all app NI");
243                 }
244         }
245         //sh-3.2# dotnettool --tac-regen-all
246         else if (cmd == "--tac-regen-all") {
247                 int ret = regenerateTACNI(flags);
248                 if (ret != NI_ERROR_NONE) {
249                         _SERR("Failed to regenerate all TAC");
250                 }
251         }
252         //sh-3.2# dotnettool --tac-restore-db
253         else if (cmd == "--tac-restore-db") {
254                 int ret = tac_restoreDB();
255                 if (ret != TAC_ERROR_NONE) {
256                         _SERR("Failed to restore TAC db");
257                 }
258                 ret = tlc_restoreDB();
259                 if (ret != TAC_ERROR_NONE) {
260                         _SERR("Failed to restore TLC db");
261                 }
262         }
263         //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
264         else if (cmd == "--tac-enable-pkg") {
265                 if (args.size() < 1) {
266                         _SERR("Package name is missing");
267                 }
268                 while (it != args.end()) {
269                         std::string pkg = std::string(*it);
270                         int ret = enableTACPackage(pkg);
271                         if (ret != TAC_ERROR_NONE) {
272                                 _SERR("Failed to enable tac [%s]", pkg.c_str());
273                                 break;
274                         }
275                         it = args.erase(it);
276                 }
277         }
278         //sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
279         else if (cmd == "--tac-disable-pkg") {
280                 if (args.size() < 1) {
281                         _SERR("Package name is missing");
282                 }
283                 while (it != args.end()) {
284                         std::string pkg = std::string(*it);
285                         int ret = disableTACPackage(pkg);
286                         if (ret != TAC_ERROR_NONE) {
287                                 _SERR("Failed to disable tac [%s]", pkg.c_str());
288                                 break;
289                         }
290                         it = args.erase(it);
291                 }
292         }
293         //sh-3.2# dotnettool --resolve-all-app
294         else if (cmd == "--resolve-all-app") {
295                 int ret = resolveAllApps();
296                 if (ret != 0) {
297                         _SERR("Failed to remove unused multi-targeting files");
298                 }
299         }
300         //sh-3.2# dotnettool --rm-app-profile [pkgId] [pkgId] ...
301         else if (cmd == "--rm-app-profile") {
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                         if (removeAppProfileData(pkg) != NI_ERROR_NONE) {
308                                 _SERR("Failed to remove [%s] profile data", pkg.c_str());
309                         }
310                         it = args.erase(it);
311                 }
312         }
313         //sh-3.2# dotnettool --rm-all-app-profile
314         else if (cmd == "--rm-all-app-profile") {
315                 removeAllAppProfileData();
316         }
317         else {
318                 _SERR("Unknown option [%s]", cmd.c_str());
319                 DisplayUsage();
320         }
321
322         finalizeNICommon();
323
324         gettimeofday(&tv, NULL);
325         endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
326         _SOUT("\nSpend time for dotnettool is [%d]ms", (int)(endtime - starttime));
327
328         return 0;
329 }