Skip to content

Bug: EntryPoint.h defines functions in a header, causing ODR violations #96

@Flare-Technologies-2026

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

  1. Create a new Walnut project
  2. Create a second .cpp file and include EntryPoint.h in it
  3. Build the project
  4. 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); }
#endif

This 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions