Incorrect variables set when enabling Objective-C for MinGW with CMAKE_SYSTEM_NAME=Windows
To reproduce:
-
Install an x86_64-w64-mingw32 cross GCC toolchain that includes Objective-C support. MacPorts'
x86_64-w64-mingw32-gcc
works. If you have a MinGW sysroot but not a suitable GCC, you can use Clang along with a wrapper script, such as this one I used on Debian:$ cat x86_64-w64-mingw32-clang #!/bin/sh exec clang --target=x86_64-w64-mingw32 --sysroot=/usr/x86_64-w64-mingw32 -L/usr/lib/gcc/x86_64-w64-mingw32/12-win32 "$@" -Wno-unused-command-line-argument
-
Create
CMakeLists.txt
:project(bug NONE) enable_language(C) message(WARNING "prefix = ${CMAKE_STATIC_LIBRARY_PREFIX}") enable_language(OBJC) message(WARNING "prefix = ${CMAKE_STATIC_LIBRARY_PREFIX}") message(FATAL_ERROR "bye")
-
Create a build directory and run:
cmake .. --fresh -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -G Ninja
Note that it prints "prefix = lib" followed by "prefix =", indicating that CMAKE_STATIC_LIBRARY_PREFIX
equals lib
after enable_language(C)
but is blank after enable_language(OBJC)
. MinGW uses Unix library naming conventions, so the first one is correct.
If you run CMake with --trace
, and perhaps add variable_watch(CMAKE_STATIC_LIBRARY_PREFIX)
to CMakeLists.txt, you can see why this happens. For both C and OBJC, the process of detecting the compiler eventually includes CMakeSystemSpecificInformation.cmake
, which includes Platform/Windows.cmake
, which sets CMAKE_STATIC_LIBRARY_PREFIX
to blank. But for C, when CMakeCInformation.cmake
runs include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C OPTIONAL RESULT_VARIABLE _INCLUDED_FILE )
, it loads Platform/Windows-GNU-C.cmake
, which includes Windows-GNU.cmake
, which sets CMAKE_STATIC_LIBRARY_PREFIX
back to lib
. (Or for Clang, it loads Platform/Windows-Clang-C.cmake
, which includes Windows-Clang.cmake
, which includes Windows-GNU.cmake
.)
The flow for OBJC is very similar, except that Platform/Windows-GNU-OBJC.cmake
(and Platform/Windows-Clang-OBJC.cmake
) do not exist, so the blank setting from Platform/Windows.cmake
persists.
CMake behaves correctly if you set CMAKE_SYSTEM_NAME
to Windows-GNU
instead of just Windows
. Edit: But this breaks in other simple cases, and doesn't seem to be intended usage; see my comment.
CMake also behaves correctly if the specified compiler is named clang
or clang.exe
and you are on a case-insensitive filesystem, because then when CMakeOBJCInformation.cmake
does include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE )
, it loads Windows-Clang.cmake
. Yipes, so many different paths.