Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add -municode for MINGW #1802

Merged
merged 5 commits into from
Dec 18, 2023
Merged

Add -municode for MINGW #1802

merged 5 commits into from
Dec 18, 2023

Conversation

vrabaud
Copy link
Collaborator

@vrabaud vrabaud commented Nov 23, 2023

Fixes #1755

Copy link
Collaborator

@wantehchang wantehchang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I suggest a change.

CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Outdated
@@ -299,7 +299,10 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
elseif(CMAKE_C_COMPILER_ID MATCHES "GNU")
message(STATUS "libavif: Enabling warnings for GCC")
add_compile_options(-Wall -Wextra)
elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
elseif(MINGW)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should test this. I remember MINGW is GCC, so I am worried that it will match the GCC check at line 299 instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely, let me add a MINGW workflow from https://github.com/msys2/setup-msys2

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If MINGW is identified as GCC, we will need to handle it as follows:

elseif(CMAKE_C_COMPILER_ID MATCHES "GNU")
    message(STATUS "libavif: Enabling warnings for GCC")
    add_compile_options(-Wall -Wextra)
    if(MINGW)
       add_compile_options(-municode)
    endif()
elseif(MSVC)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Web I found at least two pages that say -municode can be used as a linker option. Here is a patch file to do that:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 12e0a10..6b05fb7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -802,11 +802,17 @@ if(AVIF_BUILD_APPS)
     if(AVIF_USE_CXX)
         set_target_properties(avifenc PROPERTIES LINKER_LANGUAGE "CXX")
     endif()
+    if(MINGW)
+        target_link_options(avifenc PRIVATE -municode)
+    endif()
     target_link_libraries(avifenc avif_apps)
     add_executable(avifdec apps/avifdec.c)
     if(AVIF_USE_CXX)
         set_target_properties(avifdec PROPERTIES LINKER_LANGUAGE "CXX")
     endif()
+    if(MINGW)
+        target_link_options(avifdec PRIVATE -municode)
+    endif()
     target_link_libraries(avifdec avif_apps)

     if(NOT SKIP_INSTALL_APPS AND NOT SKIP_INSTALL_ALL)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index d174e05..b8d4b10 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -223,6 +223,9 @@ if(AVIF_BUILD_APPS)
     # When building apps, test the avifenc/avifdec.
     # 'are_images_equal' is used to make sure inputs/outputs are unchanged.
     add_executable(are_images_equal gtest/are_images_equal.cc)
