use clang in Visual Studio

with cmake

C++ User Group Aachen
12.01.2017
Sven Johannsen

The Problem:

Beautiful test framework from Krzysztof Jusiak:


  "match success"_test = [] {
    int v[] = {1, 2, 3, 4, 3, 3, 7, 2, 3};
    expect(ranges::equal({2, 5, 8}, match(v, 2, 3)));
  };
						

but don't compile with MS C++

MS C++ don't like GCC extentsions :-(


template <char...>
struct test {
  template <class Test>
  bool operator=(const Test& test) {
    test();
    return true;
  }
};

#if defined(__clang__)
#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
#endif

template <class T, T... Chars>
constexpr auto operator""_test() {
  return test<Chars...>{};
}
						

but clang does :-)

and Visual Studio support clang

let's try to compile the code in the Visual Studio with the help of clang!

Demo

cmake generators (old)

cmake supports different generators (-G)

  • Makefiles (e.g. NMake Makefiles, MSYS Makefiles, MinGW Makefiles, Unix Makefiles)
  • Visual Studio projects
  • Ninja
  • ...

cmake .. -G "Visual Studio 14 2015 Win64"

cmake with toolsets

new in cmake 3.6: toolsets for Visual Studio (-T toolset)

cmake .. -G"Visual Studio 14 2015" -Tv140_clang_c2

works only for the clang (v140_clang_c2) and the default toolset

Summery

It's hard to compile simple C++ projects (main()) with clang in Visual Studio

  • "New project" wizard for clang supports only dlls and libs
  • Changing the toolset of an exiting project don't merge all settings
  • cmake -Tv140_clang_c2 generates working clang projects, but
    • the toolset option in cmake is still experimental (see bug report)
    • cmake don't support the XP toolset

Links

CMakeLists.txt


cmake_minimum_required(VERSION 2.8)

project(test_clang)

if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
  set(CMAKE_CXX_FLAGS "-std=c++1z")
  set(CMAKE_CXX_FLAGS "-fms-extensions")
  set(CMAKE_CXX_FLAGS "-g2 -gdwarf-2")
endif()

add_executable(test_clang main.cpp)
					

build.cmd


@echo on

mkdir build
cd build

cmake .. -G "Visual Studio 14 2015 Win64" -T v140_clang_c2
					

main.cpp


// idea from https://github.com/modern-cpp-examples/match3
#undef NDEBUG

#include <cstdio>
#include <cstdlib>

#define expect(...) \
  (void)((__VA_ARGS__) || (expect_fail__(#__VA_ARGS__, __FILE__, __LINE__), 0))
#define static_expect(...) static_assert((__VA_ARGS__), "fail")

void expect_fail__(const char* msg, const char* file, int line)
{
  std::printf("%s:%d: %s\n", file, line, msg);
  std::exit(-1);
}

//*
template <char...>
struct test
{
  template <class Test>
  bool operator=(const Test& test)
  {
    test();
    return true;
  }
};

#if defined(__clang__)
#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
#endif

template <class T, T... Chars>
constexpr auto operator""_test()
{
  return test<Chars...>{};
}

/*/
struct test
{
template <class Test>
auto operator=(const Test& test) { test(); return true; }
};

constexpr test operator "" _test(char const* t, std::size_t s)
{
return test{};
}
// */

int main()
{
  "test_should_succes"_test = [] {
    expect(2 == 2);
  };

  "test_should_fail"_test = [] {
    expect(1 == 2);
  };
}