游戏人生

不积跬步,无以至千里;不积小流,无以成江海。

My Links

Blog Stats

引擎设计跟踪: 为什么Blade可以用Clang编译

最近在使用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

http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros

其中第一个链接, 有人提出该问题, 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.

posted on 2015-10-23 18:31 crazii 阅读(...) 评论(...) 编辑 收藏