使用xmake检测编译器特性支持
如果我们要写跨平台的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_cfuncs, detect.has_cincludes和detect.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检测编译器特性支持的更多相关文章
- objective-c 语法快速过(7)编译器特性ARC
ARC(是编译器特性) ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内 ...
- 链接脚本在编程中的高级运用之二——执行时库和C++特性支持
我们在链接脚本在编程中的高级运用之中的一个可变长数组中已经讲述了编译链接的原理,并且以uboot命令为例具体介绍链接脚本怎样实现可变长数组. 本章在前者的基础上继续讲述链接脚本在执行时库中的高级应用技 ...
- C 如何判断编译器是否支持C90 C99?
参考:<C Primer Plus>,Stephen Prata著,姜佑译. ANSI/ISO C标准 美国ANSI成立委员会X3J11,于89/90年,99年,11年,发布C标准:C89 ...
- 华为方舟编译器正式支持C语言:完全开源
投递人 itwriter 发布于 2020-10-14 19:08 评论(15) 有1938人阅读 原文链接 2019 年 8 月底,华为方舟编译器(OpenArkCompiler)正式开源,迈出了跨 ...
- MindSpore特性支持类
MindSpore特性支持类 Q:请问MindSpore支持梯度截断吗? A:支持,可以参考梯度截断的定义和使用. Q:如何在训练神经网络过程中对计算损失的超参数进行改变? A:暂时还未有这样的功能. ...
- js检测浏览器是否支持某属性
以检测浏览器是否支持 input 标签的 required 属性为例: var isSupport = 'required' in document.createElement('input');
- Android 手势检测实战 打造支持缩放平移的图片预览效果(下)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39480503,本文出自:[张鸿洋的博客] 上一篇已经带大家实现了自由的放大缩小图 ...
- WebSocket API使用篇检测浏览器是否支持WebSocket(4)
WebSocket API是下一代客户端-服务器的异步通信方法.前面有三篇文章已经对WebSocket有了一些介绍,这里我总结了一下.我在使用WebSockets API过程中遇到的问题. 1.检测浏 ...
- 自动检测GD库支持的图像类型
以下代码通过自动检测GD库支持的图像类型 来写出移直性更好的PHP代码 <?php if(function_exists("imagegif")){ header(" ...
随机推荐
- 手机安全卫士——在设置中心 自定义view和自定义属性
自定义组合控件 1. 自定义一个View, 继承ViewGroup,比如RelativeLayout,此文中是SettingItemView 2. 编写组合控件的布局文件,在自定义的View中加载 ...
- github上fork原项目,如何将本地仓库代码更新到最新版本?
场景: 在github上fork原项目,项目组成员发起pull request提交了代码,这时自己在本地仓库该如何更新到最新代码? 操作方法如下: 方法一.从github上进行操作然后更新 登录自己的 ...
- 如何从桌面程序向浏览器传递cookie或自定义header
类似问题 从c#程序启动ie并传递cookie 打开默认浏览器并传递cookie 打开一个web浏览器使用c#应用程序并添加请求头 猜想 从wpf程序打开默认浏览器并定位到一个url ,并且向这个ur ...
- c++链表-双向链表+增删查改
基于双向链表的增删改查和排序(C++实现) 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前 ...
- 天坑之mysql乱码问题以及mysql重启出现1067的错误解决
相信很多小伙伴都遇到过数据库中文乱码问题,很头疼,明明Navicat上的编码格式都是utf-8是一样的啊? 为什么还是乱码? 原因是Navicat上的数据库编码格式并不是真正的编码格式 ,所以明白了吗 ...
- c#和Java中的抽象类
应用场景:当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法. 比如:描述一个图形.圆形. 矩形三个类.不管哪种图形都会具备计算面积与周长的行为,但是每种图形计算的方式 ...
- python @staticmethod和@classmethod
Python其实有3个方法,即 静态方法 (staticmethod), 类方法 (classmethod)和 实例方法. 如下: def foo(x): print "executing ...
- hash 哈希查找复杂度为什么这么低?
hash 哈希查找复杂度为什么这么低? (2017-06-23 21:20:36) 转载▼ 分类: c from: 作者:jillzhang 出处:http://jillzhang.cnblogs ...
- jenkins+svn+pipeline+kubernetes部署java应用(一)
一.linux安装svn服务端 yum -y install subversion 二.创建svn版本库(项目仓库) mkdir -p /home/svn svnadmin create /home/ ...
- LeetCode1089复写零
问题: 给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移. 注意:请不要在超过该数组长度的位置写入元素. 要求:请对输入的数组 就地 进行上述修改,不要 ...