zoukankan      html  css  js  c++  java
  • xmake从入门到精通8:切换编译模式

    xmake是一个基于Lua的轻量级现代化c/c 的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验。

    本文我们会详细介绍下如何在项目构建过程中切换debug/release等常用构建模式,以及自定义其他编译模式。

    调试和发布模式

    通常,如果我们是通过xmake create命令创建的项目,会在xmake.lua里面自动添加一行编译规则的配置,如下:

    add_rules("mode.release", "mode.debug")
    target("hello")
        set_kind("binary")
        add_files("src/*.c")

    通过add_rules接口,我们默认添加了release和debug两个常用的内置规则,它们会在编译的时候附带上对应模式相关的一些编译flags,来开启优化用于发布或者调试编译。

    如果仅仅执行了xmake命令,没有额外的配置,那么默认就会是release编译,等价于:

    $ xmake f -m release
    $ xmake
    [  0%]: ccache compiling.release src/main.cpp
    [100%]: linking.release test
    build ok!

    如果我们要切换到debug编译模式,只需要:

    $ xmake f -m debug
    $ xmake
    [  0%]: ccache compiling.debug src/main.cpp
    [100%]: linking.debug test
    build ok!

    上面的-m/--mode=参数就是用来设置编译模式,会跟mode.releasemode.debug这两个规则做关联。

    那么,他们是如何关联上的呢?我们可以先来看下这两个规则的内部实现:

    rule("mode.debug")
        after_load(function (target)
            if is_mode("debug") then
                if not target:get("symbols") then
                    target:set("symbols", "debug")
                end
                if not target:get("optimize") then
                    target:set("optimize", "none")
                end
            end
        end)
    
    rule("mode.release")
        after_load(function (target)
            if is_mode("release") then
                if not target:get("symbols") and target:targetkind() ~= "shared" then
                    target:set("symbols", "hidden")
                end
                if not target:get("optimize") then
                    if is_plat("android", "iphoneos") then
                        target:set("optimize", "smallest")
                    else
                        target:set("optimize", "fastest")
                    end
                end
                if not target:get("strip") then
                    target:set("strip", "all")
                end
            end
        end)

    可以看到,在target被加载阶段,xmake会去判断用户对xmake f --mode=xxx的参数配置,如果通过is_mode()接口获取到是debug模式,那么会禁用相关优化并且启用符号输出。而如果是release模式,那么会开启编译优化并且strip掉所有调试符号。

    定制化的模式配置

    当然,内置的这两规则默认设置的这些编译配置,只能满足大部分场景的常规需求,如果用户想要在不同的编译模式下定制化一些个人的编译配置,那么需要自己在xmake.lua做判断。

    例如,我们想在release下也启用调试符号,那么只需要:

    if is_mode("release") then
        set_symbols("debug")
    end

    或者额外增加一些编译flags:

    if is_mode("release") then
        add_cflags("-fomit-frame-pointer")
    end

    注:如果用户自己的配置和mode.release内置的配置冲突,会优先使用用户的设置。

    当然,我们也可以完全不去通过add_rules("mode.debug", "mode.release")添加默认的配置规则,让用户完全自己控制模式配置:

    -- 如果当前编译模式是debug
    if is_mode("debug") then
    
        -- 添加DEBUG编译宏
        add_defines("DEBUG")
    
        -- 启用调试符号
        set_symbols("debug")
    
        -- 禁用优化
        set_optimize("none")
    end
    
    -- 如果是release或者profile模式
    if is_mode("release", "profile") then
    
        -- 如果是release模式
        if is_mode("release") then
    
            -- 隐藏符号
            set_symbols("hidden")
    
            -- strip所有符号
            set_strip("all")
    
            -- 忽略帧指针
            add_cxflags("-fomit-frame-pointer")
            add_mxflags("-fomit-frame-pointer")
    
        -- 如果是profile模式
        else
            -- 启用调试符号
            set_symbols("debug")
        end
    
        -- 添加扩展指令集
        add_vectorexts("sse2", "sse3", "ssse3", "mmx")
    end

    其他内置模式规则

    通过上文的例子,我们看到除了debug/release模式,还加了个profile模式的配置判断,其实xmake也提供了对应的内置模式,还有哪些,我们具体来看下:

    mode.debug

    为当前工程xmake.lua添加debug编译模式的配置规则,例如:

    add_rules("mode.debug")

    相当于:

    if is_mode("debug") then
        set_symbols("debug")
        set_optimize("none")
    end

    我们可以通过:xmake f -m debug来切换到此编译模式。

    mode.release

    为当前工程xmake.lua添加release编译模式的配置规则,例如:

    add_rules("mode.release")

    相当于:

    if is_mode("release") then
        set_symbols("hidden")
        set_optimize("fastest")
        set_strip("all")
    end

    我们可以通过:xmake f -m release来切换到此编译模式。

    mode.check

    为当前工程xmake.lua添加check编译模式的配置规则,一般用于内存检测,例如:

    add_rules("mode.check")

    相当于:

    if is_mode("check") then
        set_symbols("debug")
        set_optimize("none")
        add_cxflags("-fsanitize=address", "-ftrapv")
        add_mxflags("-fsanitize=address", "-ftrapv")
        add_ldflags("-fsanitize=address")
    end

    我们可以通过:xmake f -m check来切换到此编译模式。

    mode.profile

    为当前工程xmake.lua添加profile编译模式的配置规则,一般用于性能分析,例如:

    add_rules("mode.profile")

    相当于:

    if is_mode("profile") then
        set_symbols("debug")
        add_cxflags("-pg")
        add_ldflags("-pg")
    end

    我们可以通过:xmake f -m profile来切换到此编译模式。

    mode.coverage

    为当前工程xmake.lua添加coverage编译模式的配置规则,一般用于覆盖分析,例如:

    add_rules("mode.coverage")

    相当于:

    if is_mode("coverage") then
        add_cxflags("--coverage")
        add_mxflags("--coverage")
        add_ldflags("--coverage")
    end

    我们可以通过:xmake f -m coverage来切换到此编译模式。

    注:生成的gcno文件一般都是个obj所在目录对应的哦,因此需要从build目录下去找。

    扩展自己的编译模式

    xmake的模式配置,并没有固定值,用户可以随意传入和配置,只要xmake f -m/--mode=xxx传入的模式值和xmake.lua里面的is_mode("xxx")能对应上就行。

    比如,我们设置了一个自己独有的编译模式my_mode,可以直接在命令行配置切换;

    $ xmake f -m my_mode
    $ xmake
    [  0%]: ccache compiling.my_mode src/main.cpp
    [100%]: linking.my_mode test
    build ok!

    然后xmake.lua里面对相应的值进行判断即可:

    if is_mode("my_mode") then
        add_defines("ENABLE_MY_MODE")
    end

    使用模式变量

    我们也可以直接在配置值中传递模式变量$(mode),比如根据不同模式选择链接不同的库:

    target("test")
        set_kind("binary")
        add_files("src/*.c")
        add_links("xxx_$(mode)")

    上面的配置,如果是调试模式编译就会选择链接:libxxx_debug.a库,而release下就会链接libxxx_release.a,当然,我们也可以设置到库搜索路径中,根据目录来选择对应的库。

    target("test")
        set_kind("binary")
        add_files("src/*.c")
        add_linkdirs("lib/$(mode)")
        add_links("xxx")

    另外,我们可以通过get_config("mode")直接获取到传入的模式配置值,并且这几种获取方式,在自定义脚本也是同样有效的哦,例如:

    target("test")
        set_kind("binary")
        add_files("src/*.c")
        on_load(function (target)
            if is_mode("release") then
                print(get_config("mode"), "$(mode)")
            end
        end)

    原文:https://tboox.org/cn/2019/12/05/quickstart-8-switch-build-mode/

    个人主页

    个人项目

  • 相关阅读:
    自己写的一个校验IP、IP掩码、IP段的方法
    JS 数组方法splice的源码探究
    element ui 的时间选择控件
    浅谈闭包
    tensorFlow-深度学习训练并行模式
    tensorflow-TensorBoard
    tensorflow-RNN和LSTM
    tensorflow-TFRecord报错ValueError: Protocol message Feature has no "feature" field.
    tensorflow-mnist报错[WinError 10060] 由于连接方在一段时间后没有正确答复解决办法
    旋转图片,增加神经网络的准确率
  • 原文地址:https://www.cnblogs.com/tboox/p/12014641.html
Copyright © 2011-2022 走看看