CMakeToolchain: 使用 LLVM/Clang Windows 编译器¶
Windows 中的 Clang 编译器可以来自 2 种不同的安装或发行版
使用 MSVC 运行时的 LLVM/Clang 编译器
使用 Msys2 运行时 (libstdc++6.dll) 的 Msys2 Clang 编译器
本示例解释了使用 MSVC 运行时的 LLVM/Clang。这种 Clang 发行版反过来可以用三种不同的方式使用
使用 Visual Studio 安装程序作为 VS 一部分安装的 Clang 组件
通过类似 GNU 的前端
clang
使用下载的 LLVM/Clang 编译器(它仍然使用 MSVC 运行时)通过类似 MSVC 的前端
clang-cl
使用下载的 LLVM/Clang 编译器(它仍然使用 MSVC 运行时)
让我们从一个简单的 cmake_exe
模板开始
$ conan new cmake_exe -d name=mypkg -d version=0.1
这会创建一个简单的基于 CMake 的项目和使用 CMakeToolchain
的 Conan 包配方(recipe)。
LLVM/Clang 和类似 GNU 的前端 clang
¶
要构建此配置,我们将使用以下配置文件
[settings]
os=Windows
arch=x86_64
build_type=Release
compiler=clang
compiler.version=18
compiler.cppstd=14
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.runtime_version=v144
[buildenv]
PATH=+(path)C:/ws/LLVM/18.1/bin
[conf]
tools.cmake.cmaketoolchain:generator=Ninja
tools.compilation:verbosity=verbose
[tool_requires]
ninja/[*]
配置文件简要说明
compiler.runtime
定义是区分 Msys2-Clang 和使用 MSVC 运行时的 LLVM/Clang 的重要区别点。LLVM/Clang 定义了此compiler.runtime
,而 Msys2-Clang 没有。MSVC 运行时可以是动态的或静态的。定义此运行时的运行时版本(工具集版本
v144
)也很重要,因为可以使用不同的版本。[buildenv]
允许指向 LLVM/Clang 编译器,以防它不在路径中。注意PATH=+(path)
语法,用于预置该路径,使其具有更高的优先级,否则 CMake 可能会找到并使用安装在 Visual Studio 中的 Clang 组件。我们正在使用
Ninja
CMake 生成器,并从[tool_requires]
安装它,但如果 Ninja 已安装在您的系统中,则可能不需要这样做。
让我们构建它
$ conan build . -pr=llvm_clang
...
-- The CXX compiler identification is Clang 18.1.8 with GNU-like command-line
-- Check for working CXX compiler: C:/ws/LLVM/18.1/bin/clang++.exe - skipped
...
[1/3] C:\ws\LLVM\18.1\bin\clang++.exe -O3 -DNDEBUG -std=c++14 -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -MD -MT CMakeFiles/mypkg.dir/src/main.cpp.obj -MF CMakeFiles\mypkg.dir\src\main.cpp.obj.d -o CMakeFiles/mypkg.dir/src/main.cpp.obj -c C:/Users/Diego/conanws/kk/clang/src/main.cpp
[2/3] C:\ws\LLVM\18.1\bin\clang++.exe -O3 -DNDEBUG -std=c++14 -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -MD -MT CMakeFiles/mypkg.dir/src/mypkg.cpp.obj -MF CMakeFiles\mypkg.dir\src\mypkg.cpp.obj.d -o CMakeFiles/mypkg.dir/src/mypkg.cpp.obj -c C:/Users/Diego/conanws/kk/clang/src/mypkg.cpp
[3/3] cmd.exe /C "cd . && C:\ws\LLVM\18.1\bin\clang++.exe -fuse-ld=lld-link -nostartfiles -nostdlib -O3 -DNDEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -Xlinker /subsystem:console CMakeFiles/mypkg.dir/src/mypkg.cpp.obj CMakeFiles/mypkg.dir/src/main.cpp.obj -o mypkg.exe -Xlinker /MANIFEST:EMBED -Xlinker /implib:mypkg.lib -Xlinker /pdb:mypkg.pdb -Xlinker /version:0.0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
查看如何使用安装在 C:/ws
文件夹中的所需 LLVM/Clang 编译器,以及如何使用类似 GNU
的命令行语法。类似 GNU 的语法需要 --dependent-lib=msvcrt
(由 CMake 自动添加)编译器和链接器标志来定义链接到动态 MSVC 运行时,否则 LLVM/Clang 会将其静态链接。另请注意,-MD -MT
标志与 MSVC 运行时无关,在类似 GNU 的前端中,它们具有完全不同的含义。
我们可以运行我们的可执行文件,看看 Clang 编译器版本和 MSVC 运行时如何与定义的版本匹配
$ build\Release\mypkg.exe
mypkg/0.1: Hello World Release!
mypkg/0.1: _M_X64 defined
mypkg/0.1: __x86_64__ defined
mypkg/0.1: MSVC runtime: MultiThreadedDLL
mypkg/0.1: _MSC_VER1943
mypkg/0.1: _MSVC_LANG201402
mypkg/0.1: __cplusplus201402
mypkg/0.1: __clang_major__18
mypkg/0.1: __clang_minor__1
LLVM/Clang 和类似 MSVC 的前端 clang-cl
¶
要构建此配置,我们将使用以下配置文件
[settings]
os=Windows
arch=x86_64
build_type=Release
compiler=clang
compiler.version=18
compiler.cppstd=14
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.runtime_version=v144
[buildenv]
PATH=+(path)C:/ws/LLVM/18.1/bin
[conf]
tools.cmake.cmaketoolchain:generator=Ninja
tools.build:compiler_executables = {"c": "clang-cl", "cpp": "clang-cl"}
tools.compilation:verbosity=verbose
[tool_requires]
ninja/[*]
该配置文件与上面的几乎相同,主要区别在于定义了 tools.build:compiler_executables
,指定了 clang-cl
编译器。
注意
使用 clang-cl
编译器定义 tools.build:compiler_executables
是 Conan 用于区分不同前端的方法,在其他构建系统中也是如此。此前端不是一个 setting
,因为编译器仍然是相同的,并且生成的二进制文件应该是二进制兼容的。
让我们构建它
$ conan build . -pr=llvm_clang_cl
...
-- The CXX compiler identification is Clang 18.1.8 with MSVC-like command-line
-- Check for working CXX compiler: C:/ws/LLVM/18.1/bin/clang-cl.exe - skipped
...
[1/3] C:\ws\LLVM\18.1\bin\clang-cl.exe /nologo -TP /DWIN32 /D_WINDOWS /GR /EHsc /O2 /Ob2 /DNDEBUG -std:c++14 -MD /showIncludes /FoCMakeFiles\mypkg.dir\src\main.cpp.obj /FdCMakeFiles\mypkg.dir\ -c -- C:\project\src\main.cpp
[2/3] C:\ws\LLVM\18.1\bin\clang-cl.exe /nologo -TP /DWIN32 /D_WINDOWS /GR /EHsc /O2 /Ob2 /DNDEBUG -std:c++14 -MD /showIncludes /FoCMakeFiles\mypkg.dir\src\mypkg.cpp.obj /FdCMakeFiles\mypkg.dir\ -c -- C:\project\src\mypkg.cpp
[3/3] cmd.exe /C "cd . && C:\ws\cmake\cmake-3.27.9-windows-x86_64\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\mypkg.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests -- C:\ws\LLVM\18.1\bin\lld-link.exe /nologo CMakeFiles\mypkg.dir\src\mypkg.cpp.obj CMakeFiles\mypkg.dir\src\main.cpp.obj /out:mypkg.exe /implib:mypkg.lib /pdb:mypkg.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
查看如何使用安装在 C:/ws
文件夹中的所需 LLVM/Clang 编译器,以及如何使用类似 MSVC
的命令行语法。这种类似 MSVC 的语法使用 -MD/-MT
标志来区分动态/静态 MSVC 运行时。
我们可以运行我们的可执行文件,看看 Clang 编译器版本和 MSVC 运行时如何与定义的版本匹配
$ build\Release\mypkg.exe
mypkg/0.1: Hello World Release!
mypkg/0.1: _M_X64 defined
mypkg/0.1: __x86_64__ defined
mypkg/0.1: MSVC runtime: MultiThreadedDLL
mypkg/0.1: _MSC_VER1943
mypkg/0.1: _MSVC_LANG201402
mypkg/0.1: __cplusplus201402
mypkg/0.1: __clang_major__18
mypkg/0.1: __clang_minor__1
正如预期,输出与之前的结果相同,因为除了编译器前端之外没有任何变化。
MSVC Clang 组件 (ClangCL Visual Studio 工具集)¶
要构建此配置,我们将使用以下配置文件
[settings]
os=Windows
arch=x86_64
build_type=Release
compiler=clang
compiler.version=19
compiler.cppstd=14
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.runtime_version=v144
[conf]
tools.cmake.cmaketoolchain:generator=Visual Studio 17
tools.compilation:verbosity=verbose
此配置文件将使用 CMake 的“Visual Studio”生成器。这表明 Clang 编译器将是 Visual Studio 提供的,并通过 Visual Studio 安装程序作为 Visual Studio 的一个组件安装。注意 compiler.version=19
与上面使用的版本不同,上面是 compiler.version=18
,因为 Visual 内部的版本由其安装程序自动定义。
此设置将始终使用类似 MSVC 的 clang-cl
前端,并且 ClangCL
工具集将被激活,以便 Visual Studio 知道这是它应该使用的编译器。在此处不需要定义 tools.build:compiler_executable
。
让我们构建它
$ conan build . -pr=llvm_clang_vs
...
-- Conan toolchain: CMAKE_GENERATOR_TOOLSET=ClangCL
-- The CXX compiler identification is Clang 19.1.1 with MSVC-like command-line
...
ClCompile:
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin\clang-cl.exe /c /nologo /W1 /WX- /diagnostics:column /O2 /Ob2 /D _MBCS /D WIN
32 /D _WINDOWS /D NDEBUG /D "CMAKE_INTDIR=\"Release\"" /EHsc /MD /GS /fp:precise /GR /std:c++14 /Fo"mypkg.dir\Release\\" /Gd /TP --target=amd64-pc-windows-
msvc C:\project\src\mypkg.cpp C:\project\src\main.cpp
Link:
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin\lld-link.exe /OUT:"C:\project\build\Release\mypkg.exe" /
INCREMENTAL:NO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:
"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:"C:/Users/Diego/conanws/kk/clang/build/Release/mypkg.pdb" /SUBSYSTEM:CONSOLE /DYNAMICBASE /NXCOMP
AT /IMPLIB:"C:/Users/Diego/conanws/kk/clang/build/Release/mypkg.lib" /machine:x64 mypkg.dir\Release\mypkg.obj
mypkg.dir\Release\main.obj
mypkg.vcxproj -> C:\project\build\Release\mypkg.exe
定义了 CMAKE_GENERATOR_TOOLSET=ClangCL
,并且使用了内部的 VS Clang 组件,也显示了 19.1.1
版本。然后,使用了常规的类似 MSVC
的语法,包括通过 /MD
标志定义运行时。
我们可以运行我们的可执行文件,看看 Clang 编译器版本 (19
) 和 MSVC 运行时如何与定义的版本匹配
$ build\Release\mypkg.exe
mypkg/0.1: Hello World Release!
mypkg/0.1: _M_X64 defined
mypkg/0.1: __x86_64__ defined
mypkg/0.1: MSVC runtime: MultiThreadedDLL
mypkg/0.1: _MSC_VER1943
mypkg/0.1: _MSVC_LANG201402
mypkg/0.1: __cplusplus201402
mypkg/0.1: __clang_major__19
mypkg/0.1: __clang_minor__1