AutoTools: Using LLVM/Clang Windows compiler¶
The Clang compiler in Windows can come from 2 different installations or distributions:
The LLVM/Clang compiler, that uses the MSVC runtime
The Msys2 Clang compiler that uses the Msys2 runtime (libstdc++6.dll)
This example explains the LLVM/Clang with the MSVC runtime. This Clang distribution can in turn be used in two different ways:
Using the LLVM/Clang downloaded compiler (it still uses the MSVC runtime), via the GNU-like frontend
clang
Using the LLVM/Clang downloaded compiler (it still uses the MSVC runtime), via the MSVC-like frontend
clang-cl
Let’s start from a simple autotools_exe
template:
$ conan new autotools_exe -d name=mypkg -d version=0.1
This creates a simple Autotools based project and Conan package recipe that uses AutotoolsToolchain
.
Autotools: LLVM/Clang with clang
GNU-like frontend¶
To build this configuration we will use the following profile:
[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
Quick explanation of the profile:
The
compiler.runtime
definition is the important differentiator to distinguish between Msys2-Clang and LLVM/Clang with the MSVC runtime. The LLVM/Clang defines thiscompiler.runtime
, while the Msys2-Clang doesn’t.The MSVC runtime can be either dynamic or static. It is important also to define the runtime version (toolset version
v144
) of this runtime, as it is possible to use different ones.The
[buildenv]
allows to point to the LLVM/Clang compiler, in case it is not already in the path. Note thePATH=+(path)
syntax, to prepend that path, so it has higher priorityWhile defining
tools.microsoft.bash:path
, the full path to themsys2
bash.exe
has been used. Otherwise, it is possible that it can find anotherbash.exe
in the Windows system that will not be valid.
Let’s build it:
$ 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
Note how the clang++
compiler is used, the runtime is selected with -D_DLL -D_MT -Xclang --dependent-lib=msvcrt
.
We can run our executable, and see how the Clang compiler version and the MSVC runtime match the defined ones:
$ 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 with clang-cl
MSVC-like frontend¶
To build this configuration we will use the following profile:
[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
The profile is almost identical to the above one, the main difference is the definition of tools.build:compiler_executables
,
defining the clang-cl
compiler.
Note
The definition of tools.build:compiler_executables
using the clang-cl
compiler is what is used by Conan to differentiate
among the frontends, also in other build systems.
This frontend is not a setting
, because the compiler is still the same, and the resulting binary should be binary compatible.
Let’s build it:
$ 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
...
See how the desired clang-cl
is used, and how the MSVC-like
command line syntax is used, like -std:c++14
.
This MSVC-like syntax uses the -MD/-MT
flags to differentiate across the dynamic/static MSVC runtimes.
We can run our executable, and see how the Clang compiler version and the MSVC runtime match the defined ones:
$ 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
As expected, the output is identical to the previous one, as nothing changed except the compiler frontend.
Note
It might be possible to build using the clang-cl
distributed as a Visual Studio component for autotools-like projects.
But it is necessary to provide the full path to that Clang component within the Visual Studio installed folder, so it can
be found, via [buildenv]
and or tools.build:compiler_executables
, because it is basically an LLVM/Clang compiler,
packaged and distributed by the Visual Studio installer.