Catch2 icon indicating copy to clipboard operation
Catch2 copied to clipboard

MinGW: `CATCH_CONFIG_MAIN` defines the non-standard `WinMain` instead of the standard `main` function

Open aminya opened this issue 2 years ago • 11 comments

Describe the bug Once you define the CATCH_CONFIG_MAIN definition on MinGW, it defines a non-standard main function called WinMain. This results in a lot of undefined references. This doesn't happen with other compilers.

https://github.com/aminya/cpp_vcpkg_project/runs/6542106054?check_suite_focus=true#step:6:203

[6/18] Linking CXX executable my_exe\test\Debug\my_exe_helpers_tests.exe
FAILED: my_exe/test/Debug/my_exe_helpers_tests.exe 
cmd.exe /C "cd . && C:\Users\runneradmin\gcc\mingw64\bin\g++.exe -g  my_exe/test/CMakeFiles/my_exe_helpers_tests.dir/Debug/tests.cpp.obj -o my_exe\test\Debug\my_exe_helpers_tests.exe -Wl,--out-implib,my_exe\test\Debug\libmy_exe_helpers_tests.dll.a -Wl,--major-image-version,0,--minor-image-version,0  vcpkg_installed/x64-mingw-static/debug/lib/libfmtd.a  --coverage  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
c:/users/runneradmin/gcc/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: c:/users/runneradmin/gcc/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text+0x46): undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
[7/18] Linking CXX executable my_lib\test\Debug\my_lib_tests.exe
FAILED: my_lib/test/Debug/my_lib_tests.exe my_lib/test/my_lib_tests_tests-84286ba.cmake D:/a/cpp_vcpkg_project/cpp_vcpkg_project/build/my_lib/test/my_lib_tests_tests-84286ba.cmake 
cmd.exe /C "cd . && C:\Users\runneradmin\gcc\mingw64\bin\g++.exe -g  my_lib/test/CMakeFiles/my_lib_tests.dir/Debug/tests.cpp.obj -o my_lib\test\Debug\my_lib_tests.exe -Wl,--out-implib,my_lib\test\Debug\libmy_lib_tests.dll.a -Wl,--major-image-version,0,--minor-image-version,0  my_lib/Debug/libmy_lib.a  --coverage  vcpkg_installed/x64-mingw-static/debug/lib/libfmtd.a  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cmd.exe /C "cd /D D:\a\cpp_vcpkg_project\cpp_vcpkg_project\build\my_lib\test && C:\Users\runneradmin\cmake\cmake-3.23.1-windows-x86_64\bin\cmake.exe -D TEST_TARGET=my_lib_tests -D TEST_EXECUTABLE=D:/a/cpp_vcpkg_project/cpp_vcpkg_project/build/my_lib/test/Debug/my_lib_tests.exe -D TEST_EXECUTOR= -D TEST_WORKING_DIR=D:/a/cpp_vcpkg_project/cpp_vcpkg_project/build/my_lib/test -D TEST_SPEC= -D TEST_EXTRA_ARGS= -D TEST_PROPERTIES= -D TEST_PREFIX= -D TEST_SUFFIX= -D TEST_LIST=my_lib_tests_TESTS -D TEST_REPORTER=xml -D TEST_OUTPUT_DIR= -D TEST_OUTPUT_PREFIX= -D TEST_OUTPUT_SUFFIX= -D CTEST_FILE=D:/a/cpp_vcpkg_project/cpp_vcpkg_project/build/my_lib/test/my_lib_tests_tests-84286ba.cmake -P D:/a/cpp_vcpkg_project/cpp_vcpkg_project/build/vcpkg_installed/x64-mingw-static/share/catch2/CatchAddTests.cmake""
c:/users/runneradmin/gcc/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: c:/users/runneradmin/gcc/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text+0x46): undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
[8/18] Building CXX object my_header_lib/test/constexpr/CMakeFiles/my_header_lib_relaxed_constexpr_tests.dir/Debug/constexpr_tests.cpp.obj
Checking D:\a\cpp_vcpkg_project\cpp_vcpkg_project\my_header_lib\test\constexpr\constexpr_tests.cpp ...
Checking D:\a\cpp_vcpkg_project\cpp_vcpkg_project\my_header_lib\test\constexpr\constexpr_tests.cpp: CATCH_CONFIG_MAIN=1;CATCH_CONFIG_RUNTIME_STATIC_REQUIRE=1;FMT_LOCALE=1;UNICODE=1;_UNICODE=1;CMAKE_INTDIR="Debug"...
ninja: build stopped: subcommand failed.
task: Failed to run task "coverage": task: Failed to run task "build_template": exit status 1

