-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
should_compile.v
311 lines (301 loc) · 8.73 KB
/
should_compile.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
module pref
import os
pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []string) []string {
mut res := []string{}
mut files := files_.clone()
files.sort()
mut all_v_files := []string{}
files_loop: for file in files {
if !file.ends_with('.v') && !file.ends_with('.vh') {
continue
}
if file.ends_with('_test.v')
|| file.all_before_last('.v').all_before_last('.').ends_with('_test') {
continue
}
if prefs.backend in [.c, .interpret] && !prefs.should_compile_c(file) {
continue
}
if prefs.backend.is_js() && !prefs.should_compile_js(file) {
continue
}
if prefs.backend == .native && !prefs.should_compile_native(file) {
continue
}
if !prefs.backend.is_js() && !prefs.should_compile_asm(file) {
continue
}
if file.starts_with('.#') {
continue
}
if !prefs.prealloc && !prefs.output_cross_c && file.ends_with('prealloc.c.v') {
continue
}
if prefs.nofloat && file.ends_with('float.c.v') {
continue
}
if file.contains('_d_') {
if prefs.compile_defines_all.len == 0 {
continue
}
mut allowed := false
for cdefine in prefs.compile_defines {
file_postfixes := ['_d_${cdefine}.v', '_d_${cdefine}.c.v']
for file_postfix in file_postfixes {
if file.ends_with(file_postfix) {
allowed = true
break
}
}
if allowed {
break
}
}
if !allowed {
continue
}
}
if file.contains('_notd_') {
mut allowed := true
for cdefine in prefs.compile_defines {
file_postfixes := ['_notd_${cdefine}.v', '_notd_${cdefine}.c.v']
for file_postfix in file_postfixes {
if file.ends_with(file_postfix) {
allowed = false
break
}
}
if !allowed {
break
}
}
if !allowed {
continue
}
}
if prefs.exclude.len > 0 {
full_file_path := os.join_path(dir, file)
for epattern in prefs.exclude {
if full_file_path.match_glob(epattern) {
continue files_loop
}
}
}
all_v_files << os.join_path(dir, file)
}
//
mut defaults := []string{}
mut fnames_no_postfixes := map[string][]string{}
for file in all_v_files {
if file.contains('default.c.v') {
defaults << file
} else {
res << file
no_postfix_key := fname_without_platform_postfix(file)
mut candidates := fnames_no_postfixes[no_postfix_key]
candidates << file
fnames_no_postfixes[no_postfix_key] = candidates
}
}
for file in defaults {
no_postfix_key := fname_without_platform_postfix(file)
if no_postfix_key in fnames_no_postfixes {
if prefs.is_verbose {
println('>>> should_compile_filtered_files: skipping _default.c.v file ${file} ; the specialized versions are: ${fnames_no_postfixes[no_postfix_key]}')
}
continue
}
res << file
}
if prefs.is_verbose {
// println('>>> prefs: $prefs')
println('>>> should_compile_filtered_files: res: ${res}')
}
return res
}
fn fname_without_platform_postfix(file string) string {
res := file.replace_each([
'default.c.v',
'_',
'nix.c.v',
'_',
'windows.c.v',
'_',
'linux.c.v',
'_',
'darwin.c.v',
'_',
'macos.c.v',
'_',
'android.c.v',
'_',
'termux.c.v',
'_',
'android_outside_termux.c.v',
'_',
'freebsd.c.v',
'_',
'openbsd.c.v',
'_',
'netbsd.c.v',
'_',
'dragonfly.c.v',
'_',
'solaris.c.v',
'_',
'native.v',
'_',
])
return res
}
pub fn (prefs &Preferences) should_compile_native(file string) bool {
// allow custom filtering for native backends,
// but if there are no other rules, default to the c backend rules
return prefs.should_compile_c(file)
}
// TODO: Rework this using is_target_of()
pub fn (prefs &Preferences) should_compile_c(file string) bool {
if file.ends_with('.js.v') {
// Probably something like `a.js.v`.
return false
}
if prefs.is_bare && file.ends_with('.freestanding.v') {
return true
}
if prefs.os == .all {
return true
}
if prefs.backend != .native && file.ends_with('_native.v') {
return false
}
if prefs.building_v && prefs.output_cross_c && file.ends_with('_windows.v') {
// TODO: temp hack to make msvc_windows.v work with -os cross
return true
}
if prefs.os == .windows && (file.ends_with('_nix.c.v') || file.ends_with('_nix.v')) {
return false
}
if prefs.os != .windows && (file.ends_with('_windows.c.v') || file.ends_with('_windows.v')) {
return false
}
//
if prefs.os != .linux && (file.ends_with('_linux.c.v') || file.ends_with('_linux.v')) {
return false
}
//
if prefs.os != .macos && (file.ends_with('_darwin.c.v') || file.ends_with('_darwin.v')) {
return false
}
if prefs.os != .macos && (file.ends_with('_macos.c.v') || file.ends_with('_macos.v')) {
return false
}
//
if prefs.os != .ios && (file.ends_with('_ios.c.v') || file.ends_with('_ios.v')) {
return false
}
if prefs.os != .freebsd && file.ends_with('_freebsd.c.v') {
return false
}
if prefs.os != .openbsd && file.ends_with('_openbsd.c.v') {
return false
}
if prefs.os != .netbsd && file.ends_with('_netbsd.c.v') {
return false
}
if prefs.os != .dragonfly && file.ends_with('_dragonfly.c.v') {
return false
}
if prefs.os != .solaris && file.ends_with('_solaris.c.v') {
return false
}
if prefs.os != .qnx && file.ends_with('_qnx.c.v') {
return false
}
if prefs.os != .serenity && file.ends_with('_serenity.c.v') {
return false
}
if prefs.os != .plan9 && file.ends_with('_plan9.c.v') {
return false
}
if prefs.os != .vinix && file.ends_with('_vinix.c.v') {
return false
}
if prefs.os in [.android, .termux] {
// Note: Termux is running natively on Android devices, but the compilers there (clang) usually do not have access
// to the Android SDK. The code here ensures that you can have `_termux.c.v` and `_android_outside_termux.c.v` postfixes,
// to target both the cross compilation case (where the SDK headers are used and available), and the Termux case,
// where the Android SDK is not used.
if file.ends_with('_android.c.v') {
// common case, should compile for both cross android and termux
// eprintln('prefs.os: $prefs.os | file: $file | common')
return true
}
if file.ends_with('_android_outside_termux.c.v') {
// compile code that targets Android, but NOT Termux (i.e. the SDK is available)
// eprintln('prefs.os: $prefs.os | file: $file | android_outside_termux')
return prefs.os == .android
}
if file.ends_with('_termux.c.v') {
// compile Termux specific code
// eprintln('prefs.os: $prefs.os | file: $file | termux specific')
return prefs.os == .termux
}
} else if file.ends_with('_android.c.v') || file.ends_with('_termux.c.v')
|| file.ends_with('_android_outside_termux.c.v') {
return false
}
return true
}
pub fn (prefs &Preferences) should_compile_asm(path string) bool {
if path.count('.') != 2 || path.ends_with('c.v') || path.ends_with('js.v') {
return true
}
file := path.all_before_last('.v')
arch := arch_from_string(file.all_after_last('.')) or { Arch._auto }
if arch != prefs.arch && prefs.arch != ._auto && arch != ._auto {
return false
}
file_os := os_from_string(file.all_after_last('_').all_before('.')) or { OS._auto }
if file_os != prefs.os && prefs.os != ._auto && file_os != ._auto {
return false
}
return true
}
pub fn (prefs &Preferences) should_compile_js(file string) bool {
if !file.ends_with('.js.v') && file.split('.').len > 2 {
// Probably something like `a.c.v`.
return false
}
return true
}
// is_target_of returns true if this_os is included in the target specified
// for example, 'nix' is true for Linux and FreeBSD but not Windows
pub fn (this_os OS) is_target_of(target string) bool {
if this_os == .all {
return true
}
// Note: Termux is running natively on Android devices, but the compilers there (clang) usually do not have access
// to the Android SDK. The code here ensures that you can have `_termux.c.v` and `_android_outside_termux.c.v` postfixes,
// to target both the cross compilation case (where the SDK headers are used and available), and the Termux case,
// where the Android SDK is not used.
// 'nix' means "all but Windows"
if (this_os == .windows && target == 'nix')
|| (this_os != .windows && target == 'windows')
|| (this_os != .linux && target == 'linux')
|| (this_os != .macos && target in ['darwin', 'macos'])
|| (this_os != .ios && target == 'ios')
|| (this_os != .freebsd && target == 'freebsd')
|| (this_os != .openbsd && target == 'openbsd')
|| (this_os != .netbsd && target == 'netbsd')
|| (this_os != .dragonfly && target == 'dragonfly')
|| (this_os != .solaris && target == 'solaris')
|| (this_os != .qnx && target == 'qnx')
|| (this_os != .serenity && target == 'serenity')
|| (this_os != .plan9 && target == 'plan9')
|| (this_os != .vinix && target == 'vinix')
|| (this_os != .android && target in ['android', 'android_outside_termux'])
|| (this_os != .termux && target == 'termux') {
return false
}
return true
}