xmake從入門到精通8:切換編譯模式

  • 2019 年 12 月 10 日
  • 筆記

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)  

關注公眾號

TBOOX開源工程

專註C跨平台開發解決方案