1 | // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "bin/main_options.h" |
6 | |
7 | #include <stdio.h> |
8 | #include <stdlib.h> |
9 | #include <string.h> |
10 | |
11 | #include "bin/dartdev_isolate.h" |
12 | #include "bin/error_exit.h" |
13 | #include "bin/options.h" |
14 | #include "bin/platform.h" |
15 | #include "bin/utils.h" |
16 | #include "platform/syslog.h" |
17 | #if !defined(DART_IO_SECURE_SOCKET_DISABLED) |
18 | #include "bin/security_context.h" |
19 | #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
20 | #include "bin/socket.h" |
21 | #include "include/dart_api.h" |
22 | #include "platform/assert.h" |
23 | #include "platform/globals.h" |
24 | #include "platform/hashmap.h" |
25 | |
26 | namespace dart { |
27 | namespace bin { |
28 | |
29 | // These strings must match the enum SnapshotKind in main_options.h. |
30 | static const char* kSnapshotKindNames[] = { |
31 | "none" , |
32 | "kernel" , |
33 | "app-jit" , |
34 | NULL, |
35 | }; |
36 | |
37 | SnapshotKind Options::gen_snapshot_kind_ = kNone; |
38 | bool Options::enable_vm_service_ = false; |
39 | MallocGrowableArray<const char*> Options::enabled_experiments_ = |
40 | MallocGrowableArray<const char*>(4); |
41 | |
42 | #define OPTION_FIELD(variable) Options::variable##_ |
43 | |
44 | #define STRING_OPTION_DEFINITION(name, variable) \ |
45 | const char* OPTION_FIELD(variable) = NULL; \ |
46 | DEFINE_STRING_OPTION(name, OPTION_FIELD(variable)) |
47 | STRING_OPTIONS_LIST(STRING_OPTION_DEFINITION) |
48 | #undef STRING_OPTION_DEFINITION |
49 | |
50 | #define BOOL_OPTION_DEFINITION(name, variable) \ |
51 | bool OPTION_FIELD(variable) = false; \ |
52 | DEFINE_BOOL_OPTION(name, OPTION_FIELD(variable)) |
53 | BOOL_OPTIONS_LIST(BOOL_OPTION_DEFINITION) |
54 | #if defined(DEBUG) |
55 | DEBUG_BOOL_OPTIONS_LIST(BOOL_OPTION_DEFINITION) |
56 | #endif |
57 | #undef BOOL_OPTION_DEFINITION |
58 | |
59 | #define SHORT_BOOL_OPTION_DEFINITION(short_name, long_name, variable) \ |
60 | bool OPTION_FIELD(variable) = false; \ |
61 | DEFINE_BOOL_OPTION_SHORT(short_name, long_name, OPTION_FIELD(variable)) |
62 | SHORT_BOOL_OPTIONS_LIST(SHORT_BOOL_OPTION_DEFINITION) |
63 | #undef SHORT_BOOL_OPTION_DEFINITION |
64 | |
65 | #define ENUM_OPTION_DEFINITION(name, type, variable) \ |
66 | DEFINE_ENUM_OPTION(name, type, OPTION_FIELD(variable)) |
67 | ENUM_OPTIONS_LIST(ENUM_OPTION_DEFINITION) |
68 | #undef ENUM_OPTION_DEFINITION |
69 | |
70 | #define CB_OPTION_DEFINITION(callback) \ |
71 | static bool callback##Helper(const char* arg, CommandLineOptions* o) { \ |
72 | return Options::callback(arg, o); \ |
73 | } \ |
74 | DEFINE_CB_OPTION(callback##Helper) |
75 | CB_OPTIONS_LIST(CB_OPTION_DEFINITION) |
76 | #undef CB_OPTION_DEFINITION |
77 | |
78 | #if !defined(DART_PRECOMPILED_RUNTIME) |
79 | DFE* Options::dfe_ = NULL; |
80 | |
81 | DEFINE_STRING_OPTION_CB(dfe, { Options::dfe()->set_frontend_filename(value); }); |
82 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
83 | |
84 | static void hot_reload_test_mode_callback(CommandLineOptions* vm_options) { |
85 | // Identity reload. |
86 | vm_options->AddArgument("--identity_reload" ); |
87 | // Start reloading quickly. |
88 | vm_options->AddArgument("--reload_every=4" ); |
89 | // Reload from optimized and unoptimized code. |
90 | vm_options->AddArgument("--reload_every_optimized=false" ); |
91 | // Reload less frequently as time goes on. |
92 | vm_options->AddArgument("--reload_every_back_off" ); |
93 | // Ensure that every isolate has reloaded once before exiting. |
94 | vm_options->AddArgument("--check_reloaded" ); |
95 | #if !defined(DART_PRECOMPILED_RUNTIME) |
96 | Options::dfe()->set_use_incremental_compiler(true); |
97 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
98 | } |
99 | |
100 | DEFINE_BOOL_OPTION_CB(hot_reload_test_mode, hot_reload_test_mode_callback); |
101 | |
102 | static void hot_reload_rollback_test_mode_callback( |
103 | CommandLineOptions* vm_options) { |
104 | // Identity reload. |
105 | vm_options->AddArgument("--identity_reload" ); |
106 | // Start reloading quickly. |
107 | vm_options->AddArgument("--reload_every=4" ); |
108 | // Reload from optimized and unoptimized code. |
109 | vm_options->AddArgument("--reload_every_optimized=false" ); |
110 | // Reload less frequently as time goes on. |
111 | vm_options->AddArgument("--reload_every_back_off" ); |
112 | // Ensure that every isolate has reloaded once before exiting. |
113 | vm_options->AddArgument("--check_reloaded" ); |
114 | // Force all reloads to fail and execute the rollback code. |
115 | vm_options->AddArgument("--reload_force_rollback" ); |
116 | #if !defined(DART_PRECOMPILED_RUNTIME) |
117 | Options::dfe()->set_use_incremental_compiler(true); |
118 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
119 | } |
120 | |
121 | DEFINE_BOOL_OPTION_CB(hot_reload_rollback_test_mode, |
122 | hot_reload_rollback_test_mode_callback); |
123 | |
124 | void Options::PrintVersion() { |
125 | Syslog::PrintErr("Dart SDK version: %s\n" , Dart_VersionString()); |
126 | } |
127 | |
128 | // clang-format off |
129 | void Options::PrintUsage() { |
130 | Syslog::PrintErr( |
131 | "Usage: dart [<vm-flags>] <dart-script-file> [<script-arguments>]\n" |
132 | "\n" |
133 | "Executes the Dart script <dart-script-file> with " |
134 | "the given list of <script-arguments>.\n" |
135 | "\n" ); |
136 | if (!Options::verbose_option()) { |
137 | Syslog::PrintErr( |
138 | "Common VM flags:\n" |
139 | "--enable-asserts\n" |
140 | " Enable assert statements.\n" |
141 | "--help or -h\n" |
142 | " Display this message (add -v or --verbose for information about\n" |
143 | " all VM options).\n" |
144 | "--packages=<path>\n" |
145 | " Where to find a package spec file.\n" |
146 | "--observe[=<port>[/<bind-address>]]\n" |
147 | " The observe flag is a convenience flag used to run a program with a\n" |
148 | " set of options which are often useful for debugging under Observatory.\n" |
149 | " These options are currently:\n" |
150 | " --enable-vm-service[=<port>[/<bind-address>]]\n" |
151 | " --pause-isolates-on-exit\n" |
152 | " --pause-isolates-on-unhandled-exceptions\n" |
153 | " --warn-on-pause-with-no-debugger\n" |
154 | " This set is subject to change.\n" |
155 | " Please see these options (--help --verbose) for further documentation.\n" |
156 | "--write-service-info=<file_uri>\n" |
157 | " Outputs information necessary to connect to the VM service to the\n" |
158 | " specified file in JSON format. Useful for clients which are unable to\n" |
159 | " listen to stdout for the Observatory listening message.\n" |
160 | "--snapshot-kind=<snapshot_kind>\n" |
161 | "--snapshot=<file_name>\n" |
162 | " These snapshot options are used to generate a snapshot of the loaded\n" |
163 | " Dart script:\n" |
164 | " <snapshot-kind> controls the kind of snapshot, it could be\n" |
165 | " kernel(default) or app-jit\n" |
166 | " <file_name> specifies the file into which the snapshot is written\n" |
167 | "--version\n" |
168 | " Print the SDK version.\n" ); |
169 | } else { |
170 | Syslog::PrintErr( |
171 | "Supported options:\n" |
172 | "--enable-asserts\n" |
173 | " Enable assert statements.\n" |
174 | "--help or -h\n" |
175 | " Display this message (add -v or --verbose for information about\n" |
176 | " all VM options).\n" |
177 | "--packages=<path>\n" |
178 | " Where to find a package spec file.\n" |
179 | "--observe[=<port>[/<bind-address>]]\n" |
180 | " The observe flag is a convenience flag used to run a program with a\n" |
181 | " set of options which are often useful for debugging under Observatory.\n" |
182 | " These options are currently:\n" |
183 | " --enable-vm-service[=<port>[/<bind-address>]]\n" |
184 | " --pause-isolates-on-exit\n" |
185 | " --pause-isolates-on-unhandled-exceptions\n" |
186 | " --warn-on-pause-with-no-debugger\n" |
187 | " This set is subject to change.\n" |
188 | " Please see these options for further documentation.\n" |
189 | "--version\n" |
190 | " Print the VM version.\n" |
191 | "\n" |
192 | "--trace-loading\n" |
193 | " enables tracing of library and script loading\n" |
194 | "\n" |
195 | "--enable-vm-service[=<port>[/<bind-address>]]\n" |
196 | " Enables the VM service and listens on specified port for connections\n" |
197 | " (default port number is 8181, default bind address is localhost).\n" |
198 | "\n" |
199 | "--disable-service-auth-codes\n" |
200 | " Disables the requirement for an authentication code to communicate with\n" |
201 | " the VM service. Authentication codes help protect against CSRF attacks,\n" |
202 | " so it is not recommended to disable them unless behind a firewall on a\n" |
203 | " secure device.\n" |
204 | "\n" |
205 | "--enable-service-port-fallback\n" |
206 | " When the VM service is told to bind to a particular port, fallback to 0 if\n" |
207 | " it fails to bind instead of failing to start.\n" |
208 | "\n" |
209 | "--root-certs-file=<path>\n" |
210 | " The path to a file containing the trusted root certificates to use for\n" |
211 | " secure socket connections.\n" |
212 | "--root-certs-cache=<path>\n" |
213 | " The path to a cache directory containing the trusted root certificates to\n" |
214 | " use for secure socket connections.\n" |
215 | #if defined(HOST_OS_LINUX) || \ |
216 | defined(HOST_OS_ANDROID) || \ |
217 | defined(HOST_OS_FUCHSIA) |
218 | "--namespace=<path>\n" |
219 | " The path to a directory that dart:io calls will treat as the root of the\n" |
220 | " filesystem.\n" |
221 | #endif // defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID) |
222 | "\n" |
223 | "The following options are only used for VM development and may\n" |
224 | "be changed in any future version:\n" ); |
225 | const char* print_flags = "--print_flags" ; |
226 | char* error = Dart_SetVMFlags(1, &print_flags); |
227 | ASSERT(error == NULL); |
228 | } |
229 | } |
230 | // clang-format on |
231 | |
232 | dart::SimpleHashMap* Options::environment_ = NULL; |
233 | bool Options::ProcessEnvironmentOption(const char* arg, |
234 | CommandLineOptions* vm_options) { |
235 | return OptionProcessor::ProcessEnvironmentOption(arg, vm_options, |
236 | &Options::environment_); |
237 | } |
238 | |
239 | void Options::DestroyEnvironment() { |
240 | if (environment_ != NULL) { |
241 | for (SimpleHashMap::Entry* p = environment_->Start(); p != NULL; |
242 | p = environment_->Next(p)) { |
243 | free(p->key); |
244 | free(p->value); |
245 | } |
246 | delete environment_; |
247 | environment_ = NULL; |
248 | } |
249 | } |
250 | |
251 | bool Options::ExtractPortAndAddress(const char* option_value, |
252 | int* out_port, |
253 | const char** out_ip, |
254 | int default_port, |
255 | const char* default_ip) { |
256 | // [option_value] has to be one of the following formats: |
257 | // - "" |
258 | // - ":8181" |
259 | // - "=8181" |
260 | // - ":8181/192.168.0.1" |
261 | // - "=8181/192.168.0.1" |
262 | // - "=8181/::1" |
263 | |
264 | if (*option_value == '\0') { |
265 | *out_ip = default_ip; |
266 | *out_port = default_port; |
267 | return true; |
268 | } |
269 | |
270 | if ((*option_value != '=') && (*option_value != ':')) { |
271 | return false; |
272 | } |
273 | |
274 | int port = atoi(option_value + 1); |
275 | const char* slash = strstr(option_value, "/" ); |
276 | if (slash == NULL) { |
277 | *out_ip = default_ip; |
278 | *out_port = port; |
279 | return true; |
280 | } |
281 | |
282 | *out_ip = slash + 1; |
283 | *out_port = port; |
284 | return true; |
285 | } |
286 | |
287 | static const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost" ; |
288 | static const int DEFAULT_VM_SERVICE_SERVER_PORT = 8181; |
289 | static const int INVALID_VM_SERVICE_SERVER_PORT = -1; |
290 | |
291 | const char* Options::vm_service_server_ip_ = DEFAULT_VM_SERVICE_SERVER_IP; |
292 | int Options::vm_service_server_port_ = INVALID_VM_SERVICE_SERVER_PORT; |
293 | bool Options::ProcessEnableVmServiceOption(const char* arg, |
294 | CommandLineOptions* vm_options) { |
295 | const char* value = |
296 | OptionProcessor::ProcessOption(arg, "--enable-vm-service" ); |
297 | if (value == NULL) { |
298 | return false; |
299 | } |
300 | if (!ExtractPortAndAddress( |
301 | value, &vm_service_server_port_, &vm_service_server_ip_, |
302 | DEFAULT_VM_SERVICE_SERVER_PORT, DEFAULT_VM_SERVICE_SERVER_IP)) { |
303 | Syslog::PrintErr( |
304 | "unrecognized --enable-vm-service option syntax. " |
305 | "Use --enable-vm-service[=<port number>[/<bind address>]]\n" ); |
306 | return false; |
307 | } |
308 | #if !defined(DART_PRECOMPILED_RUNTIME) |
309 | dfe()->set_use_incremental_compiler(true); |
310 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
311 | enable_vm_service_ = true; |
312 | return true; |
313 | } |
314 | |
315 | bool Options::ProcessObserveOption(const char* arg, |
316 | CommandLineOptions* vm_options) { |
317 | const char* value = OptionProcessor::ProcessOption(arg, "--observe" ); |
318 | if (value == NULL) { |
319 | return false; |
320 | } |
321 | if (!ExtractPortAndAddress( |
322 | value, &vm_service_server_port_, &vm_service_server_ip_, |
323 | DEFAULT_VM_SERVICE_SERVER_PORT, DEFAULT_VM_SERVICE_SERVER_IP)) { |
324 | Syslog::PrintErr( |
325 | "unrecognized --observe option syntax. " |
326 | "Use --observe[=<port number>[/<bind address>]]\n" ); |
327 | return false; |
328 | } |
329 | |
330 | // These options should also be documented in the help message. |
331 | vm_options->AddArgument("--pause-isolates-on-exit" ); |
332 | vm_options->AddArgument("--pause-isolates-on-unhandled-exceptions" ); |
333 | vm_options->AddArgument("--profiler" ); |
334 | vm_options->AddArgument("--warn-on-pause-with-no-debugger" ); |
335 | #if !defined(DART_PRECOMPILED_RUNTIME) |
336 | dfe()->set_use_incremental_compiler(true); |
337 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
338 | enable_vm_service_ = true; |
339 | return true; |
340 | } |
341 | |
342 | // Explicitly handle VM flags that can be parsed by DartDev's run command. |
343 | bool Options::ProcessVMDebuggingOptions(const char* arg, |
344 | CommandLineOptions* vm_options) { |
345 | #define IS_DEBUG_OPTION(name, arg) \ |
346 | if (strncmp(name, arg, strlen(name)) == 0) { \ |
347 | vm_options->AddArgument(arg); \ |
348 | return true; \ |
349 | } |
350 | |
351 | // This is an exhaustive set of VM flags that are accepted by 'dart run'. Flags |
352 | // defined in main_options.h do not need to be handled here as they already |
353 | // have handlers generated. |
354 | // |
355 | // NOTE: When updating this list of VM flags, be sure to make the corresponding |
356 | // changes in pkg/dartdev/lib/src/commands/run.dart. |
357 | #define HANDLE_DARTDEV_VM_DEBUG_OPTIONS(V, arg) \ |
358 | V("--enable-asserts", arg) \ |
359 | V("--pause-isolates-on-exit", arg) \ |
360 | V("--no-pause-isolates-on-exit", arg) \ |
361 | V("--pause-isolates-on-start", arg) \ |
362 | V("--no-pause-isolates-on-start", arg) \ |
363 | V("--pause-isolates-on-unhandled-exception", arg) \ |
364 | V("--no-pause-isolates-on-unhandled-exception", arg) \ |
365 | V("--warn-on-pause-with-no-debugger", arg) \ |
366 | V("--no-warn-on-pause-with-no-debugger", arg) |
367 | HANDLE_DARTDEV_VM_DEBUG_OPTIONS(IS_DEBUG_OPTION, arg); |
368 | |
369 | #undef IS_DEBUG_OPTION |
370 | #undef HANDLE_DARTDEV_VM_DEBUG_OPTIONS |
371 | |
372 | return false; |
373 | } |
374 | |
375 | bool Options::ProcessEnableExperimentOption(const char* arg, |
376 | CommandLineOptions* vm_options) { |
377 | const char* value = |
378 | OptionProcessor::ProcessOption(arg, "--enable_experiment=" ); |
379 | if (value == nullptr) { |
380 | value = OptionProcessor::ProcessOption(arg, "--enable-experiment=" ); |
381 | } |
382 | if (value == nullptr) { |
383 | return false; |
384 | } |
385 | vm_options->AddArgument(arg); |
386 | Utils::CStringUniquePtr tmp = |
387 | Utils::CreateCStringUniquePtr(Utils::StrDup(value)); |
388 | char* save_ptr; // Needed for strtok_r. |
389 | char* token = strtok_r(const_cast<char*>(tmp.get()), "," , &save_ptr); |
390 | while (token != NULL) { |
391 | enabled_experiments_.Add(Utils::StrDup(token)); |
392 | token = strtok_r(NULL, "," , &save_ptr); |
393 | } |
394 | return true; |
395 | } |
396 | |
397 | int Options::ParseArguments(int argc, |
398 | char** argv, |
399 | bool vm_run_app_snapshot, |
400 | CommandLineOptions* vm_options, |
401 | char** script_name, |
402 | CommandLineOptions* dart_options, |
403 | bool* print_flags_seen, |
404 | bool* verbose_debug_seen) { |
405 | const char* kPrefix = "--" ; |
406 | const intptr_t kPrefixLen = strlen(kPrefix); |
407 | |
408 | // Store the executable name. |
409 | Platform::SetExecutableName(argv[0]); |
410 | |
411 | // Start the rest after the executable name. |
412 | int i = 1; |
413 | |
414 | CommandLineOptions temp_vm_options(vm_options->max_count()); |
415 | |
416 | bool enable_dartdev_analytics = false; |
417 | bool disable_dartdev_analytics = false; |
418 | |
419 | // Parse out the vm options. |
420 | while (i < argc) { |
421 | bool skipVmOption = false; |
422 | if (OptionProcessor::TryProcess(argv[i], &temp_vm_options)) { |
423 | i++; |
424 | } else { |
425 | // Check if this flag is a potentially valid VM flag. |
426 | if (!OptionProcessor::IsValidFlag(argv[i], kPrefix, kPrefixLen)) { |
427 | break; |
428 | } |
429 | // The following two flags are processed by both the embedder and |
430 | // the VM. |
431 | const char* kPrintFlags1 = "--print-flags" ; |
432 | const char* kPrintFlags2 = "--print_flags" ; |
433 | const char* kVerboseDebug1 = "--verbose_debug" ; |
434 | const char* kVerboseDebug2 = "--verbose-debug" ; |
435 | |
436 | // The following two flags are processed as DartDev flags and are not to |
437 | // be treated as if they are VM flags. |
438 | const char* kEnableDartDevAnalytics1 = "--enable-analytics" ; |
439 | const char* kEnableDartDevAnalytics2 = "--enable_analytics" ; |
440 | const char* kDisableDartDevAnalytics1 = "--disable-analytics" ; |
441 | const char* kDisableDartDevAnalytics2 = "--disable_analytics" ; |
442 | |
443 | if ((strncmp(argv[i], kPrintFlags1, strlen(kPrintFlags1)) == 0) || |
444 | (strncmp(argv[i], kPrintFlags2, strlen(kPrintFlags2)) == 0)) { |
445 | *print_flags_seen = true; |
446 | } else if ((strncmp(argv[i], kVerboseDebug1, strlen(kVerboseDebug1)) == |
447 | 0) || |
448 | (strncmp(argv[i], kVerboseDebug2, strlen(kVerboseDebug2)) == |
449 | 0)) { |
450 | *verbose_debug_seen = true; |
451 | } else if ((strncmp(argv[i], kEnableDartDevAnalytics1, |
452 | strlen(kEnableDartDevAnalytics1)) == 0) || |
453 | (strncmp(argv[i], kEnableDartDevAnalytics2, |
454 | strlen(kEnableDartDevAnalytics2)) == 0)) { |
455 | enable_dartdev_analytics = true; |
456 | skipVmOption = true; |
457 | } else if ((strncmp(argv[i], kDisableDartDevAnalytics1, |
458 | strlen(kDisableDartDevAnalytics1)) == 0) || |
459 | (strncmp(argv[i], kDisableDartDevAnalytics2, |
460 | strlen(kDisableDartDevAnalytics2)) == 0)) { |
461 | disable_dartdev_analytics = true; |
462 | skipVmOption = true; |
463 | } |
464 | if (!skipVmOption) { |
465 | temp_vm_options.AddArgument(argv[i]); |
466 | } |
467 | i++; |
468 | } |
469 | } |
470 | |
471 | #if !defined(DART_PRECOMPILED_RUNTIME) |
472 | Options::dfe()->set_use_dfe(); |
473 | #else |
474 | // DartDev is not supported in AOT. |
475 | Options::disable_dart_dev_ = true; |
476 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
477 | if (Options::deterministic()) { |
478 | // Both an embedder and VM flag. |
479 | temp_vm_options.AddArgument("--deterministic" ); |
480 | } |
481 | |
482 | Socket::set_short_socket_read(Options::short_socket_read()); |
483 | Socket::set_short_socket_write(Options::short_socket_write()); |
484 | #if !defined(DART_IO_SECURE_SOCKET_DISABLED) |
485 | SSLCertContext::set_root_certs_file(Options::root_certs_file()); |
486 | SSLCertContext::set_root_certs_cache(Options::root_certs_cache()); |
487 | #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
488 | |
489 | // The arguments to the VM are at positions 1 through i-1 in argv. |
490 | Platform::SetExecutableArguments(i, argv); |
491 | |
492 | bool run_script = false; |
493 | int script_or_cmd_index = -1; |
494 | |
495 | // Get the script name. |
496 | if (i < argc) { |
497 | #if !defined(DART_PRECOMPILED_RUNTIME) |
498 | // If the script name is a valid file or a URL, we'll run the script |
499 | // directly. Otherwise, this might be a DartDev command and we need to try |
500 | // to find the DartDev snapshot so we can forward the command and its |
501 | // arguments. |
502 | bool is_potential_file_path = !DartDevIsolate::ShouldParseCommand(argv[i]); |
503 | bool implicitly_use_dart_dev = false; |
504 | #else |
505 | bool is_potential_file_path = true; |
506 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
507 | script_or_cmd_index = i; |
508 | if (Options::disable_dart_dev() || |
509 | (is_potential_file_path && !enable_vm_service_)) { |
510 | *script_name = Utils::StrDup(argv[i]); |
511 | run_script = true; |
512 | i++; |
513 | } |
514 | #if !defined(DART_PRECOMPILED_RUNTIME) |
515 | else { // NOLINT |
516 | DartDevIsolate::set_should_run_dart_dev(true); |
517 | } |
518 | // Handle the special case where the user is running a Dart program without |
519 | // using a DartDev command and wants to use the VM service. Here we'll run |
520 | // the program using DartDev as it's used to spawn a DDS instance |
521 | if (!Options::disable_dart_dev() && is_potential_file_path && |
522 | enable_vm_service_) { |
523 | implicitly_use_dart_dev = true; |
524 | dart_options->AddArgument("run" ); |
525 | } |
526 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
527 | } |
528 | #if !defined(DART_PRECOMPILED_RUNTIME) |
529 | else if (!Options::disable_dart_dev() && // NOLINT |
530 | ((Options::help_option() && !Options::verbose_option()) || |
531 | (argc == 1))) { |
532 | DartDevIsolate::set_should_run_dart_dev(true); |
533 | // Let DartDev handle the default help message. |
534 | dart_options->AddArgument("help" ); |
535 | return 0; |
536 | } else if (!Options::disable_dart_dev() && |
537 | (enable_dartdev_analytics || disable_dartdev_analytics)) { |
538 | // The analytics flags are a special case as we don't have a target script |
539 | // or DartDev command but we still want to launch DartDev. |
540 | DartDevIsolate::set_should_run_dart_dev(true); |
541 | |
542 | if (enable_dartdev_analytics) { |
543 | dart_options->AddArgument("--enable-analytics" ); |
544 | } |
545 | if (disable_dartdev_analytics) { |
546 | dart_options->AddArgument("--disable-analytics" ); |
547 | } |
548 | return 0; |
549 | } |
550 | |
551 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
552 | else { // NOLINT |
553 | return -1; |
554 | } |
555 | const char** vm_argv = temp_vm_options.arguments(); |
556 | int vm_argc = temp_vm_options.count(); |
557 | |
558 | vm_options->AddArguments(vm_argv, vm_argc); |
559 | |
560 | #if !defined(DART_PRECOMPILED_RUNTIME) |
561 | if (!enabled_experiments_.is_empty()) { |
562 | intptr_t num_experiments = enabled_experiments_.length(); |
563 | if (!(Options::disable_dart_dev() || run_script)) { |
564 | const char* kEnableExperiment = "--enable-experiment=" ; |
565 | int option_size = strlen(kEnableExperiment); |
566 | for (intptr_t i = 0; i < num_experiments; ++i) { |
567 | const char* flag = enabled_experiments_.At(i); |
568 | option_size += strlen(flag); |
569 | if (i + 1 != num_experiments) { |
570 | // Account for comma if there's more experiments to add. |
571 | ++option_size; |
572 | } |
573 | } |
574 | // Make room for null terminator |
575 | ++option_size; |
576 | |
577 | char* enabled_experiments_arg = new char[option_size]; |
578 | int offset = snprintf(enabled_experiments_arg, option_size, "%s" , |
579 | kEnableExperiment); |
580 | for (intptr_t i = 0; i < num_experiments; ++i) { |
581 | const char* flag = enabled_experiments_.At(i); |
582 | const char* kFormat = (i + 1 != num_experiments) ? "%s," : "%s" ; |
583 | offset += snprintf(enabled_experiments_arg + offset, |
584 | option_size - offset, kFormat, flag); |
585 | free(const_cast<char*>(flag)); |
586 | ASSERT(offset < option_size); |
587 | } |
588 | DartDevIsolate::set_should_run_dart_dev(true); |
589 | dart_options->AddArgument(enabled_experiments_arg); |
590 | } else { |
591 | for (intptr_t i = 0; i < num_experiments; ++i) { |
592 | free(const_cast<char*>(enabled_experiments_.At(i))); |
593 | } |
594 | } |
595 | } |
596 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
597 | |
598 | // Parse out options to be passed to dart main. |
599 | while (i < argc) { |
600 | if (!run_script) { |
601 | OptionProcessor::TryProcess(argv[i], vm_options); |
602 | } |
603 | dart_options->AddArgument(argv[i]); |
604 | i++; |
605 | } |
606 | |
607 | if (!Options::disable_dart_dev() && enable_vm_service_) { |
608 | dart_options->AddArgument("--launch-dds" ); |
609 | } |
610 | |
611 | // Verify consistency of arguments. |
612 | |
613 | // snapshot_depfile is an alias for depfile. Passing them both is an error. |
614 | if ((snapshot_deps_filename_ != NULL) && (depfile_ != NULL)) { |
615 | Syslog::PrintErr("Specify only one of --depfile and --snapshot_depfile\n" ); |
616 | return -1; |
617 | } |
618 | if (snapshot_deps_filename_ != NULL) { |
619 | depfile_ = snapshot_deps_filename_; |
620 | snapshot_deps_filename_ = NULL; |
621 | } |
622 | |
623 | if ((packages_file_ != NULL) && (strlen(packages_file_) == 0)) { |
624 | Syslog::PrintErr("Empty package file name specified.\n" ); |
625 | return -1; |
626 | } |
627 | if ((gen_snapshot_kind_ != kNone) && (snapshot_filename_ == NULL)) { |
628 | Syslog::PrintErr( |
629 | "Generating a snapshot requires a filename (--snapshot).\n" ); |
630 | return -1; |
631 | } |
632 | if ((gen_snapshot_kind_ == kNone) && (depfile_ != NULL) && |
633 | (snapshot_filename_ == NULL) && (depfile_output_filename_ == NULL)) { |
634 | Syslog::PrintErr( |
635 | "Generating a depfile requires an output filename" |
636 | " (--depfile-output-filename or --snapshot).\n" ); |
637 | return -1; |
638 | } |
639 | if ((gen_snapshot_kind_ != kNone) && vm_run_app_snapshot) { |
640 | Syslog::PrintErr( |
641 | "Specifying an option to generate a snapshot and" |
642 | " run using a snapshot is invalid.\n" ); |
643 | return -1; |
644 | } |
645 | |
646 | // If --snapshot is given without --snapshot-kind, default to script snapshot. |
647 | if ((snapshot_filename_ != NULL) && (gen_snapshot_kind_ == kNone)) { |
648 | gen_snapshot_kind_ = kKernel; |
649 | } |
650 | |
651 | return 0; |
652 | } |
653 | |
654 | } // namespace bin |
655 | } // namespace dart |
656 | |