[This post was written by Dave Bartolomeo and the Clang/C2 feature crew]
One of the challenges with developing and maintaining cross-platform C++ code is dealing with different C++ compilers for different platforms. You write some code that builds fine with the Visual C++ compiler for your Windows-targeting build, but then your Android-targeting build breaks because Clang is stricter about standards conformance and your code was accidentally depending on Visual C++ being more permissive. Or, you write new code that builds successfully with Clang for iOS, only to find out that you used a relatively new C++ language feature that Visual C++ does not yet support, and now you have to either re-implement the code without using that language feature, or maintain a separate implementation that works with Visual C++ for your Windows build.
To make it easier to develop cross-platform code that works well for both Windows and other platforms, we’ve released an additional compiler toolset for Visual Studio called Clang with Microsoft CodeGen. This compiler uses the open-source Clang parser for C and C++, along with the code generator and optimizer from the Visual C++ compiler. This lets you compile your cross-platform code for Windows using the same Clang parser that you use for other targets, while still taking advantage of the advanced optimizations from the Visual C++ optimizer when you build for Windows. Because the new toolset uses the same Clang parser used for non-Windows targets, you won’t need to have annoying #ifdefs throughout the code just to account for differences between the compilers. Also, your code can take advantage of language features that are not currently available in the Visual C++ compiler, including C99 complex types and C++14 extended constexpr support. And because the Clang-based compiler generates the same debug information format as the Visual C++ compiler, you’ll still be able to debug your code with the same great Visual Studio debugger experience.
Code compiled with the new toolset can be linked with other code compiled with the Visual C++ 2015 C and C++ compilers. Typically, you would compile the cross-platform parts of your code with Clang with Microsoft CodeGen, and compile any Windows-specific code (e.g. your UI) with the regular Visual C++ toolset.
Note that Clang with Microsoft CodeGen is currently a preview feature. There are areas we know are incomplete or have bugs. We wanted to get this feature into your hands to give you a chance to try it out, understand how it will work in your code, and give us feedback.
In the feature selection UI of Visual Studio setup starting with Visual Studio 2015 Update 1, you’ll see a check box for Clang with Microsoft CodeGen under “Cross-Platform and Mobile Development\Visual C++ Mobile Development”. Checking this box will install the new toolset and the corresponding project templates.
Using the New Toolset
To create a new static library or DLL project that uses Clang with Microsoft CodeGen, you can use one of the new project templates under “Visual C++\Cross Platform”.
Migrating Existing Projects
To use the new toolset in an existing project, go to your project properties and change the “Platform Toolset” dropdown from “Visual Studio 2015″ to “Clang 3.7 with Microsoft CodeGen”. Make sure to hit “Apply” before you switch to editing other properties to let the project system load the corresponding toolset definition.
In this preview release we do not provide any support for automatic migration of values of the relevant properties between “Visual Studio 2015″ and “Clang 3.7 with Microsoft CodeGen” toolsets, so you will have to fix any invalid values manually. The project system will emit errors when property value in the old toolset is not valid in the new toolset. You might encounter these errors only on values that were overridden from toolset’s defaults (they are marked with bold font in project properties); the values that were not changed would automatically be switched to defaults in the new toolset. In most cases, changing the invalid value to “inherit from parent or project defaults” would fix the problem. There are a few cases you might need to fix in other ways:
- Some of the defaults are not what you might expect in this release. We’ll be changing defaults in future releases.
- When changing from MSVC toolset, exception handling is currently off-by-default even though exception handling works. The developer can override this switch manually. The default will change in the next release.
- Precompiled headers are not currently supported so you must disable their usage. Failure to do so would usually manifest itself in an “error : cannot specify -o when generating multiple output files”. If you still see this error even with precompiled headers disabled, please make sure that the value of “Object File Name” property is reset to its default value “$(IntDir)%(filename).obj” in Clang toolset.
- If source files in the project you are trying to convert are UTF-16 encoded, you will need to resave them as UTF-8 when Clang gives you an error about UTF-16 encoded source with BOM.
- If you get an “error : use of undeclared identifier ‘O_WRONLY’”, define in your project settings macro __STDC__=0.
- If you get an error “TRK0005: Failed to locate: “clang.exe”. The system cannot find the file specified”, you might be using AMD64-hosted compiler. We currently don’t support AMD64-hosted compiler support for Clang/C2 toolset. See here how to make your project x86 hosted.
- If you plan on using “VS 2015 x86 Native Tools Command Prompt”, please note that in the current release clang.exe is not immediately available via PATH environment variable. You’ll need to modify your environment to use clang.exe directly.
Identifying your Platform and Toolset
Compiler toolsets generally define a set of macros that help your code adapt to different versions of the compiler toolset and target. Here’s a table showing some relevant macros that are defined in Clang with Microsoft CodeGen and a code sample you can include in your code to help determine your platform and toolset combination.
|-fno-ms-compatibility||no ms||no ms|
|__clang_version__||“3.7.0 (…)”||“3.7.0 (…)”||“3.8.0 (…)”||“3.8.0 (…)”|
// Include (and extend) this code in your project to determine platform and toolset combination
#if defined(_WIN32) && !defined(_WIN64) puts(“I am targeting 32-bit Windows.”); #endif
#ifdef _WIN64 puts(“I am targeting 64-bit Windows.”); #endif
#ifdef __clang__ printf(“I am Clang, version: %s\n”, __clang_version__); #endif
#if defined(__clang__) && defined(__c2__) puts(“I am Clang/C2.”); #endif
#if defined(__clang__) && defined(__llvm__) puts(“I am Clang/LLVM.”); #endif
// Not tested: __EDG__, __GNUC__, etc.
#if defined(_MSC_VER) && !defined(__clang__) printf(“I am C1XX/C2, version: %02d.%02d.%05d.%02d\n”, _MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 100000, _MSC_BUILD); #endif
Known Issues in the First Preview
Because this is a preview release we released even though we’re aware of a few issues. We want to get bits into our developer’s hands as quickly as possible so that you can evaluate the toolset and see how it works with your code. Unfortunately, that means shipping with a few known bugs.
- No support for ARM. It will be there in the next update via the existing Universal App project template
- PCH build is not supported. Turn off PCH usage for any project where you explicitly set this new Platform Toolset
- No OpenMP support. You will get a diagnostic that says “OpenMP is not supported”
- No inline asm on any architecture. You will get a diagnostic that says “Inline assembly is not supported” or “GNU-style inline assembly is disabled”
- No LTCG for compilation units compiled by Clang. Such compilation units can still link with other compilation units that were compiled for LTCG by MSVC.
- No PGO instrumentation or optimization for compilation units compiled by Clang
- /bigobj is not currently supported. The number of sections in the object file is limited to 2^16.
- std::atomic_flag is not supported due to silent bad code gen. This will be fixed in the next update.
- No hashing of source files. File hashes are used by the debugger to ensure that the source file is the same version as the one used during compilation.
- Debug type information will always be placed in the .obj file (equivalent to cl.exe /Z7, not /Zi). No functionality is lost, but generated .obj files will likely be larger.
- In some cases IntelliSense may not emulate Clang behavior
- Clang diagnostics are currently only available in English
Contributing Back to Clang and LLVM
Clang with Microsoft CodeGen isn’t just a private fork of the open-source Clang compiler. We’ll be contributing the vast majority of the Clang and LLVM changes we’ve made back to the official Clang and LLVM sources. The biggest of these changes is support for emitting debug information compatible with the Visual Studio debugger. This will eventually allow code compiled with the LLVM code generator to be debugged with Visual Studio as well.
As Clang releases new versions, we’ll update our installer to include the new version.