+    if(MINGW)
+        target_link_options(are_images_equal PRIVATE -municode)
+    endif()
     target_link_libraries(are_images_equal aviftest_helpers)
     add_test(NAME test_cmd COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/test_cmd.sh ${CMAKE_BINARY_DIR}
                                    ${CMAKE_CURRENT_SOURCE_DIR}/data

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some webpages also say if wmain() is defined in a C++ file, it needs to be declared as extern "C" for the g++ in MinGW. In my testing I don't need to make that change to are_images_equal.cc.

Copy link
Contributor

@kmilos kmilos Nov 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, MINGW is defined for both GCC and Clang. See

https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/Platform/Windows-GNU.cmake
https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/Platform/Windows-Clang.cmake

In the CI, you can/should test both UCRT64 and CLANG64 environments.

Btw, don't you want all those (or some) CMAKE_C_COMPILER_ID MATCHES "GNU" checks to apply to Clang as well?

CMakeLists.txt Outdated
@@ -299,7 +299,10 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
elseif(CMAKE_C_COMPILER_ID MATCHES "GNU")
message(STATUS "libavif: Enabling warnings for GCC")
add_compile_options(-Wall -Wextra)
elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
elseif(MINGW)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If MINGW is identified as GCC, we will need to handle it as follows:

elseif(CMAKE_C_COMPILER_ID MATCHES "GNU")
    message(STATUS "libavif: Enabling warnings for GCC")
    add_compile_options(-Wall -Wextra)
    if(MINGW)
       add_compile_options(-municode)
    endif()
elseif(MSVC)

Comment on lines 48 to 52
- name: Build GoogleTest
if: steps.cache-ext.outputs.cache-hit != 'true'
working-directory: ./ext
run: bash -e googletest.cmd
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just in case you want to make the CI faster, MSYS2 ships googletest already...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but I thought (just like on Ubuntu), that it was better to compile gtest from source to make sure the same compile flags are passed?

@vrabaud
Copy link
Collaborator Author

vrabaud commented Nov 24, 2023

Ok, I added a working CI.
@kmilos , it is now failing for pure code reasons: -municode is set, wmain is used, but setlocale(LC_ALL, ".UTF8") does not work. Any way you can help me with that? Thx!

@kmilos
Copy link
Contributor

kmilos commented Nov 24, 2023

setlocale(LC_ALL, ".UTF8") does not work

@vrabaud It seems to not fail in UCRT64 and CLANG64 environments (as they use the modern UCRT), but obviously fail in the legacy MINGW32/64 ones as they use MSVCRT where .utf8 locales are non-existent. In MINGW32/64 (i.e. MSVCRT), there's no way around not using wstring/wchar_t and W APIs for i18n.

In order to just avoid the error, you can wrap the setlocale() call w/ #ifdef _UCRT I guess.

I guess what you need to decide/say is - libavif is dropping support for MSVCRT (MINGW32/64 and anything before Windows 10 1903 and VS 2015), and will have only UCRT builds (and CI) w/ UTF-8, so default on VS 2015 and later, and UCRT64+CLANG64 (and possibly CLANG32 if you really want to cover x86).

@vrabaud
Copy link
Collaborator Author

vrabaud commented Nov 24, 2023

Thx @kmilos for the explanation. How about:

  • I remove -municode for MINGW32/64
  • I also check for __MINGW32__ and __MINGW64__ not being defined when defining INIT_ARGV with setlocale in apps/shared/avifutil.h?
  • I disable the UTF8 test for MINGW32/64

This way, MINGW32/64 is supported, not just UTF8

@kmilos
Copy link
Contributor

kmilos commented Nov 24, 2023

  • I also check for __MINGW32__ and __MINGW64__ not being defined when defining INIT_ARGV with setlocale in apps/shared/avifutil.h?

These are defined for all MinGW environments (and it's redundant to check for __MINGW64__ like it is redundant to check for _WIN64 if you already check for _WIN32). They really just define the platform, not the actual toolchain details. I guess you really want to check for _UCRT as the runtime C library being used (by either MSVC or MinGW toolchains).

Good idea for the other two points!

Although, not sure how to tell the difference between e.g. MINGW64 vs UCRT64 from within CMake!? Some small test code?

@vrabaud
Copy link
Collaborator Author

vrabaud commented Nov 24, 2023

Indeed, the only thing I found so far (from https://discourse.cmake.org/t/how-to-check-that-the-current-compiler-is-gcc-msys-when-using-ninja-generator/6698/5) is to run gcc -dumpmachine.

@kmilos
Copy link
Contributor

kmilos commented Nov 24, 2023

Indeed, the only thing I found so far (from https://discourse.cmake.org/t/how-to-check-that-the-current-compiler-is-gcc-msys-when-using-ninja-generator/6698/5) is to run gcc -dumpmachine.

Again, not the same thing. There's no problem telling if you're building for MINGW vs MSYS/CYGWIN (those all exist in CMake as variables already, so there's no need for such acrobatics). You can also tell GCC vs Clang w/ CMAKE_{C,CXX}_COMPILER_ID. But AFAIK you can't tell between MSVCRT and UCRT? You can only e.g. check the MSYSTEM environment variable perhaps...

Btw, gcc -dumpmachine in the UCRT64 environment returns the same as in MINGW64: x86_64-w64-mingw32, it doesn't tell you anything about the the C runtime.

So something like if(MINGW AND NOT "$ENV{MSYSTEM}" MATCHES "(MINGW32|MINGW64)")?

@vrabaud
Copy link
Collaborator Author

vrabaud commented Nov 24, 2023

Thx, @kmilos, that works ! Still I had to disable mingw32: some errors appeared that seem unrelated: https://github.com/vrabaud/libavif/actions/runs/6985029492/job/19008737494#step:3:79
mingw64 is fine though.

tests/CMakeLists.txt Outdated Show resolved Hide resolved
@wantehchang
Copy link
Collaborator

Vincent: I assume this pull request has stabilized. I will review it tomorrow (Thursday).

Copy link
Collaborator

@wantehchang wantehchang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you very much for all your work on this.

apps/shared/avifutil.h Outdated Show resolved Hide resolved
apps/shared/avifutil.h Outdated Show resolved Hide resolved
apps/shared/avifutil.h Show resolved Hide resolved
tests/CMakeLists.txt Outdated Show resolved Hide resolved
tests/CMakeLists.txt Show resolved Hide resolved
@@ -431,7 +431,7 @@ endif()
# /usr/local/include.
set(CMAKE_FIND_FRAMEWORK LAST)

if(UNIX)
if(UNIX OR MINGW)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: This seems like an unrelated bug fix. Would be good to move it to a separate pull request. Or at least describe this bug fix in the commit message.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit message.

CMakeLists.txt Show resolved Hide resolved
.github/workflows/ci-mingw.yml Show resolved Hide resolved
.github/workflows/ci-mingw.yml Show resolved Hide resolved
Also add CI for MinGW
- add cmp and convert utilities.
- use m with gcc and pthreads with clang
@vrabaud vrabaud merged commit 1fb7a8a into AOMediaCodec:main Dec 18, 2023
20 of 21 checks passed
@vrabaud vrabaud deleted the mingw branch December 18, 2023 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Building in MSYS2/MinGW with GCC 13.2 fails: undefined reference to `WinMain@16'
4 participants