如果我们要写跨平台的c/c++代码,很多时候需要处理由于不同编译器对c/c++各个标准支持力度不同导致的兼容性问题,一般通常的解决办法是:自己在代码中通过宏去判断各个编译器的版本、内置宏、标准库宏、__has_feature等来检测处理。

自己如果在代码中按上述的方式检测,会很繁琐,尤其是像c++这种存在大量语法特性,如果一一检测过来,工作量是非常大的。

通过构建工具预先检测编译特性

另外比较省事的方式,就是依赖构建工具提前做好检测,然后把检测结果作为宏添加到编译中去,这样代码只需要判断对应的特性宏是否存在,就可以进行处理了。

在cmake中就有类似的检测机制,非常强大,因此xmake也对其进行了支持,提供更加灵活强大的编译器特性预先检测支持:

target("test")
on_load(function (target)
import("core.tool.compiler")
if compiler.has_features("cxx_constexpr") then
target:add("defines", "HAS_CXX_CONSTEXPR=1")
end
end)

通过core.tool.compiler模块的compiler.has_features接口,在xmake.lua中预先判断当前编译期支持的语言特性,实现条件编译。

此处也是参考了cmake的设计,具体详情见:issues#83

上述代码,在加载target的时候,判断当前编译器是否支持c++的常量表达式语法特性,如果支持则添加宏定义:HAS_CXX_CONSTEXPR=1

我们也可以在判断时候,追加一些参数控制编译选项,例如上述特性需要c++11支持,我们可以启用它:

if compiler.has_features({"c_static_assert", "cxx_constexpr"}, {languages = "cxx11"}) then
-- ok
end

通过上面的代码可以看到,此接口是可以同时检测多个特性的,返回值为实际支持的特性列表。

如果之前对这个target已经设置了c++11,那么我们也可以传入target对象,继承target的所有设置,甚至指定一些其他扩展编译配置:

if compiler.has_features("cxx_constexpr", {target = target, defines = "..", includedirs = ".."}) then
-- ok
end

批量编译器特性检测

c++的语言特性非常多,这个时候我们可以通过脚本实现快速的批量检测:

target("test")

    on_load(function (target)
import("core.tool.compiler")
for feature, _ in pairs(compiler.features("cxx", {target = target})) do -- 传入target在检测特性时继承target的所有编译配置
target:add("defines", "has_feature_" .. feature)
end
end)

上述代码,会在加载target的时候,把当前编译器对c++的所有支持特性,都添加到target的宏定义中进行编译,例如:-Dhas_feature_cxx_constexpr
我们只需要在代码中,通过判断对应的特性宏是否存在就行了:

#ifdef has_feature_cxx_constexpr
// TODO
#endif

目前支持的所有c/c++编译器特性列表,见:compiler.features

更加底层的检测接口

如果我们要指定获取具体哪个编译器的特性支持,则需要更加底层的接口支持了,例如:

import("lib.detect.has_features")

local features = has_features("clang", "cxx_constexpr")
local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = {"-g", "-O0"}, program =www.rcsx.org "xcrun -sdk macosx clang"})
local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = "-g"})

lib.detect.has_features属于探测模块的接口,可以指定需要检测的工具名,例如这里通过传入clang,只对clang编译器进行检测。

当然此接口,还可以检测其他非编译器的工具特性,更加的通用。

通过自定义c/c++代码片段来检测特性

对于一些复杂的编译器特性,连compiler.has_features都无法检测到的时候,可以通过自定义代码片段尝试编译来检测它。

import("lib.detect.check_cxsnippets")

local ok = check_cxsnippets("constexpr int f(int x) { return x ? x+f(x-1) : 0; } constexpr int x = f(5); static_assert(x == 15);", {sourcekind = "cxx", languages = "cxx11"})

上述代码通过自定义一个constexpr的测试代码,去检测c++11的constexpr支持。

此接口是detect.has_cfuncsdetect.has_cincludesdetect.has_ctypes等接口的通用版本,也更加底层。

因此我们可以用它来检测:types, functions, includes 还有 links,或者是组合起来一起检测。

