1. 程式人生 > >xmake v2.3.4 釋出, 更加完善的工具鏈支援

xmake v2.3.4 釋出, 更加完善的工具鏈支援

為了讓xmake更好得支援交叉編譯,這個版本我重構了整個工具鏈,使得工具鏈的切換更加的方便快捷,並且現在使用者可以很方便地在xmake.lua中擴充套件自己的工具鏈。 關於平臺的支援上,我們新增了對*BSD系統的支援,另外,此版本還新增了一個ninja主題風格,實現類似ninja的編譯進度顯示,例如: * [專案原始碼](https://github.com/xmake-io/xmake) * [官方文件](https://xmake.io/#/zh-cn/) ## 新特性介紹 ### 工具鏈改進 #### 工具鏈和平臺完全分離 之前的版本,平臺和工具鏈繫結的過於緊密,例如`xmake f -p windows` 平臺,預設只能使用msvc的編譯,想要切到clang或者其他編譯器,就只能走交叉編譯平臺:`xmake f -p cross`。 但是這樣的話,一些windows平臺特有的設定就丟失了,而且使用者也沒法使用`if is_plat("windows") then`來判斷windows平臺做特定的設定。 其實平臺和工具鏈是完全可以獨立開來的,新版本經過重構後,即使是windows平臺以及其他任何平臺,也可以方便快速的切換到clang, llvm等其他工具鏈。 ```bash $ xmake f -p windows --toolchain=clang ``` #### 內建工具鏈 雖然xmake的交叉編譯配置支援所有工具鏈,也提供一定程度的智慧分析和工具鏈探測,但通用方案多少對特定工具鏈支援需要追加各種額外的配置,例如額外傳遞一些`--ldflags=`, `--cxflags=`引數什麼的。 而新版本xmake內建了一些常用工具鏈,可以省去交叉編譯工具鏈複雜的配置過程,只需要傳遞工具鏈名到`--toolchain=xxx`即可。 切換到llvm工具鏈: ```bash $ xmake f -p cross --toolchain=llvm --sdk="C:\Program Files\LLVM" $ xmake ``` 切換到GNU-RM工具鏈: ```bash $ xmake f -p cross --toolchain=gnu-rm --sdk=/xxx/cc-arm-none-eabi-9-2019-q4-major $ xmake ``` 就可以快速切換的指定的交叉編譯工具鏈,對於內建的工具鏈,可以省去大部分配置,通常只需要`--toolchain=`和`--sdk=`即可,其他的配置都會自動設定好,確保編譯正常。 那xmake還支援哪些內建工具鏈呢?我們可以通過下面的命令檢視: ```bash $ xmake show -l toolchains xcode Xcode IDE vs VisualStudio IDE yasm The Yasm Modular Assembler clang A C language family frontend for LLVM go Go Programming Language Compiler dlang D Programming Language Compiler sdcc Small Device C Compiler cuda CUDA Toolkit ndk Android NDK rust Rust Programming Language Compiler llvm A collection of modular and reusable compiler and toolchain technologies cross Common cross compilation toolchain nasm NASM Assembler gcc GNU Compiler Collection mingw Minimalist GNU for Windows gnu-rm GNU Arm Embedded Toolchain envs Environment variables toolchain fasm Flat Assembler ``` #### 工具鏈的同步切換 新版本xmake還支援工具鏈的完整同步切換,這個是什麼意思呢? 比如,我們要從預設的gcc切換到clang編譯,可能需要切一些工具集,`xmake f --cc=clang --cxx=clang --ld=clang++ --sh=clang++`,因為編譯器切了,對應的連結器,靜態庫歸檔器什麼的都得同時切才行。 這麼挨個切一邊,確實很蛋疼,作者本人也是受不了了,所以重構工具鏈的時候,這塊也重點改進了下,現在只需要: ```bash $ xmake f --toolchain=clang $ xmake ``` 就可以完全把所有clang工具集整體切過去,那如何重新切回gcc呢,也很方便: 或者 ```bash $ xmake f --toolchain=gcc $ xmake ``` #### 自定義工具鏈 另外,我們現在也可以在xmake.lua中自定義toolchain,然後通過`xmake f --toolchain=myclang`指定切換,例如: ```lua toolchain("myclang") set_kind("standalone") set_toolset("cc", "clang") set_toolset("cxx", "clang", "clang++") set_toolset("ld", "clang++", "clang") set_toolset("sh", "clang++", "clang") set_toolset("ar", "ar") set_toolset("ex", "ar") set_toolset("strip", "strip") set_toolset("mm", "clang") set_toolset("mxx", "clang", "clang++") set_toolset("as", "clang") -- ... ``` 其中`set_toolset`用於挨個設定不同的工具集,比如編譯器、連結器、彙編器等。 xmake預設會從`xmake f --sdk=xx`的sdk引數中去探測工具,當然我們也可以在xmake.lua中對每個自定義工具鏈呼叫`set_sdk("/xxx/llvm")`來寫死工具鏈sdk地址。 關於這塊的詳情介紹,可以到[自定義工具鏈](https://xmake.io/zh-cn/manual/custom_toolchain)章節檢視 更多詳情見:[#780](https://github.com/xmake-io/xmake/issues/780) #### 針對特定target設定工具鏈 除了自定義工具鏈,我們也可以對某個特定的target單獨切換設定不同的工具鏈,和set_toolset不同的是,此介面是對完整工具鏈的整體切換,比如cc/ld/sh等一系列工具集。 這也是推薦做法,因為像gcc/clang等大部分編譯工具鏈,編譯器和連結器都是配套使用的,要切就得整體切,單獨零散的切換設定會很繁瑣。 比如我們切換test目標到clang+yasm兩個工具鏈: ```lua target("test") set_kind("binary") add_files("src/*.c") set_toolchains("clang", "yasm") ``` 或者可以通過`set_toolset`來對每個target的工具鏈中的特定工具單獨設定。 ```lua target("test") set_kind("binary") set_toolset("cxx", "clang") set_toolset("ld", "clang++") ``` ### ninja構建主題 構建進度風格類似ninja,採用單行進度條,不再回滾進度,使用者可以根據自己的喜好設定。 除了進度展示不同外,其他都跟預設主題的配置相同。 ```bash $ xmake g --theme=ninja ```
### 設定構建行為策略 xmake有很多的預設行為,比如:自動檢測和對映flags、跨target並行構建等,雖然提供了一定的智慧化處理,但重口難調,不一定滿足所有的使用者的使用習慣和需求。 因此,從v2.3.4開始,xmake提供預設構建策略的修改設定,開放給使用者一定程度上的可配置性。 使用方式如下: ```lua set_policy("check.auto_ignore_flags", false) ``` 只需要在專案根域設定這個配置,就可以禁用flags的自動檢測和忽略機制,另外`set_policy`也可以針對某個特定的target區域性生效。 ```lua target("test") set_policy("check.auto_ignore_flags", false) ``` !> 另外,如果設定的策略名是無效的,xmake也會有警告提示。 如果要獲取當前xmake支援的所有策略配置列表和描述,可以執行下面的命令: ```bash $ xmake l core.project.policy.policies { "check.auto_map_flags" = { type = "boolean", description = "Enable map gcc flags to the current compiler and linker automatically.", default = true }, "build.across_targets_in_parallel" = { type = "boolean", description = "Enable compile the source files for each target in parallel.", default = true }, "check.auto_ignore_flags" = { type = "boolean", description = "Enable check and ignore unsupported flags automatically.", default = true } } ``` #### check.auto_ignore_flags xmake預設會對所有`add_cxflags`, `add_ldflags`介面設定的原始flags進行自動檢測,如果檢測當前編譯器和連結器不支援它們,就會自動忽略。 這通常是很有用的,像一些可選的編譯flags,即使不支援也能正常編譯,但是強行設定上去,其他使用者在編譯的時候,有可能會因為編譯器的支援力度不同,出現一定程度的編譯失敗。 但,由於自動檢測並不保證100%可靠,有時候會有一定程度的誤判,所以某些使用者並不喜歡這個設定(尤其是針對交叉編譯工具鏈,更容易出現失敗)。 目前,v2.3.4版本如果檢測失敗,會有警告提示避免使用者莫名躺坑,例如: ```bash warning: add_ldflags("-static") is ignored, please pass `{force = true}` or call `set_policy("check.auto_ignore_flags", false)` if you want to set it. ``` 根據提示,我們可以自己分析判斷,是否需要強制設定這個flags,一種就是通過: ```lua add_ldflags("-static", {force = true}) ``` 來顯示的強制設定上它,跳過自動檢測,這對於偶爾的flags失敗,是很有效快捷的處理方式,但是對於交叉編譯時候,一堆的flags設定檢測不過的情況下,每個都設定force太過於繁瑣。 這個時候,我們就可以通過`set_policy`來對某個target或者整個project直接禁用預設的自動檢測行為: ```lua set_policy("check.auto_ignore_flags", false) target("test") add_ldflags("-static") ``` 然後我們就可以隨意設定各種原始flags,xmake不會去自動檢測和忽略他們了。 #### check.auto_map_flags 這是xmake的另外一個對flags的智慧分析處理,通常像`add_links`, `add_defines`這種xmake內建的api去設定的配置,是具有跨平臺特性的,不同編譯器平臺會自動處理成對應的原始flags。 但是,有些情況,使用者還是需要自己通過add_cxflags, add_ldflags設定原始的編譯連結flags,這些flags並不能很好的跨編譯器 就拿`-O0`的編譯優化flags來說,雖然有`set_optimize`來實現跨編譯器配置,但如果使用者直接設定`add_cxflags("-O0")`呢?gcc/clang下可以正常處理,但是msvc下就不支援了 也許我們能通過`if is_plat() then`來分平臺處理,但很繁瑣,因此xmake內建了flags的自動對映功能。 基於gcc flags的普及性,xmake採用gcc的flags命名規範,對其根據不同的編譯實現自動對映,例如: ```lua add_cxflags("-O0") ``` 這一行設定,在gcc/clang下還是`-O0`,但如果當前是msvc編譯器,那邊會自動對映為msvc對應`-Od`編譯選項來禁用優化。 整個過程,使用者是完全無感知的,直接執行xmake就可以跨編譯器完成編譯。 !> 當然,目前的自動對映實現還不是很成熟,沒有100%覆蓋所有gcc的flags,所以還是有不少flags是沒去對映的。 也有部分使用者並不喜歡這種自動對映行為,那麼我們可以通過下面的設定完全禁用這個預設的行為: ```bash set_policy("check.auto_map_flags", false) ``` #### build.across_targets_in_parallel 這個策略也是預設開啟的,主要用於跨target間執行並行構建,v2.3.3之前的版本,並行構建只能針對單個target內部的所有原始檔, 跨target的編譯,必須要要等先前的target完全link成功,才能執行下一個target的編譯,這在一定程度上會影響編譯速度。 然而每個target的原始檔是可以完全並行化處理的,最終在一起執行link過程,v2.3.3之後的版本通過這個優化,構建速度提升了30%。 當然,如果有些特殊的target裡面的構建原始檔要依賴先前的target(尤其是一些自定義rules的情況,雖然很少遇到),我們也可以通過下面的設定禁用這個優化行為: ```bash set_policy("build.across_targets_in_parallel", false) ``` ### 新增編譯模式 #### mode.releasedbg 為當前工程xmake.lua新增releasedbg編譯模式的配置規則,例如: ```lua add_rules("mode.releasedbg") ``` !> 與release模式相比,此模式還會額外開啟除錯符號,這通常是非常有用的。 相當於: ```lua if is_mode("releasedbg") then set_symbols("debug") set_optimize("fastest") set_strip("all") end ``` 我們可以通過:`xmake f -m releasedbg`來切換到此編譯模式。 #### mode.minsizerel 為當前工程xmake.lua新增minsizerel編譯模式的配置規則,例如: ```lua add_rules("mode.minsizerel") ``` !> 與release模式相比,此模式更加傾向於最小程式碼編譯優化,而不是速度優先。 相當於: ```lua if is_mode("minsizerel") then set_symbols("hidden") set_optimize("smallest") set_strip("all") end ``` 我們可以通過:`xmake f -m minsizerel`來切換到此編譯模式。 ### 顯示指定資訊和列表 #### 顯示xmake自身和當前專案的基礎資訊 ```bash $ xmake show The information of xmake: version: 2.3.3+202006011009 host: macosx/x86_64 programdir: /Users/ruki/.local/share/xmake programfile: /Users/ruki/.local/bin/xmake globaldir: /Users/ruki/.xmake tmpdir: /var/folders/32/w9cz0y_14hs19lkbs6v6_fm80000gn/T/.xmake501/200603 workingdir: /Users/ruki/projects/personal/tbox packagedir: /Users/ruki/.xmake/packages packagedir(cache): /Users/ruki/.xmake/cache/packages/2006 The information of project: tbox version: 1.6.5 plat: macosx arch: x86_64 mode: release buildir: build configdir: /Users/ruki/projects/personal/tbox/.xmake/macosx/x86_64 projectdir: /Users/ruki/projects/personal/tbox projectfile: /Users/ruki/projects/personal/tbox/xmake.lua ``` #### 顯示工具鏈列表 ```bash $ xmake show -l toolchains xcode Xcode IDE vs VisualStudio IDE yasm The Yasm Modular Assembler clang A C language family frontend for LLVM ... ``` #### 顯示指定target配置資訊 ```bash $ xmake show --target=tbox The information of target(tbox): kind: static targetfile: build/macosx/x86_64/release/libtbox.a rules: mode.release, mode.debug, mode.profile, mode.coverage options: info, float, wchar, exception, force-utf8, deprecated, xml, zip, hash, regex, coroutine, object, charset, database packages: mbedtls, polarssl, openssl, pcre2, pcre, zlib, mysql, sqlite3 links: pthread syslinks: pthread, dl, m, c cxflags: -Wno-error=deprecated-declarations, -fno-strict-aliasing, -Wno-error=expansion-to-defined, -fno-stack-protector defines: __tb_small__, __tb_prefix__="tbox" mxflags: -Wno-error=deprecated-declarations, -fno-strict-aliasing, -Wno-error=expansion-to-defined headerfiles: src/(tbox/**.h)|**/impl/**.h, src/(tbox/prefix/**/prefix.S), src/(tbox/math/impl/*.h), src/(tbox/utils/impl/*.h), build/macosx/x86_64/release/tbox.config.h includedirs: src, build/macosx/x86_64/release at: /Users/ruki/projects/personal/tbox/src/tbox/xmake.lua sourcebatch(cc): with rule(c.build) -> src/tbox/string/static_string.c -> build/.objs/tbox/macosx/x86_64/release/src/tbox/string/static_string.c.o -> build/.deps/tbox/macosx/x86_64/release/src/tbox/string/static_string.c.o.d -> src/tbox/platform/sched.c -> build/.objs/tbox/macosx/x86_64/release/src/tbox/platform/sched.c.o -> build/.deps/tbox/macosx/x86_64/release/src/tbox/platform/sched.c.o.d -> src/tbox/stream/stream.c -> build/.objs/tbox/macosx/x86_64/release/src/tbox/stream/stream.c.o -> build/.deps/tbox/macosx/x86_64/release/src/tbox/stream/stream.c.o.d -> src/tbox/utils/base32.c -> build/.objs/tbox/macosx/x86_64/release/src/tbox/utils/base32.c.o -> build/.deps/tbox/macosx/x86_64/release/src/tbox/utils/base32.c.o.d ``` #### 顯示內建編譯模式列表 ```bash $ xmake show -l modes ``` #### 顯示內建編譯規則列表 ```bash $ xmake show -l rules ``` #### 顯示其他資訊 還在完善中,詳情見:https://github.com/xmake-io/xmake/issues/798 或者執行: ```bash $ xmake show --help ``` ## 更新內容 ### 新特性 * [#630](https://github.com/xmake-io/xmake/issues/630): 支援*BSD系統,例如:FreeBSD, .. * 新增wprint介面去顯示警告資訊 * [#784](https://github.com/xmake-io/xmake/issues/784): 新增`set_policy()`去設定修改一些內建的策略,比如:禁用自動flags檢測和對映 * [#780](https://github.com/xmake-io/xmake/issues/780): 針對target新增set_toolchains/set_toolsets實現更完善的工具鏈設定,並且實現platform和toolchains分離 * [#798](https://github.com/xmake-io/xmake/issues/798): 新增`xmake show`外掛去顯示xmake內建的各種資訊 * [#797](https://github.com/xmake-io/xmake/issues/797): 新增ninja主題風格,顯示ninja風格的構建進度條,`xmake g --theme=ninja` * [#816](https://github.com/xmake-io/xmake/issues/816): 新增mode.releasedbg和mode.minsizerel編譯模式規則 * [#819](https://github.com/xmake-io/xmake/issues/819): 支援ansi/vt100終端字元控制 ### 改進 * [#771](https://github.com/xmake-io/xmake/issues/771): 檢測includedirs,linkdirs和frameworkdirs的輸入有效性 * [#774](https://github.com/xmake-io/xmake/issues/774): `xmake f --menu`視覺化配置選單支援視窗大小Resize調整 * [#782](https://github.com/xmake-io/xmake/issues/782): 新增add_cxflags等配置flags自動檢測失敗提示 * [#808](https://github.com/xmake-io/xmake/issues/808): 生成cmakelists外掛增加對add_frameworks的支援 * [#820](https://github.com/xmake-io/xmake/issues/820): 支援獨立的工作目錄和構建目錄,保持專案目錄完全乾淨 ### Bugs修復 * [#786](https://github.com/xmake-io/xmake/issues/786): 修復標頭檔案依賴檢測 * [#810](https://github.com/xmake-io/xmake/issues/810): 修復linux下gcc strip debug符