From 793487fd6d0f720414466d137684027394aea4b3 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Tue, 11 Feb 2025 23:48:19 +0800 Subject: [PATCH] cgen,builder: fix windows 32bit dll function name mangle (fix #23689) (#23690) --- vlib/v/builder/msvc_windows.v | 7 +++++++ vlib/v/gen/c/cgen.v | 15 ++++++++++++++- vlib/v/gen/c/fn.v | 2 ++ vlib/v/tests/create_dll/create_win_dll_test.v | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/vlib/v/builder/msvc_windows.v b/vlib/v/builder/msvc_windows.v index 09496f8da4e2aa..65c16e58738a44 100644 --- a/vlib/v/builder/msvc_windows.v +++ b/vlib/v/builder/msvc_windows.v @@ -337,6 +337,13 @@ pub fn (mut v Builder) cc_msvc() { // Libs are passed to cl.exe which passes them to the linker a << real_libs.join(' ') a << '/link' + if v.pref.is_shared { + // generate a .def for export function names, avoid function name mangle + // must put after the /link flag! + def_name := v.pref.out_name[0..v.pref.out_name.len - 4] + a << '/DEF:' + os.quoted_path('${def_name}.def') + } + a << '/nologo' // NOTE: /NOLOGO is explicitly not recognised! a << '/OUT:${os.quoted_path(v.pref.out_name)}' a << r.library_paths() diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index f12be502cef295..3b5a734f37a9a6 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -263,7 +263,8 @@ mut: has_debugger bool // $dbg has been used in the code reflection_strings &map[string]int defer_return_tmp_var string - vweb_filter_fn_name string // vweb__filter or x__vweb__filter, used by $vweb.html() for escaping strings in the templates, depending on which `vweb` import is used + vweb_filter_fn_name string // vweb__filter or x__vweb__filter, used by $vweb.html() for escaping strings in the templates, depending on which `vweb` import is used + export_funcs []string // for .dll export function names } @[heap] @@ -403,6 +404,7 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) GenO global_g.embedded_data.write(g.embedded_data) or { panic(err) } global_g.shared_types.write(g.shared_types) or { panic(err) } global_g.shared_functions.write(g.channel_definitions) or { panic(err) } + global_g.export_funcs << g.export_funcs global_g.force_main_console = global_g.force_main_console || g.force_main_console @@ -717,6 +719,15 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) GenO helpers.writeln(fn_def) } } + + if g.pref.is_shared && g.pref.os == .windows && g.export_funcs.len > 0 { + // generate a .def for export function names, avoid function name mangle + def_name := g.pref.out_name[0..g.pref.out_name.len - 4] + dll_name := g.pref.out_name.all_after_last('\\') + file_content := 'LIBRARY ${dll_name}.dll\n\nEXPORTS\n' + g.export_funcs.join('\n') + os.write_file('${def_name}.def', file_content) or { panic(err) } + } + // End of out_0.c shelpers := helpers.str() @@ -6366,6 +6377,7 @@ fn (mut g Gen) write_init_function() { if g.pref.os != .windows { g.writeln('__attribute__ ((constructor))') } + g.export_funcs << '_vinit_caller' g.writeln('void _vinit_caller() {') g.writeln('\tstatic bool once = false; if (once) {return;} once = true;') if g.nr_closures > 0 { @@ -6377,6 +6389,7 @@ fn (mut g Gen) write_init_function() { if g.pref.os != .windows { g.writeln('__attribute__ ((destructor))') } + g.export_funcs << '_vcleanup_caller' g.writeln('void _vcleanup_caller() {') g.writeln('\tstatic bool once = false; if (once) {return;} once = true;') g.writeln('\t_vcleanup();') diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index da866b58b42e25..9f0e2a0e1c5b2b 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -367,6 +367,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) { } if is_liveshared { if g.pref.os == .windows { + g.export_funcs << impl_fn_name g.definitions.write_string('VV_EXPORTED_SYMBOL ${type_name} ${impl_fn_name}(') g.write('VV_EXPORTED_SYMBOL ${type_name} ${impl_fn_name}(') } else { @@ -538,6 +539,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) { if attr.name == 'export' { weak := if node.attrs.any(it.name == 'weak') { 'VWEAK ' } else { '' } g.writeln('// export alias: ${attr.arg} -> ${name}') + g.export_funcs << attr.arg export_alias := '${weak}${type_name} ${fn_attrs}${attr.arg}(${arg_str})' g.definitions.writeln('VV_EXPORTED_SYMBOL ${export_alias}; // exported fn ${node.name}') g.writeln('${export_alias} {') diff --git a/vlib/v/tests/create_dll/create_win_dll_test.v b/vlib/v/tests/create_dll/create_win_dll_test.v index 160469056c9c3c..c63d01bf50a16e 100644 --- a/vlib/v/tests/create_dll/create_win_dll_test.v +++ b/vlib/v/tests/create_dll/create_win_dll_test.v @@ -54,7 +54,7 @@ fn test_create_and_dllmain() { run_test('clang32') } $if msvc { - // run_test('msvc32') // something wrong as it passes when it should fail + run_test('msvc32') } } }