About Talks Articles

Clang on Windows

3 min read

Thanks to the MSYS2 project, now there is an easy way to utilize Clang to build C/C++ application on Windows. This works equally well for both 32-bit and 64-bit programs.

MSYS2 is a fantastic (and better) reimagination of Cygwin, it is like taking the best part of a typical modern Unix environment (a familiar shell, a general collection of utilities, a porting layer, a package manager, and so on) while still working on Windows. Bootstrapping into MSYS2 is easy, either install it directly (using the GUI installer) or use Chocolatey: choco install msys2. Once inside its shell, pacman is the go-to, ever-so-powerful package manager, with thousands of packages available at your disposal.

This of course, includes the toolchain. Not only the latest GCC is there, but we also have Clang! To illustrate the concept, let us go back to the simple ANSI C/C90 program covered in the previous blog post. Once we clone the repository, open MSYS2 32-bit shell and try the following:

pacman -S msys/make mingw32/mingw-w64-i686-clang

It is a simple step to install both Make and Clang. Wait a bit and after that, do the usual magic:

CC=clang make

A caveat here, Clang for Windows does not append the .exe suffix for the executable. Thus, a quick rename to the rescue:

ren hello hello.exe

And now you can run, inspect, analyze the executable as usual.

Pipelines Clang on Windows

To incorporate it into the continuous integration using Azure Pipelines (again, see the previous blog post), we shall construct a new job. The basic step is as follows.

- job: 'i686_windows_clang'
    vmImage: 'vs2017-win2016'
    PACMAN_PACKAGES: C:\tools\msys64\var\cache\pacman\pkg
    CC: clang

First, programmatically install MSYS2:

  - script: choco install --no-progress msys2
    displayName: 'Install MSYS2'

After that, perform some pacman maintenances:

  - script: |
      pacman -Sy
      pacman --noconfirm -S pacman-mirrors
    workingDirectory:  C:\tools\msys64\usr\bin\
    displayName: 'Check pacman'

And then, we install the required packages. At the time of this writing, Clang version 9.0 (the latest) will be installed.

  - script:  pacman --noconfirm -S msys/make mingw64/mingw-w64-x86_64-clang
    workingDirectory: C:\tools\msys64\usr\bin\
    displayName: 'Install requirements'

For the x86 architecture (aka, 32-bit Intel/AMD), install a different package:

  - script:  pacman --noconfirm -S msys/make mingw32/mingw-w64-i686-clang
    workingDirectory: C:\tools\msys64\usr\bin\
    displayName: 'Install requirements'

And now, down to the actual build step:

  - script: |
      set PATH=C:\tools\msys64\usr\bin;C:\tools\msys64\mingw64\bin;%PATH%
      ren hello hello.exe
    displayName: 'make'

As a minor tweak, we can also cache pacman downloaded packages. In the above example, it hardly matters since we only install Make and Clang. But if you have a larger application, e.g. requiring Python, Qt, and so on, it is wide to avoid the CI run redownloading the same packages again and again (saving bandwith, and also being nice to those mirrors). We can achieve this by using the Cache task from Azure Pipelines. Simply insert this after MSYS2 installation step.

  - task: Cache@2
      key: pacman
      restoreKeys: pacman
      path: $(PACMAN_PACKAGES)
    displayName: 'Cache pacman packages'

For the complete illustration of such a job, take a look at the actual azure-pipelines.yml for the hello-c90 project.

Clang everywhere, yay!

Related posts:

♡ this article? Explore more articles and follow me Twitter.

Share this on Twitter Facebook