為了讓xmake更好得支援交叉編譯,這個版本我重構了整個工具鏈,使得工具鏈的切換更加的方便快捷,並且現在使用者可以很方便地在xmake.lua中擴充套件自己的工具鏈。
關於平臺的支援上,我們新增了對*BSD系統的支援,另外,此版本還新增了一個ninja主題風格,實現類似ninja的編譯進度顯示,例如:
新特性介紹
工具鏈改進
工具鏈和平臺完全分離
之前的版本,平臺和工具鏈繫結的過於緊密,例如xmake f -p windows
平臺,預設只能使用msvc的編譯,想要切到clang或者其他編譯器,就只能走交叉編譯平臺:xmake f -p cross
。
但是這樣的話,一些windows平臺特有的設定就丟失了,而且使用者也沒法使用if is_plat("windows") then
來判斷windows平臺做特定的設定。
其實平臺和工具鏈是完全可以獨立開來的,新版本經過重構後,即使是windows平臺以及其他任何平臺,也可以方便快速的切換到clang, llvm等其他工具鏈。
$ xmake f -p windows --toolchain=clang
內建工具鏈
雖然xmake的交叉編譯配置支援所有工具鏈,也提供一定程度的智慧分析和工具鏈探測,但通用方案多少對特定工具鏈支援需要追加各種額外的配置,例如額外傳遞一些--ldflags=
, --cxflags=
引數什麼的。
而新版本xmake內建了一些常用工具鏈,可以省去交叉編譯工具鏈複雜的配置過程,只需要傳遞工具鏈名到--toolchain=xxx
即可。
切換到llvm工具鏈:
$ xmake f -p cross --toolchain=llvm --sdk="C:\Program Files\LLVM"
$ xmake
切換到GNU-RM工具鏈:
$ xmake f -p cross --toolchain=gnu-rm --sdk=/xxx/cc-arm-none-eabi-9-2019-q4-major
$ xmake
就可以快速切換的指定的交叉編譯工具鏈,對於內建的工具鏈,可以省去大部分配置,通常只需要--toolchain=
和--sdk=
即可,其他的配置都會自動設定好,確保編譯正常。
那xmake還支援哪些內建工具鏈呢?我們可以通過下面的命令檢視:
$ 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++
,因為編譯器切了,對應的連結器,靜態庫歸檔器什麼的都得同時切才行。
這麼挨個切一邊,確實很蛋疼,作者本人也是受不了了,所以重構工具鏈的時候,這塊也重點改進了下,現在只需要:
$ xmake f --toolchain=clang
$ xmake
就可以完全把所有clang工具集整體切過去,那如何重新切回gcc呢,也很方便:
或者
$ xmake f --toolchain=gcc
$ xmake
自定義工具鏈
另外,我們現在也可以在xmake.lua中自定義toolchain,然後通過xmake f --toolchain=myclang
指定切換,例如:
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地址。
關於這塊的詳情介紹,可以到自定義工具鏈章節檢視
更多詳情見:#780
針對特定target設定工具鏈
除了自定義工具鏈,我們也可以對某個特定的target單獨切換設定不同的工具鏈,和set_toolset不同的是,此介面是對完整工具鏈的整體切換,比如cc/ld/sh等一系列工具集。
這也是推薦做法,因為像gcc/clang等大部分編譯工具鏈,編譯器和連結器都是配套使用的,要切就得整體切,單獨零散的切換設定會很繁瑣。
比如我們切換test目標到clang+yasm兩個工具鏈:
target("test")
set_kind("binary")
add_files("src/*.c")
set_toolchains("clang", "yasm")
或者可以通過set_toolset
來對每個target的工具鏈中的特定工具單獨設定。
target("test")
set_kind("binary")
set_toolset("cxx", "clang")
set_toolset("ld", "clang++")
ninja構建主題
構建進度風格類似ninja,採用單行進度條,不再回滾進度,使用者可以根據自己的喜好設定。
除了進度展示不同外,其他都跟預設主題的配置相同。
$ xmake g --theme=ninja
設定構建行為策略
xmake有很多的預設行為,比如:自動檢測和對映flags、跨target並行構建等,雖然提供了一定的智慧化處理,但重口難調,不一定滿足所有的使用者的使用習慣和需求。
因此,從v2.3.4開始,xmake提供預設構建策略的修改設定,開放給使用者一定程度上的可配置性。
使用方式如下:
set_policy("check.auto_ignore_flags", false)
只需要在專案根域設定這個配置,就可以禁用flags的自動檢測和忽略機制,另外set_policy
也可以針對某個特定的target區域性生效。
target("test")
set_policy("check.auto_ignore_flags", false)
!> 另外,如果設定的策略名是無效的,xmake也會有警告提示。
如果要獲取當前xmake支援的所有策略配置列表和描述,可以執行下面的命令:
$ 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版本如果檢測失敗,會有警告提示避免使用者莫名躺坑,例如:
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,一種就是通過:
add_ldflags("-static", {force = true})
來顯示的強制設定上它,跳過自動檢測,這對於偶爾的flags失敗,是很有效快捷的處理方式,但是對於交叉編譯時候,一堆的flags設定檢測不過的情況下,每個都設定force太過於繁瑣。
這個時候,我們就可以通過set_policy
來對某個target或者整個project直接禁用預設的自動檢測行為:
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命名規範,對其根據不同的編譯實現自動對映,例如:
add_cxflags("-O0")
這一行設定,在gcc/clang下還是-O0
,但如果當前是msvc編譯器,那邊會自動對映為msvc對應-Od
編譯選項來禁用優化。
整個過程,使用者是完全無感知的,直接執行xmake就可以跨編譯器完成編譯。
!> 當然,目前的自動對映實現還不是很成熟,沒有100%覆蓋所有gcc的flags,所以還是有不少flags是沒去對映的。
也有部分使用者並不喜歡這種自動對映行為,那麼我們可以通過下面的設定完全禁用這個預設的行為:
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的情況,雖然很少遇到),我們也可以通過下面的設定禁用這個優化行為:
set_policy("build.across_targets_in_parallel", false)
新增編譯模式
mode.releasedbg
為當前工程xmake.lua新增releasedbg編譯模式的配置規則,例如:
add_rules("mode.releasedbg")
!> 與release模式相比,此模式還會額外開啟除錯符號,這通常是非常有用的。
相當於:
if is_mode("releasedbg") then
set_symbols("debug")
set_optimize("fastest")
set_strip("all")
end
我們可以通過:xmake f -m releasedbg
來切換到此編譯模式。
mode.minsizerel
為當前工程xmake.lua新增minsizerel編譯模式的配置規則,例如:
add_rules("mode.minsizerel")
!> 與release模式相比,此模式更加傾向於最小程式碼編譯優化,而不是速度優先。
相當於:
if is_mode("minsizerel") then
set_symbols("hidden")
set_optimize("smallest")
set_strip("all")
end
我們可以通過:xmake f -m minsizerel
來切換到此編譯模式。
顯示指定資訊和列表
顯示xmake自身和當前專案的基礎資訊
$ 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
顯示工具鏈列表
$ xmake show -l toolchains
xcode Xcode IDE
vs VisualStudio IDE
yasm The Yasm Modular Assembler
clang A C language family frontend for LLVM
...
顯示指定target配置資訊
$ 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
顯示內建編譯模式列表
$ xmake show -l modes
顯示內建編譯規則列表
$ xmake show -l rules
顯示其他資訊
還在完善中,詳情見:https://github.com/xmake-io/xmake/issues/798
或者執行:
$ xmake show --help
更新內容
新特性
- #630: 支援*BSD系統,例如:FreeBSD, ..
- 新增wprint介面去顯示警告資訊
- #784: 新增
set_policy()
去設定修改一些內建的策略,比如:禁用自動flags檢測和對映 - #780: 針對target新增set_toolchains/set_toolsets實現更完善的工具鏈設定,並且實現platform和toolchains分離
- #798: 新增
xmake show
外掛去顯示xmake內建的各種資訊 - #797: 新增ninja主題風格,顯示ninja風格的構建進度條,
xmake g --theme=ninja
- #816: 新增mode.releasedbg和mode.minsizerel編譯模式規則
- #819: 支援ansi/vt100終端字元控制
改進
- #771: 檢測includedirs,linkdirs和frameworkdirs的輸入有效性
- #774:
xmake f --menu
視覺化配置選單支援視窗大小Resize調整 - #782: 新增add_cxflags等配置flags自動檢測失敗提示
- #808: 生成cmakelists外掛增加對add_frameworks的支援
- #820: 支援獨立的工作目錄和構建目錄,保持專案目錄完全乾淨