第一个参数为代码片段列表,一般用于一些自定义特性的检测,如果为空,则可以仅仅检测可选参数中条件,例如:

 
local ok = check_cxsnippets({"void test() {}", "void test2() {}"}, {types = {"wchar_t", "char*"},www.rcsx.org includes ="stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}})

上面那个调用,会去同时检测types, includes和funcs是否都满足,如果通过返回true。

使用xmake检测编译器特性支持的更多相关文章

  1. objective-c 语法快速过(7)编译器特性ARC

    ARC(是编译器特性) ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内 ...

  2. 链接脚本在编程中的高级运用之二——执行时库和C++特性支持

    我们在链接脚本在编程中的高级运用之中的一个可变长数组中已经讲述了编译链接的原理,并且以uboot命令为例具体介绍链接脚本怎样实现可变长数组. 本章在前者的基础上继续讲述链接脚本在执行时库中的高级应用技 ...

  3. C 如何判断编译器是否支持C90 C99?

    参考:<C Primer Plus>,Stephen Prata著,姜佑译. ANSI/ISO C标准 美国ANSI成立委员会X3J11,于89/90年,99年,11年,发布C标准:C89 ...

  4. 华为方舟编译器正式支持C语言:完全开源

    投递人 itwriter 发布于 2020-10-14 19:08 评论(15) 有1938人阅读 原文链接 2019 年 8 月底,华为方舟编译器(OpenArkCompiler)正式开源,迈出了跨 ...

  5. MindSpore特性支持类

    MindSpore特性支持类 Q:请问MindSpore支持梯度截断吗? A:支持,可以参考梯度截断的定义和使用. Q:如何在训练神经网络过程中对计算损失的超参数进行改变? A:暂时还未有这样的功能. ...

  6. js检测浏览器是否支持某属性

    以检测浏览器是否支持 input 标签的 required 属性为例: var isSupport = 'required' in document.createElement('input');

  7. Android 手势检测实战 打造支持缩放平移的图片预览效果(下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39480503,本文出自:[张鸿洋的博客] 上一篇已经带大家实现了自由的放大缩小图 ...

  8. WebSocket API使用篇检测浏览器是否支持WebSocket(4)

    WebSocket API是下一代客户端-服务器的异步通信方法.前面有三篇文章已经对WebSocket有了一些介绍,这里我总结了一下.我在使用WebSockets API过程中遇到的问题. 1.检测浏 ...

  9. 自动检测GD库支持的图像类型

    以下代码通过自动检测GD库支持的图像类型 来写出移直性更好的PHP代码 <?php if(function_exists("imagegif")){ header(" ...

随机推荐

  1. layout_weight属性

    layout_weight 某个控件text多行,第一行对齐,baselineAligned = "false" 可使控件对齐 weight 计算规则 剩余尺寸=父布局尺寸-子布局 ...

  2. Ionic 2 中的创建一个闪视卡片组件

    闪视卡片是记忆信息的重要工具,它的使用可以追溯到19世纪.我们将要创建一个很酷的短暂动画来实现它.看起来像是这个样子的: 闪视卡片示例 Ionic 2 实例开发 新增章节将为你介绍如何在Ionic 2 ...

  3. Electron 入门文档

    https://www.kancloud.cn/wizardforcel/electron-doc/137765 https://segmentfault.com/a/1190000006207600 ...

  4. sqlserver 查询某表的所有列名

    select name + ',' from syscolumns where id = object_id('SEND_TALLY') AND name <> 'PICDATAS'

  5. ES6, Angular,React和ABAP中的String Template(字符串模板)

    String Template(字符串模板)在很多编程语言和框架中都支持,是一个很有用的特性.本文将Jerry工作中使用到的String Template的特性做一个总结. ES6 阮一峰老师有一个专 ...

  6. ucos-ii核心算法分析(转)

    μC/OS-Ⅱ是一种免费公开源代码.结构小巧.具有可剥夺实时内核的实时操作系统.其 内核提供任务调度与管理.时间管理.任务间同步与通信.内存管理和中断服务等功能.适合小型控制系统,具有执行效率高.占用 ...

  7. 掘金 里面 写文章 带目录的时候 用#(空格)标题 后面用## title,一个页面只有一个H1

    掘金 里面 写文章 带目录的时候 用#(空格)标题 后面用## title,一个页面只有一个H1

  8. javaweb基础(16)_jsp指令

    一.JSP指令简介 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分. 在JSP 2.0规范中共定义了三个指令: pa ...

  9. ios sinaweibo 客户端(三)

    这个页面要讲述的是用户的粉丝列表,下面是效果图: 可以看到这个视图明显也是一个tableview,在每一个cell中包含的有三个部分的内容:粉丝头像image,粉丝昵称label,我和粉丝之间的相互关 ...

  10. NOIP模拟赛 czy的后宫

    [题目描述] czy要妥善安排他的后宫,他想在机房摆一群妹子,一共有n个位置排成一排,每个位置可以摆妹子也可以不摆妹子.有些类型妹子如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看了.假定每种 ...