1 | // Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved. |
2 | // Use of this source code is governed by an MIT license |
3 | // that can be found in the LICENSE file. |
4 | module main |
5 | |
6 | import os |
7 | import term |
8 | import v.help |
9 | import v.pref |
10 | import v.util |
11 | import v.util.version |
12 | import v.builder |
13 | import v.builder.cbuilder |
14 | |
15 | const ( |
16 | external_tools = [ |
17 | 'ast', |
18 | 'bin2v', |
19 | 'bug', |
20 | 'build-examples', |
21 | 'build-tools', |
22 | 'build-vbinaries', |
23 | 'bump', |
24 | 'check-md', |
25 | 'complete', |
26 | 'compress', |
27 | 'doc', |
28 | 'doctor', |
29 | 'fmt', |
30 | 'gret', |
31 | 'ls', |
32 | 'missdoc', |
33 | 'repl', |
34 | 'self', |
35 | 'setup-freetype', |
36 | 'shader', |
37 | 'share', |
38 | 'should-compile-all', |
39 | 'symlink', |
40 | 'scan', |
41 | 'test', |
42 | 'test-all', // runs most of the tests and other checking tools, that will be run by the CI |
43 | 'test-cleancode', |
44 | 'test-fmt', |
45 | 'test-parser', |
46 | 'test-self', |
47 | 'tracev', |
48 | 'up', |
49 | 'vet', |
50 | 'wipe-cache', |
51 | 'watch', |
52 | 'where', |
53 | ] |
54 | list_of_flags_that_allow_duplicates = ['cc', 'd', 'define', 'cf', 'cflags'] |
55 | ) |
56 | |
57 | fn main() { |
58 | mut timers_should_print := false |
59 | $if time_v ? { |
60 | timers_should_print = true |
61 | } |
62 | mut timers := util.new_timers(should_print: timers_should_print, label: 'main') |
63 | timers.start('v total') |
64 | defer { |
65 | timers.show('v total') |
66 | } |
67 | timers.start('v start') |
68 | timers.show('v start') |
69 | timers.start('parse_CLI_args') |
70 | args := os.args[1..] |
71 | |
72 | if args.len == 0 || args[0] in ['-', 'repl'] { |
73 | if args.len == 0 { |
74 | // Running `./v` without args launches repl |
75 | if os.is_atty(0) == 0 { |
76 | mut args_and_flags := util.join_env_vflags_and_os_args()[1..].clone() |
77 | args_and_flags << ['run', '-'] |
78 | pref.parse_args_and_show_errors(external_tools, args_and_flags, true) |
79 | } |
80 | } |
81 | util.launch_tool(false, 'vrepl', os.args[1..]) |
82 | return |
83 | } |
84 | mut args_and_flags := util.join_env_vflags_and_os_args()[1..] |
85 | prefs, command := pref.parse_args_and_show_errors(external_tools, args_and_flags, |
86 | true) |
87 | if prefs.use_cache && os.user_os() == 'windows' { |
88 | eprintln('-usecache is currently disabled on windows') |
89 | exit(1) |
90 | } |
91 | timers.show('parse_CLI_args') |
92 | // Start calling the correct functions/external tools |
93 | // Note for future contributors: Please add new subcommands in the `match` block below. |
94 | if command in external_tools { |
95 | // External tools |
96 | util.launch_tool(prefs.is_verbose, 'v' + command, os.args[1..]) |
97 | return |
98 | } |
99 | match command { |
100 | 'run', 'crun', 'build', 'build-module' { |
101 | rebuild(prefs) |
102 | return |
103 | } |
104 | 'help' { |
105 | invoke_help_and_exit(args) |
106 | } |
107 | 'version' { |
108 | println(version.full_v_version(prefs.is_verbose)) |
109 | return |
110 | } |
111 | 'new', 'init' { |
112 | util.launch_tool(prefs.is_verbose, 'vcreate', os.args[1..]) |
113 | return |
114 | } |
115 | 'install', 'list', 'outdated', 'remove', 'search', 'show', 'update', 'upgrade' { |
116 | util.launch_tool(prefs.is_verbose, 'vpm', os.args[1..]) |
117 | return |
118 | } |
119 | 'vlib-docs' { |
120 | util.launch_tool(prefs.is_verbose, 'vdoc', ['doc', 'vlib']) |
121 | } |
122 | 'interpret' { |
123 | util.launch_tool(prefs.is_verbose, 'builders/interpret_builder', os.args[1..]) |
124 | } |
125 | 'get' { |
126 | eprintln('V Error: Use `v install` to install modules from vpm.vlang.io') |
127 | exit(1) |
128 | } |
129 | 'translate' { |
130 | util.launch_tool(prefs.is_verbose, 'translate', os.args[1..]) |
131 | // exit(1) |
132 | // return |
133 | } |
134 | else { |
135 | if command.ends_with('.v') || os.exists(command) { |
136 | // println('command') |
137 | // println(prefs.path) |
138 | rebuild(prefs) |
139 | return |
140 | } |
141 | } |
142 | } |
143 | if prefs.is_help { |
144 | invoke_help_and_exit(args) |
145 | } |
146 | |
147 | other_commands := ['run', 'crun', 'build', 'build-module', 'help', 'version', 'new', 'init', |
148 | 'install', 'list', 'outdated', 'remove', 'search', 'show', 'update', 'upgrade', 'vlib-docs', |
149 | 'interpret', 'translate'] |
150 | mut all_commands := []string{} |
151 | all_commands << external_tools |
152 | all_commands << other_commands |
153 | all_commands.sort() |
154 | eprintln(util.new_suggestion(command, all_commands).say('v: unknown command `${command}`')) |
155 | eprintln('Run ${term.highlight_command('v help')} for usage.') |
156 | exit(1) |
157 | } |
158 | |
159 | fn invoke_help_and_exit(remaining []string) { |
160 | match remaining.len { |
161 | 0, 1 { help.print_and_exit('default') } |
162 | 2 { help.print_and_exit(remaining[1]) } |
163 | else {} |
164 | } |
165 | eprintln('${term.highlight_command('v help')}: provide only one help topic.') |
166 | eprintln('For usage information, use ${term.highlight_command('v help')}.') |
167 | exit(1) |
168 | } |
169 | |
170 | fn rebuild(prefs &pref.Preferences) { |
171 | match prefs.backend { |
172 | .c { |
173 | $if no_bootstrapv ? { |
174 | // TODO: improve the bootstrapping with a split C backend here. |
175 | // C code generated by `VEXE=v cmd/tools/builders/c_builder -os cross -o c.c cmd/tools/builders/c_builder.v` |
176 | // is enough to bootstrap the C backend, and thus the rest, but currently bootstrapping relies on |
177 | // `v -os cross -o v.c cmd/v` having a functional C codegen inside instead. |
178 | util.launch_tool(prefs.is_verbose, 'builders/c_builder', os.args[1..]) |
179 | } |
180 | builder.compile('build', prefs, cbuilder.compile_c) |
181 | } |
182 | .js_node, .js_freestanding, .js_browser { |
183 | util.launch_tool(prefs.is_verbose, 'builders/js_builder', os.args[1..]) |
184 | } |
185 | .native { |
186 | util.launch_tool(prefs.is_verbose, 'builders/native_builder', os.args[1..]) |
187 | } |
188 | .interpret { |
189 | util.launch_tool(prefs.is_verbose, 'builders/interpret_builder', os.args[1..]) |
190 | } |
191 | .golang { |
192 | println('using Go WIP backend...') |
193 | util.launch_tool(prefs.is_verbose, 'builders/golang_builder', os.args[1..]) |
194 | } |
195 | .wasm { |
196 | util.launch_tool(prefs.is_verbose, 'builders/wasm_builder', os.args[1..]) |
197 | } |
198 | } |
199 | } |