-
Notifications
You must be signed in to change notification settings - Fork 470
Description
Bug: EntryPoint.h defines functions in a header, causing potential ODR violations
Description
The current EntryPoint.h defines WinMain and main directly inside a header file. While #pragma once prevents re-inclusion within the same translation unit, it does not protect across multiple translation units. Each .cpp file that includes this header is its own translation unit, so if a user accidentally includes EntryPoint.h in more than one .cpp file, the linker will throw a cryptic duplicate symbol error:
error LNK2005: _main already defined in Main.obj
error LNK2005: _WinMain already defined in Main.obj
This can be especially confusing for beginners who may not immediately understand why the linker is complaining.
Steps to Reproduce
- Create a new Walnut project
- Create a second
.cppfile and includeEntryPoint.hin it - Build the project
- Observe the linker error with no helpful diagnostic message
Suggested Fix
Move the WinMain and main definitions into a dedicated EntryPoint.cpp file, and keep only the extern int VX_Main(int argc, char* argv[]); declaration in the header:
EntryPoint.h
#pragma once
extern int VX_Main(int argc, char* argv[]);EntryPoint.cpp
#include "EntryPoint.h"
#ifdef WL_PLATFORM_WINDOWS
#include <Windows.h>
int WINAPI WinMain(...) { return VX_Main(__argc, __argv); }
int main(int argc, char* argv[]) { return VX_Main(argc, argv); }
#else
int main(int argc, char* argv[]) { return VX_Main(argc, argv); }
#endifThis follows the fundamental C++ rule of declarations in headers, definitions in source files, and eliminates the ODR risk entirely.
Additional Notes
An alternative mitigation (short of moving to a .cpp) is an opt-in macro guard that produces a clear #error message if the header is misused — but this still cannot fully prevent the problem across translation units. The .cpp approach is the only complete fix.
Thanks for the great framework!