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