博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用xmake检测编译器特性支持
阅读量:6606 次
发布时间:2019-06-24

本文共 2724 字,大约阅读时间需要 9 分钟。

如果我们要写跨平台的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模块的接口,在xmake.lua中预先判断当前编译期支持的语言特性,实现条件编译。

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

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

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

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

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

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

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

批量编译器特性检测

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++编译器特性列表,见:

更加底层的检测接口

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

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 = "xcrun -sdk macosx clang"})local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = "-g"})

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

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

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

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

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支持。

此接口是, 和等接口的通用版本,也更加底层。

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

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

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

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

原文出处:

转载地址:http://vfbso.baihongyu.com/

你可能感兴趣的文章
索引失效的几个原因
查看>>
关于多线程中使用while做循环而不使用if的解释
查看>>
js typoeof用法
查看>>
五险一金,你清楚吗?
查看>>
Ip核_fifo
查看>>
自定义pageControl
查看>>
repquota命令--Linux命令应用大词典729个命令解读
查看>>
设置vs解决方案跟随右边cpp
查看>>
Linux Administration
查看>>
如何使版面富有节奏感
查看>>
rabbitmq 管理及常用命令
查看>>
iphone导航控制器的开发与使用
查看>>
debian python library re-install
查看>>
如何用转义来给JS添加的input元素设置单引号
查看>>
J2E——网络编程练习
查看>>
VirtualBox移植
查看>>
HTTP要被抛弃? 亚洲诚信携手宝塔开启HTTPS加密快速通道
查看>>
Chrome: 完全移除对WoSign和StartCom证书的信任
查看>>
RecyclerView侧滑删除功能
查看>>
记一个hystrix异常
查看>>