最近在使用VS2015 Community, 在添加了shared items project, 并把源代码加入shared items, 添加Android工程编译的时候, 发现可以用Clang正常编译(VS2015默认使用自带的Clang编译器来编译安卓).
一开始并没有多想, 后来在准备添加Clang支持的时候, 突然意识到, Blade并没有做Clang编译器的支持, 但是可以正常编译!
最后发现, Clang也定义了__GNUC__, 编译的时候就当做GCC编译了.
相关搜索如下:
http://rem.eifzilla.de/archives/2012/08/10/identify-theft-by-clang
其中第一个链接, 有人提出该问题, Clang的贡献者出来说这是个已知问题, 但问题是__GNUC__只是表示编译器支持GNU扩展, 而不是说编译器一定是GCC, 比如ICC(Intel)也可以定义这个宏定义.
原因在于GCC只提供了extension检查而没其他定义可以区分编译器.
为了防止Clang编译器需要特殊处理, 所以还是需要加上Clang支持, 所以Blade的代码现在如下:
1 #if defined(_MSC_VER) 2 # define BLADE_COMPILER BLADE_COMPILER_MSVC 3 #elif defined(__clang__) 4 //note: Clang also defines (__GNUC__), so we need detect Clang first, or it will be mistaken as GCC 5 # define BLADE_COMPILER BLADE_COMPILER_CLANG 6 # define BLADE_COMPILER_GNU_EXTENSION 1 7 #elif defined(__GNUC__) 8 # define BLADE_COMPILER BLADE_COMPILER_GNUC 9 # define BLADE_COMPILER_GNU_EXTENSION 1 10 #else 11 # error Compiler not supported yet. 12 # define BLADE_ALWAYS_INLINE inline 13 #endif 14 15 #if BLADE_COMPILER == BLADE_COMPILER_MSVC 16 # define BLADE_ALIGNED(n) __declspec(align(n)) 17 # define BLADE_CDECL __cdecl 18 # define BLADE_STDCALL __stdcall 19 # define BLADE_FASTCALL __fastcall 20 # define BLADE_FUNCTION __FUNCTION__ 21 # define BLADE_ALWAYS_INLINE __forceinline 22 #elif BLADE_COMPILER_GNU_EXTENSION 23 # define BLADE_ALIGNED(n) __attribute__((aligned(n))) 24 # define BLADE_CDECL __attribute__((cdecl)) 25 # define BLADE_STDCALL __attribute__((stdcall)) 26 # define BLADE_FASTCALL __attribute__((fastcall)) 27 # define BLADE_FUNCTION __PRETTY_FUNCTION__ 28 # define BLADE_ALWAYS_INLINE __attribute__((always_inline)) 29 #else 30 # error Compiler not supported yet. 31 #endif
对于支持GNU扩展的编译器, 必须要在检测GNU之前检测, 否则会被误认为GCC编译器.
也就是添加了CLANG编译器, 但是对于支持GNU Extension的编译器, 单独有统一的处理. 通常情况下, 只需要使用BLADE_COMPILER_GNU_EXTENSION就可以使用GCC和CLANG和其他支持GNU Extension的编译器,
除非真的要用到Clang的特性或者需要针对Clang进行特殊fix, 才会使用BLADE_COMPILER_CLANG.