aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/old/cmd/tools/check_os_api_parity.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/old/cmd/tools/check_os_api_parity.v')
-rw-r--r--v_windows/v/old/cmd/tools/check_os_api_parity.v130
1 files changed, 130 insertions, 0 deletions
diff --git a/v_windows/v/old/cmd/tools/check_os_api_parity.v b/v_windows/v/old/cmd/tools/check_os_api_parity.v
new file mode 100644
index 0000000..d4b925c
--- /dev/null
+++ b/v_windows/v/old/cmd/tools/check_os_api_parity.v
@@ -0,0 +1,130 @@
+module main
+
+import os
+import v.util
+import v.util.diff
+import v.pref
+import v.builder
+import v.ast
+import rand
+import term
+
+const (
+ base_os = 'linux'
+ os_names = ['linux', 'macos', 'windows']
+ skip_modules = [
+ 'builtin.bare',
+ 'builtin.linux_bare.old',
+ 'builtin.js',
+ 'strconv',
+ 'strconv.ftoa',
+ 'hash',
+ 'strings',
+ 'crypto.rand',
+ 'os.bare',
+ 'os2',
+ 'picohttpparser',
+ 'picoev',
+ 'szip',
+ 'v.eval',
+ ]
+)
+
+struct App {
+ diff_cmd string
+ is_verbose bool
+ modules []string
+mut:
+ api_differences map[string]int
+}
+
+fn main() {
+ vexe := pref.vexe_path()
+ vroot := os.dir(vexe)
+ util.set_vroot_folder(vroot)
+ os.chdir(vroot)
+ cmd := diff.find_working_diff_command() or { '' }
+ mut app := App{
+ diff_cmd: cmd
+ is_verbose: os.getenv('VERBOSE').len > 0
+ modules: if os.args.len > 1 { os.args[1..] } else { all_vlib_modules() }
+ }
+ for mname in app.modules {
+ if !app.is_verbose {
+ eprintln('Checking module: $mname ...')
+ }
+ api_base := app.gen_api_for_module_in_os(mname, base_os)
+ for oname in os_names {
+ if oname == base_os {
+ continue
+ }
+ api_os := app.gen_api_for_module_in_os(mname, oname)
+ app.compare_api(api_base, api_os, mname, base_os, oname)
+ }
+ }
+ howmany := app.api_differences.len
+ if howmany > 0 {
+ eprintln(term.header('Found $howmany modules with different APIs', '='))
+ for m in app.api_differences.keys() {
+ eprintln('Module: $m')
+ }
+ exit(1)
+ }
+}
+
+fn all_vlib_modules() []string {
+ mut vlib_v_files := os.walk_ext('vlib', '.v')
+ mut vmodulesmap := map[string]int{}
+ for f in vlib_v_files {
+ if f.contains('/tests/') || f.ends_with('_test.v') {
+ continue
+ }
+ vmodulename := os.dir(f).replace('/', '.').replace('vlib.', '')
+ if vmodulename in skip_modules {
+ continue
+ }
+ vmodulesmap[vmodulename] = vmodulesmap[vmodulename] + 1
+ }
+ mut modules := vmodulesmap.keys()
+ modules.sort()
+ return modules
+}
+
+fn (app App) gen_api_for_module_in_os(mod_name string, os_name string) string {
+ if app.is_verbose {
+ eprintln('Checking module: ${mod_name:-30} for OS: ${os_name:-10} ...')
+ }
+ mpath := os.join_path('vlib', mod_name.replace('.', '/'))
+ tmpname := '/tmp/${mod_name}_${os_name}.c'
+ prefs, _ := pref.parse_args([], ['-os', os_name, '-o', tmpname, '-shared', mpath])
+ mut b := builder.new_builder(prefs)
+ b.compile_c()
+ mut res := []string{}
+ for f in b.parsed_files {
+ for s in f.stmts {
+ if s is ast.FnDecl {
+ if s.is_pub {
+ fn_signature := s.stringify(b.table, mod_name, map[string]string{})
+ fn_mod := s.modname()
+ if fn_mod == mod_name {
+ fline := '$fn_mod: $fn_signature'
+ res << fline
+ }
+ }
+ }
+ }
+ }
+ res.sort()
+ return res.join('\n')
+}
+
+fn (mut app App) compare_api(api_base string, api_os string, mod_name string, os_base string, os_target string) {
+ res := diff.color_compare_strings(app.diff_cmd, rand.ulid(), api_base, api_os)
+ if res.len > 0 {
+ summary := 'Different APIs found for module: `$mod_name`, between OS base: `$os_base` and OS: `$os_target`'
+ eprintln(term.header(summary, '-'))
+ eprintln(res)
+ eprintln(term.h_divider('-'))
+ app.api_differences[mod_name] = 1
+ }
+}