Expected behavior CATCH_CONFIG_MAIN should define a standard main on MinGW

Reproduction steps

  • Install MinGW from here
  • Clone this branch: https://github.com/aminya/cpp_vcpkg_project/tree/mingw
  • Then run task test or make test

Platform information:

  • OS: Windows NT
  • Compiler+version: GCC v11
  • Catch version: v2.13.7

Additional context

Blocks https://github.com/aminya/project_options/issues/129 Related issues:

  • https://github.com/brechtsanders/winlibs_mingw/issues/106
  • https://sourceforge.net/p/mingw-w64/bugs/942/
  • https://github.com/catchorg/Catch2/issues/1287

aminya avatar May 29 '22 02:05 aminya

There is an explicit code that results in this issue. I don't know why just Catch2 doesn't use main on Windows similar to others!

https://github.com/catchorg/Catch2/blob/e33de8fc05ca80923a8216a8aecd6a1afc5e00af/include/internal/catch_default_main.hpp#L16-L18

aminya avatar Jun 01 '22 23:06 aminya

I am pretty sure you are wrong here.

This linking error:

c:/users/runneradmin/gcc/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text+0x46): undefined reference to `WinMain'

means that libmingw32.a is missing the reference to WinMain (because Catch2 doesn't provide it, it isn't a GUI subsystem application).

From a quick google, the issue is that you need to add -municode when building the executable (likely the link step is enough) so that MinGW understands to target wmain entry point and not main entry point.

horenmar avatar Jun 05 '22 15:06 horenmar

Adding -municode doesn't fix undefined references to `WinMain' https://github.com/aminya/project_options/issues/129

Why do you want to use non-standard wmain on Windows?

aminya avatar Jun 05 '22 16:06 aminya

-municode needs to be added as link option, not compile option.

As to your question, wmain is used on Windows, when you provide _UNICODE define during compilation. This means that you require support for unicode, which requires wmain so that you can accept wchar_t (unicode-ish) arguments.

horenmar avatar Jun 05 '22 20:06 horenmar

If you want to keep this Unicode default on MinGW, you should handle -municode inside Catch2's CMake files. By default, it is not possible to build a simple test on MinGW.

aminya avatar Jun 09 '22 19:06 aminya

Adding -municode to the link options changes the error: undefined reference to 'wWinMain'

https://github.com/aminya/project_options/runs/6819912259?check_suite_focus=true#step:5:458

cmd.exe /C "cd . && C:\Users\runneradmin\gcc\mingw64\bin\g++.exe -O3 -DNDEBUG -municode CMakeFiles/main.dir/Release/src/main/main.cpp.obj -o Release\main.exe -Wl,--out-implib,Release\libmain.dll.a -Wl,--major-image-version,0,--minor-image-version,0  vcpkg_installed/x64-mingw-static/lib/libfmt.a  --coverage  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cmd.exe /C "cd /D D:\a\project_options\project_options\test\build && "C:\Program Files\PowerShell\7\pwsh.exe" -noprofile -executionpolicy Bypass -file C:/Users/runneradmin/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/a/project_options/project_options/test/build/Release/main.exe -installedDir D:/a/project_options/project_options/test/build/vcpkg_installed/x64-mingw-static/bin -OutVariable out""
c:/users/runneradmin/gcc/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: c:/users/runneradmin/gcc/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_w.o):crt0_w.c:(.text+0x41): undefined reference to `wWinMain'

aminya avatar Jun 09 '22 22:06 aminya

Mingw doesn't use wmain as wWinMain. It might be because the function prototype looks different than what Catch2 is using.

https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/#unicode-applications

Current MinGW status:

  • Doesn't compile without Unicode because of an undefined reference to WinMain.
  • Doesn't compile with Unicode because of an undefined reference to wWinMain.

This can be simply fixed by using the standard main function!

aminya avatar Jun 20 '22 19:06 aminya

@horenmar any update on my comments and pull request?

aminya avatar Jul 13 '22 00:07 aminya

My build worked using v.3.1.0 but gives undefined reference to WinMain at v.3.2.0. Turns out in cmake I needed to link with Catch2::Catch2WithMain instead of Catch2::Catch2

msd avatar Nov 26 '22 22:11 msd

For anyone who is still struggling with this, as a last resort you can provide your own main as per the example: https://github.com/catchorg/Catch2/blob/devel/docs/own-main.md

dnwpark avatar Dec 31 '23 04:12 dnwpark

-DDO_NOT_USE_WMAIN=ON can make mingw happy.

tedli avatar Apr 07 '24 03:04 tedli