如果我们要写跨平台的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. django之session配置

    session应用示例 from django.shortcuts import render from django.shortcuts import HttpResponse from djang ...

  2. C++拾遗(六)——复制控制

    年前忙了几天,到现在才算是有空休息下来.先祝大家新年快乐,心想事成:)我也会发笑脸o.o 这篇博文主要介绍定义一个类型的对象时的复制控制方式,这部分内容之前有一定的了解但又浅尝辄止,始终感觉没能找到要 ...

  3. LR脚本录制方式说明

    1.LR脚本录制方式说明1)HTML-based script基于HTML的脚本从内存中读取并下载资源,较少的关联处理,可以加入图片检查,回放时需要解析返回的信息a-基于用户行为的方式 web_lin ...

  4. 日常-acm-三位数反转

    输入一个三位数,分理出它的百位,十位和个位,反转后输出. 样例输入: 127 样例输出: 721 tips:注意最后一位为0的情况,如360,输出063 #include <iostream&g ...

  5. uva806 Spatial Structures 空间结构 (黑白图像的四分树表示)

    input 8 00000000 00000000 00001111 00001111 00011111 00111111 00111100 00111000 -8 9 14 17 22 23 44 ...

  6. [Tracking] KCF + KalmanFilter目标跟踪

    基于KCF和MobileNet V2以及KalmanFilter的摄像头监测系统 简介 这是一次作业.Tracking这一块落后Detection很多年了,一般认为Detection做好了,那么只要能 ...

  7. 八数码问题(一) 暴力BFS + STL

    八数码问题是一个经典的人工智能问题.具体问题不累述了. 思路:由于存在多组测试数据,可以考虑“打表法“.所谓打表法,即枚举所有的初始情况,记录其到达终点的路径.而在这个题目中,顺序打表会调用很多次BF ...

  8. python面试笔试题汇总

    Python面试攻略(嗨谈篇) 110道python面试笔试题汇总,你能答对几道? Python 面试问答 Top 25 2018 年最常见的 Python 面试题 & 答案

  9. 重新postgresql出现错误:Problem running post-install step. Installation may not complete correctly. The database cluster initialisation failed.

    以前正常使用的postgresql,今天出现问题:报*.dll错误.百度了一下,只能重新安装 . 在重新安装过程中报:Problem running post-install step. Instal ...

  10. java abstraction and encapsulation

    How is Abstraction different from Encapsulation? Abstraction happens at class level design. It resul ...