v / vlib / v2 / builder / util.v
146 lines · 141 sloc · 3.59 KB · ddb021b9866c3b4523b746fa2f4c16a594f8bd89
Raw
1// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module builder
5
6import os
7import v2.pref
8
9fn list_dir_entries(path string) []string {
10 mut entries := os.ls(path) or { []string{} }
11 entries.sort()
12 return entries
13}
14
15pub fn get_v_files_from_dir(dir string, user_defines []string, target_os string) []string {
16 if dir == '' {
17 return []string{}
18 }
19 mod_files := list_dir_entries(dir)
20 mut v_files := []string{}
21 mut defaults := []string{}
22 for file in mod_files {
23 if file == '' {
24 continue
25 }
26 // Include .v files (including .c.v), exclude .js.v and test files
27 if !file.ends_with('.v') || file.ends_with('.js.v') || file.contains('_test.') {
28 continue
29 }
30 // skip platform-specific files
31 if file.contains('.arm64.') || file.contains('.arm32.') || file.contains('.amd64.') {
32 continue
33 }
34 // Skip files specialized for a different target OS before parsing/type checking.
35 if pref.file_has_incompatible_os_suffix(file, target_os) {
36 continue
37 }
38 if file.ends_with('prealloc.c.v') && 'prealloc' !in user_defines {
39 continue
40 }
41 // Conditional compilation files: _d_<feature> included when -d <feature> is set,
42 // _notd_<feature> included when -d <feature> is NOT set.
43 if file.contains('_notd_') {
44 feature := extract_define_feature(file, '_notd_')
45 if feature.len > 0 && feature in user_defines {
46 continue
47 }
48 } else if file.contains('_d_') {
49 feature := extract_define_feature(file, '_d_')
50 if feature.len == 0 || feature !in user_defines {
51 continue
52 }
53 }
54 path := os.join_path(dir, file)
55 if path == '' {
56 continue
57 }
58 // Collect _default.c.v files separately; they are only included when
59 // no platform-specific variant exists (e.g. _darwin.c.v, _linux.c.v).
60 if file.contains('default.c.v') {
61 defaults << path
62 } else {
63 v_files << path
64 }
65 }
66 // Add _default.c.v files only when no platform-specific variant was selected.
67 for dfile in defaults {
68 no_postfix := fname_without_platform_postfix(dfile)
69 mut has_specialized := false
70 for vf in v_files {
71 if fname_without_platform_postfix(vf) == no_postfix {
72 has_specialized = true
73 break
74 }
75 }
76 if !has_specialized {
77 v_files << dfile
78 }
79 }
80 return v_files
81}
82
83// fname_without_platform_postfix strips the platform-specific suffix from a file path,
84// so that e.g. "free_memory_impl_darwin.c.v" and "free_memory_impl_default.c.v" both
85// map to the same key, allowing detection of specialized vs default variants.
86fn fname_without_platform_postfix(file string) string {
87 return file.replace_each([
88 'default.c.v',
89 '_',
90 'windows.c.v',
91 '_',
92 'linux.c.v',
93 '_',
94 'darwin.c.v',
95 '_',
96 'macos.c.v',
97 '_',
98 'android.c.v',
99 '_',
100 'android_outside_termux.c.v',
101 '_',
102 'termux.c.v',
103 '_',
104 'ios.c.v',
105 '_',
106 'freebsd.c.v',
107 '_',
108 'openbsd.c.v',
109 '_',
110 'netbsd.c.v',
111 '_',
112 'dragonfly.c.v',
113 '_',
114 'bsd.c.v',
115 '_',
116 'solaris.c.v',
117 '_',
118 'qnx.c.v',
119 '_',
120 'serenity.c.v',
121 '_',
122 'plan9.c.v',
123 '_',
124 'vinix.c.v',
125 '_',
126 'nix.c.v',
127 '_',
128 ])
129}
130
131// extract_define_feature extracts the feature name from a _d_ or _notd_ filename.
132// e.g. "parse_d_parallel.v" with marker "_d_" returns "parallel"
133// e.g. "array_notd_gcboehm_opt.v" with marker "_notd_" returns "gcboehm_opt"
134fn extract_define_feature(file string, marker string) string {
135 idx := file.index(marker) or { return '' }
136 rest := file[idx + marker.len..]
137 // Strip .v or .c.v suffix
138 feature := if rest.ends_with('.c.v') {
139 rest[..rest.len - 4]
140 } else if rest.ends_with('.v') {
141 rest[..rest.len - 2]
142 } else {
143 rest
144 }
145 return feature
146}
147