[WIN/CLANG/CMAKE] Incorrect linker flags when configuring on the Windows.
Godot version
no matter
godot-cpp version
godot-4.5-stable
System information
Windows 11
Issue description
Incorrect linker flags are used when building the project in the Windows + Clang (GNU-like CLI) + Ninja + CMake environment
FAILED: [code=1] reproduce.dll reproduce.lib
C:\Windows\system32\cmd.exe /C "cd . && C:\PROGRA~1\LLVM\bin\CLANG_~1.EXE -nostartfiles -nostdlib -O0 -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -g -Xclang -gcodeview -shared -Wl,--no-undefined -lstdc++ -fuse-ld=lld-link -o reproduce.dll -Xlinker /MANIFEST:EMBED -Xlinker /implib:reproduce.lib -Xlinker /pdb:reproduce.pdb -Xlinker /version:0.0 CMakeFiles/reproduce.dir/empty.cpp.obj bin/libgodot-cpp.windows.template_debug.x86_64.lib -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
lld-link: warning: ignoring unknown argument '--no-undefined'
lld-link: error: could not open 'stdc++.lib': no such file or directory
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
Incorrect linker flags are added here. I assume this was written with the expectation that we are using MinGW/MSYS with a POSIX runtime, but that’s not the case here.
t would be nice to have an option to prevent targets that use godot-cpp from being polluted with its PUBLIC linker flags, and instead allow the higher-level project (the one that calls add_subdirectory(godot-cpp)) to control them.
Steps to reproduce
- Download reproduce.zip
- Configure (options below)
- Try to build
- Wait for the linking stage
Configure options: -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_C_COMPILER=C:/Program Files/LLVM/bin/clang.exe (It’s possible to use Clang installed via Chocolatey) -DCMAKE_CXX_COMPILER=C:/Program Files/LLVM/bin/clang++.exe
Minimal reproduction project
I think we need to somehow distinguish between when we’re building with Mingw/MSYS + CLANG and when we’re building with just CLANG (without Mingw/MSYS). 🤔
I think we need to somehow distinguish between when we’re building with
Mingw/MSYS + CLANGand when we’re building with justCLANG(without Mingw/MSYS). 🤔
Things can always use improvement. And it's even more complicated than you ight imagine if you want to support all combinations as the llvm set of tools can be set to take flags in either format, even distinguishing between linker and compiler, but I digress.
If you have any suggestions on what to change I'm eager to hear them.
This was a massive PITA when I tried some time ago to support all options, i'm sorry i never managed to make it work.
If you have any suggestions on what to change I'm eager to hear them.
How about adding an option to disable setting any compilation or linking flags - at least the PUBLIC ones? That way, the top-level project would have full control over them.
Something like this (instead of using conditions and checking the option, I’m commenting out what needs to be removed. This is just for clarity)
set(GODOTCPP_DISABLE_PUBLIC_FLAGS ON CACHE BOOL "Disables PUBLIC compile/link flags on the targets")
# These are compile definitions. We’ll keep them (Although this probably shouldn’t apply to _HAS_EXCEPTIONS. 😅)
target_compile_definitions(
godot-cpp
PUBLIC
GDEXTENSION
# features
$<${DEBUG_FEATURES}:DEBUG_ENABLED>
$<${IS_DEV_BUILD}:DEV_ENABLED>
$<${HOT_RELOAD}:HOT_RELOAD_ENABLED>
$<$<STREQUAL:${GODOTCPP_PRECISION},double>:REAL_T_IS_DOUBLE>
#$<${IS_MSVC}:$<${DISABLE_EXCEPTIONS}:_HAS_EXCEPTIONS=0>>
$<${THREADS_ENABLED}:THREADS_ENABLED>
)
# remove PUBLIC and keep PRIVATE
target_link_options(
godot-cpp
#PUBLIC
# $<${DEBUG_SYMBOLS}:$<${IS_MSVC}:/DEBUG:FULL>>
#
# $<$<NOT:${DEBUG_SYMBOLS}>:
# $<${IS_GNU}:-s>
# $<${IS_CLANG}:-s>
# $<${IS_APPLECLANG}:-Wl,-S -Wl,-x -Wl,-dead_strip>
# >
PRIVATE
$<${IS_MSVC}:
/WX # treat link warnings as errors.
/MANIFEST:NO # We dont need a manifest
>
)
If you have any suggestions on what to change I'm eager to hear them.
How about adding an option to disable setting any compilation or linking flags - at least the PUBLIC ones? That way, the top-level project would have full control over them.
I agree that there should be no unnecessary public flags. The ones you mentioned are the only ones I think, and should be changed. The common_flags all have guard variables, or are private.
aside from the public part, its picking up the NOT_MSVC because its clang, but its clang using the MSVC FRONTEND, and while there is a flag for that for the compiler https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.html Unfortunately the matching flag for the linker wasnt introduced until 3.29, and we're on 3.17 https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_LINKER_FRONTEND_VARIANT.html
Certainly an assumption can be made which might solve the issue for most people though.
I'm going to have to install from chocolaty or tune my environment to account for this now, I'm sure I already have a compiler which would exhibit this flavour of error.