Refactoring the dotnettool (#231)
[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
21 #include <vector>
22 #include <stdlib.h>
23 #include <sys/time.h>
24
25 void DisplayUsage() {
26         fprintf(stdout,
27                 "\n"
28                 "Dotnet Tool Version: 1.0\n"
29                 "\n"
30                 "Commands:\n"
31                 "       -h, --help                - Show this help message\n"
32                 "       --ni-system               - Create NI under System DLLs\n"
33                 "       --ni-dll                  - Create NI for DLL\n"
34                 "       --ni-pkg                  - Create NI for package\n"
35                 "       --ni-pkg-dll              - Create NI for DLL in package\n"
36                 "       --ni-dir                  - Create NI for directory\n"
37                 "       --ni-reset-system         - Remove System NI files\n"
38                 "       --ni-reset-pkg            - Remove App NI files\n"
39                 "       --ni-reset-dir            - Remove NI for directory\n"
40                 "       --ni-regen-all-app        - Re-generate All App NI files\n"
41                 "       --tac-regen-all           - Re-generate All TAC files\n"
42                 "       --tac-restore-db          - Restore TAC Database\n"
43                 "       --tac-disable-pkg         - Disable TAC for package\n"
44                 "       --tac-enable-pkg          - Enable TAC for package\n"
45                 "       --ibc-dir                 - Specify a directory containing IBC files\n"
46                 "\n"
47                 "Options:\n"
48                 "       --r2r                     - Generate a Ready-To-Run image (disable: /FragileNonVersionable)\n"
49                 "       --compatibility           - Compatibility mode for older versions of crossgen\n"
50                 "                                   (replaces /r with /Trusted_Platform_Assemblies)\n"
51                 "       --verbose                 - Display verbose information\n"
52                 "       --instrument              - Generate an instrumented image for profiling (enable: /Tuning)\n"
53                 "\n"
54                 "Usage: dotnettool [options] [command] [arguments]\n"
55                 "\n"
56                 "Example:\n"
57                 "1. Create native image for dlls and exes under platform directories\n"
58                 "   # dotnettool --ni-system\n"
59                 "2. Create native image for dll\n"
60                 "   # dotnettool --ni-dll /usr/bin/Tizen.Runtime.dll\n"
61                 "3. Create native image under the package's bin and lib directory\n"
62                 "   # dotnettool --ni-pkg org.tizen.FormsGallery\n"
63                 "4. Regenerate native images for all installed .net packages with ready-to-run option\n"
64                 "   # dotnettool --r2r --ni-regen-all-app\n"
65                 "5. Create native image for dll based on the IBC data\n"
66                 "   # dotnettool --ibc-dir /tmp/ibcdata/ --ni-dll /usr/bin/Tizen.Runtime.dll\n"
67                 "\n");
68 }
69
70 int main(int argc, char* argv[])
71 {
72         argc--;
73         argv++;
74
75         long starttime;
76         long endtime;
77         struct timeval tv;
78         gettimeofday(&tv, NULL);
79         starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
80
81         if (argc <= 0) {
82                 DisplayUsage();
83                 return -1;
84         }
85
86         NiCommonOption option = {std::string(), std::string(), std::string()};
87         if (initNICommon(&option) != NI_ERROR_NONE) {
88                 return -1;
89         }
90
91         //sh-3.2# dotnettool --[r2r|compatibility|instrument|verbose]
92         DWORD flags = 0;
93         std::vector<std::string> args;
94         for (char** it = argv; it != argv+argc; it++) {
95                 if (!strncmp(*it, "-?", 2) || !strncmp(*it, "-h", 2) || !strncmp(*it, "--help", 6)) {
96                         DisplayUsage();
97                         return 0;
98                 } else if (!strncmp(*it, "--r2r", 5)) {
99                         flags |= NI_FLAGS_ENABLER2R;
100                 } else if (!strncmp(*it, "--compatibility", 15)) {
101                         flags |= NI_FLAGS_COMPATIBILITY;
102                 } else if (!strncmp(*it, "--instrument", 12)) {
103                         flags |= NI_FLAGS_INSTRUMENT;
104                 } else if (!strncmp(*it, "--verbose", 9)) {
105                         flags |= NI_FLAGS_VERBOSE;
106                 } else {
107                         args.push_back(*it);
108                 }
109         }
110
111         //sh-3.2# dotnettool --ibc-dir [ibcDirectory]
112         for (auto it = args.begin(); it != args.end(); ) {
113                 if (*it == "--ibc-dir") {
114                         it = args.erase(it);
115
116                         std::string ibcFilePath = std::string(*it);
117                         if (!isDirectoryExist(ibcFilePath)) {
118                                 fprintf(stderr, "IBC path is missing or not exist\n");
119                                 return -1;
120                         }
121
122                         setenv("COMPlus_IBCFileDir", const_cast<char *>(ibcFilePath.c_str()), 1);
123                         setenv("COMPlus_UseIBCFile", const_cast<char *>("1"), 1);
124                 } else {
125                         ++it;
126                 }
127         }
128
129         std::vector<std::string>::iterator it = args.begin();
130         std::string cmd = std::string(*it);
131         it = args.erase(it);
132
133         //sh-3.2# dotnettool --ni-system
134         if (cmd == "--ni-system") {
135                 int ret = createNiPlatform(flags);
136                 if (ret != NI_ERROR_NONE) {
137                         fprintf(stderr, "Failed to generate system NI\n");
138                 }
139         }
140         //sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
141         else if (cmd == "--ni-dll") {
142                 if (args.size() < 1) {
143                         fprintf(stderr, "DLL path is missing\n");
144                 }
145                 while (it != args.end()) {
146                         std::string dll = std::string(*it);
147                         int ret = createNiDll(dll, flags);
148                         if (ret != NI_ERROR_NONE) {
149                                 fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
150                                 break;
151                         }
152                         it = args.erase(it);
153                 }
154         }
155         //sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
156         else if (cmd == "--ni-pkg") {
157                 if (args.size() < 1) {
158                         fprintf(stderr, "Package name is missing\n");
159                 }
160                 while (it != args.end()) {
161                         std::string pkg = std::string(*it);
162                         // if there is AOTed dlls under package root, that is skiped.
163                         int ret = createNiUnderPkgRoot(pkg, flags);
164                         if (ret == NI_ERROR_INVALID_PACKAGE) {
165                                 fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
166                                 break;
167                         } else if (ret != NI_ERROR_NONE) {
168                                 fprintf(stderr, "Failed to generate NI file [%s]\n", pkg.c_str());
169                                 break;
170                         }
171                         ret = createTACPkgRoot(pkg, flags);
172                         if (ret == NI_ERROR_INVALID_PACKAGE) {
173                                 fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
174                                 break;
175                         } else if (ret != NI_ERROR_NONE) {
176                                 fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkg.c_str());
177                                 break;
178                         }
179                         it = args.erase(it);
180                 }
181         }
182         //sh-3.2# dotnettool --ni-pkg-dll [pkgId] [pkgAssemblyPath] [pkgAssemblyPath] ...
183         else if (cmd == "--ni-pkg-dll") {
184                 if (args.size() < 2) {
185                         fprintf(stderr, "Package name or DLL path is missing\n");
186                 } else {
187                         std::string pkg = std::string(*it);
188                         it = args.erase(it);
189                         while (it != args.end()) {
190                                 std::string dll = std::string(*it);
191                                 int ret = createNiDllUnderPkgRoot(pkg, dll, flags);
192                                 if (ret == NI_ERROR_INVALID_PACKAGE) {
193                                         fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
194                                         break;
195                                 } else if (ret != NI_ERROR_NONE) {
196                                         fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
197                                         break;
198                                 }
199                                 it = args.erase(it);
200                         }
201                 }
202         }
203         //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
204         else if (cmd == "--ni-dir") {
205                 if (args.size() < 1) {
206                         fprintf(stderr, "Directory path is missing\n");
207                 }
208                 while (it != args.end()) {
209                         const std::string dir[] = {std::string(*it)};
210                         int ret = createNiUnderDirs(dir, 1, flags);
211                         if (ret != NI_ERROR_NONE) {
212                                 fprintf(stderr, "Failed to generate NI directory\n");
213                                 break;
214                         }
215                         it = args.erase(it);
216                 }
217         }
218         //sh-3.2# dotnettool --ni-reset-system
219         else if (cmd == "--ni-reset-system") {
220                 removeNiPlatform();
221         }
222         //sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
223         else if (cmd == "--ni-reset-pkg") {
224                 if (args.size() < 1) {
225                         fprintf(stderr, "Package name is missing\n");
226                 }
227                 while (it != args.end()) {
228                         std::string pkg = std::string(*it);
229                         int ret = removeNiUnderPkgRoot(pkg);
230                         if (ret == NI_ERROR_INVALID_PACKAGE) {
231                                 fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
232                                 break;
233                         } else if (ret != NI_ERROR_NONE) {
234                                 fprintf(stderr, "Failed to remove dlls for given package [%s]\n", pkg.c_str());
235                                 break;
236                         }
237                         ret = resetTACPackage(pkg);
238                         if (ret == TAC_ERROR_INVALID_PACKAGE) {
239                                 fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
240                                 break;
241                         } else if (ret != TAC_ERROR_NONE) {
242                                 fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkg.c_str());
243                                 break;
244                         }
245                         it = args.erase(it);
246                 }
247         }
248         //sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
249         else if (cmd == "--ni-reset-dir") {
250                 if (args.size() < 1) {
251                         fprintf(stderr, "Directory path is missing\n");
252                 }
253                 while (it != args.end()) {
254                         const std::string dir[] = {std::string(*it)};
255                         removeNiUnderDirs(dir, 1);
256                         it = args.erase(it);
257                 }
258         }
259         //sh-3.2# dotnettool --ni-regen-all-app
260         else if (cmd == "--ni-regen-all-app") {
261                 int ret = regenerateAppNI(flags);
262                 if (ret != NI_ERROR_NONE) {
263                         fprintf(stderr, "Failed to regenerate all app NI\n");
264                 }
265         }
266         //sh-3.2# dotnettool --tac-regen-all
267         else if (cmd == "--tac-regen-all") {
268                 int ret = regenerateTACNI(flags);
269                 if (ret != NI_ERROR_NONE) {
270                         fprintf(stderr, "Failed to regenerate all TAC\n");
271                 }
272         }
273         //sh-3.2# dotnettool --tac-restore-db
274         else if (cmd == "--tac-restore-db") {
275                 int ret = restoreTACDB();
276                 if (ret != TAC_ERROR_NONE) {
277                         fprintf(stderr, "Failed to restore TAC db\n");
278                 }
279         }
280         //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
281         else if (cmd == "--tac-enable-pkg") {
282                 if (args.size() < 1) {
283                         fprintf(stderr, "Package name is missing\n");
284                 }
285                 while (it != args.end()) {
286                         std::string pkg = std::string(*it);
287                         int ret = enableTACPackage(pkg);
288                         if (ret == TAC_ERROR_INVALID_PACKAGE) {
289                                 fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
290                                 break;
291                         } else if (ret != TAC_ERROR_NONE) {
292                                 fprintf(stderr, "Failed to enable tac [%s]\n", pkg.c_str());
293                                 break;
294                         }
295                         it = args.erase(it);
296                 }
297         }
298         //sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
299         else if (cmd == "--tac-disable-pkg") {
300                 if (args.size() < 1) {
301                         fprintf(stderr, "Package name is missing\n");
302                 }
303                 while (it != args.end()) {
304                         std::string pkg = std::string(*it);
305                         int ret = disableTACPackage(pkg);
306                         if (ret == TAC_ERROR_INVALID_PACKAGE) {
307                                 fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
308                                 break;
309                         } else if (ret != TAC_ERROR_NONE) {
310                                 fprintf(stderr, "Failed to disable tac [%s]\n", pkg.c_str());
311                                 break;
312                         }
313                         it = args.erase(it);
314                 }
315         }
316         else {
317                 fprintf(stderr, "Unknown option [%s]\n", cmd.c_str());
318                 DisplayUsage();
319         }
320
321         gettimeofday(&tv, NULL);
322         endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
323         fprintf(stdout, "\nSpend time for dotnettool is [%d]ms\n", (int)(endtime - starttime));
324
325         return 0;
326 }