catchorg / Catch2

A modern, C++-native, test framework for unit-tests, TDD and BDD - using C++14, C++17 and later (C++11 support is in v2.x branch, and C++03 on the Catch1.x branch)
https://discord.gg/4CWS9zD
Boost Software License 1.0
18.46k stars 3.02k forks source link

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

Open aminya opened 2 years ago

aminya commented 2 years ago

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

Platform information:

Additional context

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

aminya commented 2 years ago

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

horenmar commented 2 years ago

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.

aminya commented 2 years ago

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?

horenmar commented 2 years ago

-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.

aminya commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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:

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

aminya commented 2 years ago

@horenmar any update on my comments and pull request?

msd commented 1 year ago

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

dnwpark commented 8 months ago

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

tedli commented 5 months ago

-DDO_NOT_USE_WMAIN=ON can make mingw happy.