xmake v2.3.4 釋出, 更加完善的工具鏈支援
阿新 • • 發佈:2020-06-08
為了讓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符