Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use lld with CMake on Windows?

I'm trying to compile SDL2 (https://www.libsdl.org/download-2.0.php) using CMake with clang + lld (http://releases.llvm.org/) + mingw (https://sourceforge.net/projects/mingw-w64/) headers on Windows 10. Despite my many efforts, I seem unable to get CMake to use the lld linker over the mingw ld linker.

I currently build sdl2 with a batch file:

@ECHO OFF

IF NOT EXIST build MKDIR build
PUSHD build

cmake.exe -DCMAKE_BUILD_TYPE=Debug -G "MinGW Makefiles"^
  -DCMAKE_C_FLAGS="-target x86_64-windows-gnu"^
  -DCMAKE_C_COMPILER_ID="Clang" -DCMAKE_C_COMPILER="clang.exe"^
  -DCMAKE_CXX_FLAGS="-target x86_64-windows-gnu"^
  -DCMAKE_CXX_COMPILER_ID="Clang++" -DCMAKE_CXX_COMPILER="clang++.exe"^
  -DDIRECTX=OFF -DSDL_TEST=OFF -DSDL_SHARED=OFF -DSDL_STATIC=ON ..

cmake.exe --build . -- -j %NUMBER_OF_PROCESSORS%

POPD

I have tried to no avail:

  • setting -fuse-ld=lld.exe

  • setting LDFLAGS=lld.exe

  • setting -DCMAKE_LINKER=lld.exe

  • the solution from: CMake: use a custom linker

Any help would be greatly appreciated.

like image 699
Edward Chamberlain Avatar asked Oct 05 '19 23:10

Edward Chamberlain


Video Answer


1 Answers

To replicate your environment, I followed these steps:

  • I installed LLVM+Clang 12 to C:\Program Files\LLVM from the GitHub releases page: https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/LLVM-12.0.0-win64.exe
  • I downloaded mingw-w64 via MSYS2. I have it installed to C:\msys64. See: https://www.msys2.org/
  • I then downloaded SDL2 2.0.14 from https://www.libsdl.org/release/SDL2-2.0.14.zip and unzipped it to D:\SDL2-2.0.14

I have CMake 3.20 and Ninja 1.10.2 installed system-wide and in the PATH.


Then, I created D:\clang-mingw.cmake with the following contents:

set(CMAKE_C_COMPILER "C:/Program Files/LLVM/bin/clang.exe")
set(CMAKE_CXX_COMPILER "C:/Program Files/LLVM/bin/clang++.exe")

set(CMAKE_C_COMPILER_TARGET x86_64-windows-gnu)
set(CMAKE_CXX_COMPILER_TARGET x86_64-windows-gnu)

set(CMAKE_SYSROOT "C:/msys64/mingw64")

set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")

This is called a toolchain file. These are used to inform CMake about non-standard compiler and library setups like this one.

Setting the CMAKE_<LANG>_COMPILER variables (naturally) points CMake to the compilers you want to use. In this case, that's Clang.

Setting CMAKE_<LANG>_COMPILER_TARGET configures Clang to use the x86_64-windows-gnu target when compiling. This is important for CMake's compiler detection and sanity checking steps.

Setting CMAKE_SYSROOT informs Clang where to find all of the standard libraries and headers (ie. those from mingw-w64).

Finally, we ensure LLD is used by adding -fuse-ld=lld to the linker flags used when linking executables, loadable modules, and shared libraries (but not static libraries, since no linker is needed, just the archiver). The CMAKE_{EXE,MODULE,SHARED}_LINKER_FLAGS_INIT variables are meant to be set from the toolchain for this purpose.

Then from a normal command prompt (i.e. not a Visual Studio command prompt or MSYS2 bash), I ran:

D:\SDL2-2.0.14>cmake -G Ninja -S . -B build -DCMAKE_TOOLCHAIN_FILE=D:/clang-mingw.cmake -DCMAKE_BUILD_TYPE=Debug -DDIRECTX=OFF -DSDL_TEST=OFF -DSDL_SHARED=OFF -DSDL_STATIC=ON
-- The C compiler identification is Clang 12.0.0
-- The CXX compiler identification is Clang 12.0.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/LLVM/bin/clang.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/LLVM/bin/clang++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
-- Performing Test HAVE_GCC_WALL
-- Performing Test HAVE_GCC_WALL - Success

[... output clipped ...]

The configure command I used does little more than replicate the SDL-specific settings you used in your question. It just selects Ninja as the build system generator (you could of course replace this with a different one if you so desired) and sets the toolchain file to the one above.

It then builds without errors.

D:\SDL2-2.0.14>cmake --build build

[... output clipped ...]

[163/164] C:\PROGRA~1\LLVM\bin\clang.exe --target=x86_64-windows-gnu --sysroot=C:/msys64/mingw64 -DUSING_GENERATED_CONFIG_H -Iinclude -I../include -idirafter "D:/SDL2-2.0.14/src/video/khronos"  "-ID:/SDL2-2.0.14/src/hidapi/hidapi" -msse3 -msse2 -msse -m3dnow -mmmx -Wshadow -fvisibility=hidden -Wdeclaration-after-statement -Werror=declaration-after-statement -fno-strict-aliasing -Wall  -g -MD -MT CMakeFiles/SDL2-static.dir/src/video/yuv2rgb/yuv_rgb.c.obj -MF CMakeFiles\SDL2-static.dir\src\video\yuv2rgb\yuv_rgb.c.obj.d -o CMakeFiles/SDL2-static.dir/src/video/yuv2rgb/yuv_rgb.c.obj -c ../src/video/yuv2rgb/yuv_rgb.c
[164/164] cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E rm -f libSDL2d.a && C:\PROGRA~1\LLVM\bin\llvm-ar.exe qc libSDL2d.a  @CMakeFiles\SDL2-static.rsp && cd ."
like image 50
Alex Reinking Avatar answered Oct 26 '22 12:10

Alex Reinking