diff --git a/cmd/v/help/build-c.txt b/cmd/v/help/build-c.txt index a1995b3179..d8e48027a9 100644 --- a/cmd/v/help/build-c.txt +++ b/cmd/v/help/build-c.txt @@ -25,7 +25,20 @@ see also `v help build`. -cstrict Turn on additional C warnings. This slows down compilation - slightly (~10% for gcc), but sometimes provides better diagnosis. + slightly (~10% for gcc), but sometimes provides better error diagnosis. + + -cmain + Useful with framework like code, that uses macros to re-define `main`, like SDL2 does for example. + With that option, V will always generate: + `int MainFunctionName(int ___argc, char** ___argv) {` , for the program entry point function, *no matter* the OS. + Without it, on non Windows systems, it will generate: + `int main(int ___argc, char** ___argv) {` + ... and on Windows, it will generate: + a) `int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, LPWSTR cmd_line, int show_cmd){` + when you are compiling applications that `import gg`. + ... or it will generate: + b) `int wmain(int ___argc, wchar_t* ___argv[], wchar_t* ___envp[]){` + when you are compiling console apps. -showcc Prints the C command that is used to build the program. diff --git a/vlib/v/gen/c/cmain.v b/vlib/v/gen/c/cmain.v index ed07c9a618..25432022f5 100644 --- a/vlib/v/gen/c/cmain.v +++ b/vlib/v/gen/c/cmain.v @@ -50,7 +50,11 @@ fn (mut g Gen) gen_vlines_reset() { } } -fn (mut g Gen) gen_c_main_function_header() { +fn (mut g Gen) gen_c_main_function_only_header() { + if g.pref.cmain != '' { + g.writeln('int ${g.pref.cmain}(int ___argc, char** ___argv){') + return + } if g.pref.os == .windows { if g.is_gui_app() { $if msvc { @@ -65,13 +69,17 @@ fn (mut g Gen) gen_c_main_function_header() { g.writeln('\tcmd_line_to_argv CommandLineToArgvW = (cmd_line_to_argv)GetProcAddress(shell32_module, "CommandLineToArgvW");') g.writeln('\tint ___argc;') g.writeln('\twchar_t** ___argv = CommandLineToArgvW(full_cmd_line, &___argc);') - } else { - // Console application - g.writeln('int wmain(int ___argc, wchar_t* ___argv[], wchar_t* ___envp[]){') + return } - } else { - g.writeln('int main(int ___argc, char** ___argv){') + // Console application + g.writeln('int wmain(int ___argc, wchar_t* ___argv[], wchar_t* ___envp[]){') + return } + g.writeln('int main(int ___argc, char** ___argv){') +} + +fn (mut g Gen) gen_c_main_function_header() { + g.gen_c_main_function_only_header() g.writeln('\tg_main_argc = ___argc;') g.writeln('\tg_main_argv = ___argv;') if g.nr_closures > 0 { diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index a5d24c587e..0af3de4319 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -163,6 +163,7 @@ pub mut: bare_builtin_dir string // Set by -bare-builtin-dir xyz/ . The xyz/ module should contain implementations of malloc, memset, etc, that are used by the rest of V's `builtin` module. That option is only useful with -freestanding (i.e. when is_bare is true). no_preludes bool // Prevents V from generating preludes in resulting .c files custom_prelude string // Contents of custom V prelude that will be prepended before code in resulting .c files + cmain string // The name of the generated C main function. Useful with framework like code, that uses macros to re-define `main`, like SDL2 does. When set, V will always generate `int THE_NAME(int ___argc, char** ___argv){`, *no matter* the platform. lookup_path []string output_cross_c bool // true, when the user passed `-os cross` output_es5 bool @@ -686,6 +687,10 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin res.custom_prelude = prelude i++ } + '-cmain' { + res.cmain = cmdline.option(current_args, '-cmain', '') + i++ + } else { if command == 'build' && is_source_file(arg) { eprintln('Use `v $arg` instead.')