AutoTools:使用 LLVM/Clang Windows 编译器¶
Windows 中的 Clang 编译器可以来自 2 种不同的安装或发行版
使用 MSVC 运行时(runtime)的 LLVM/Clang 编译器
使用 Msys2 运行时(runtime)(libstdc++6.dll)的 Msys2 Clang 编译器
本示例将介绍使用 MSVC 运行时的 LLVM/Clang。此 Clang 发行版又可以两种不同的方式使用
通过类 GNU 前端(frontend)
clang
使用下载的 LLVM/Clang 编译器(它仍然使用 MSVC 运行时)通过类 MSVC 前端(frontend)
clang-cl
使用下载的 LLVM/Clang 编译器(它仍然使用 MSVC 运行时)
我们从一个简单的 autotools_exe
模板开始
$ conan new autotools_exe -d name=mypkg -d version=0.1
这将创建一个简单的基于 Autotools 的项目和 Conan 包配方,它使用 AutotoolsToolchain
。
Autotools:LLVM/Clang 配合 clang
类 GNU 前端¶
我们将使用以下配置文件来构建此配置
[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.compilation:verbosity=verbose
tools.build:compiler_executables = {"c": "clang", "cpp": "clang++"}
tools.microsoft.bash:subsystem=msys2
tools.microsoft.bash:path=C:\ws\msys64\usr\bin\bash.exe
配置文件的快速说明
compiler.runtime
定义是区分 Msys2-Clang 和使用 MSVC 运行时的 LLVM/Clang 的重要区别。LLVM/Clang 定义了这个compiler.runtime
,而 Msys2-Clang 则没有。MSVC 运行时可以是动态的或静态的。定义此运行时的运行时版本(工具集版本
v144
)也很重要,因为可以使用不同的版本。[buildenv]
允许指向 LLVM/Clang 编译器,以防它尚未在路径中。注意PATH=+(path)
语法,用于prepend(前置)该路径,使其具有更高的优先级在定义
tools.microsoft.bash:path
时,使用了msys2
bash.exe
的完整路径。否则,它可能会在 Windows 系统中找到另一个无效的bash.exe
。
我们来构建它
$ conan build . -pr=llvm_clang
...
conanfile.py (mypkg/0.1): Calling build()
conanfile.py (mypkg/0.1): RUN: autoreconf --force --install
conanfile.py (mypkg/0.1): RUN: "/c/projectpath/clang/configure" --prefix=/ --bindir=${prefix}/bin --sbindir=${prefix}/bin --libdir=${prefix}/lib --includedir=${prefix}/include --oldincludedir=${prefix}/include
conanfile.py (mypkg/0.1): RUN: make -j8
...
clang++ -DPACKAGE_NAME=\"mypkg\" -DPACKAGE_TARNAME=\"mypkg\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"mypkg\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"mypkg\" -DVERSION=\"0.1\" -I. -I/c/projectpath/clang/src -DNDEBUG -std=c++14 -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -O3 -c -o main.o /c/projectpath/clang/src/main.cpp
source='/c/projectpath/clang/src/mypkg.cpp' object='mypkg.o' libtool=no \
DEPDIR=.deps depmode=none /bin/sh /c/projectpath/clang/depcomp \
clang++ -DPACKAGE_NAME=\"mypkg\" -DPACKAGE_TARNAME=\"mypkg\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"mypkg\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"mypkg\" -DVERSION=\"0.1\" -I. -I/c/projectpath/clang/src -DNDEBUG -std=c++14 -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -O3 -c -o mypkg.o /c/projectpath/clang/src/mypkg.cpp
clang++ -std=c++14 -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -O3 -fuse-ld=lld-link -o mypkg.exe main.o mypkg.o
注意 clang++
编译器是如何被使用的,运行时是通过 -D_DLL -D_MT -Xclang --dependent-lib=msvcrt
选择的。
我们可以运行我们的可执行文件,并查看 Clang 编译器版本和 MSVC 运行时如何与定义的匹配
$ build-release\src\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
Autotools:LLVM/Clang 配合 clang-cl
类 MSVC 前端¶
我们将使用以下配置文件来构建此配置
[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.compilation:verbosity=verbose
tools.microsoft.bash:subsystem=msys2
tools.build:compiler_executables = {"c": "clang-cl", "cpp": "clang-cl"}
tools.microsoft.bash:path=C:\ws\msys64\usr\bin\bash.exe
配置文件与上面的几乎相同,主要区别在于 tools.build:compiler_executables
的定义,它定义了 clang-cl
编译器。
注意
使用 clang-cl
编译器的 tools.build:compiler_executables
定义是 Conan 用于区分前端(frontend)的方式,在其他构建系统(build systems)中也一样。这个前端不是一个 setting
,因为编译器仍然是同一个,生成的二进制文件应该是二进制兼容的。
我们来构建它
$ conan build . -pr=llvm_clang_cl
...
clang-cl -DPACKAGE_NAME=\"mypkg\" -DPACKAGE_TARNAME=\"mypkg\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"mypkg\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"mypkg\" -DVERSION=\"0.1\" -I. -I/c/projectpath/clang/src -DNDEBUG -std:c++14 -MD -O2 -c -o main.obj `cygpath -w '/c/projectpath/clang/src/main.cpp'`
source='/c/projectpath/clang/src/mypkg.cpp' object='mypkg.obj' libtool=no \
DEPDIR=.deps depmode=msvc7msys /bin/sh /c/projectpath/clang/depcomp \
clang-cl -DPACKAGE_NAME=\"mypkg\" -DPACKAGE_TARNAME=\"mypkg\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"mypkg\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"mypkg\" -DVERSION=\"0.1\" -I. -I/c/projectpath/clang/src -DNDEBUG -std:c++14 -MD -O2 -c -o mypkg.obj `cygpath -w '/c/projectpath/clang/src/mypkg.cpp'`
clang-cl -std:c++14 -MD -O2 -o mypkg.exe main.obj mypkg.obj
...
可以看到所需的 clang-cl
是如何被使用的,以及 MSVC-like
命令行语法(例如 -std:c++14
)是如何被使用的。这种类 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
正如预期的那样,输出与前面的完全相同,因为除了编译器前端之外,没有任何变化。
注意
可能可以使用 Visual Studio 组件作为 Autotools 类项目的 clang-cl
分发版进行构建。但是,有必要通过 [buildenv]
和/或 tools.build:compiler_executables
来提供 Visual Studio 安装文件夹内该 Clang 组件的完整路径,以便找到它,因为这基本上是一个 LLVM/Clang 编译器,由 Visual Studio 安装程序打包和分发。