第三方包管理器支持
新版本對內(nèi)置的包管理進(jìn)行了重構(gòu),已經(jīng)支持的非常完善了,我們可以通過
add_requires("libuv master", "ffmpeg", "zlib 1.20.*")`
方便的安裝使用依賴包,但是官方的包倉庫xmake-repo目前收錄的包還非常少,因此為了擴(kuò)充xmake的包倉庫,
xmake新增了對第三方包管理器的內(nèi)置支持,通過包命名空間顯式指定其他包管理器中的包,目前支持對conan::
,brew::
和vcpkg::
包管理中的包進(jìn)行安裝。
安裝homebrew的依賴包
add_requires("brew::zlib", {alias = "zlib"}})
add_requires("brew::pcre2/libpcre2-8", {alias = "pcre2"}})
target("test")
set_kind("binary")
add_files("src/*.c")
add_packages("pcre2", "zlib")
安裝vcpkg的依賴包
add_requires("vcpkg::zlib", "vcpkg::pcre2")
target("test")
set_kind("binary")
add_files("src/*.c")
add_packages("vcpkg::zlib", "vcpkg::pcre2")
不過需要注意的是,使用vcpkg,需要先對vcpkg與xmake進(jìn)行集成才行,詳細(xì)操作如下:
windows上用戶裝完vcpkg后,執(zhí)行$ vcpkg integrate install
,xmake就能自動從系統(tǒng)中檢測到vcpkg的根路徑,然后自動適配里面包。
當(dāng)然,我們也可以手動指定vcpkg的根路徑來支持:
$ xmake f --vcpkg=f:\vcpkg
安裝conan的依賴包
新版本實(shí)現(xiàn)了對conan的generator,來集成獲取conan中的包信息,我們在xmake中使用也是非常的方便,并且可以傳遞conan包的所有配置參數(shù)。
add_requires("conan::zlib/1.2.11@conan/stable", {alias = "zlib", debug = true})
add_requires("conan::OpenSSL/1.0.2n@conan/stable", {alias = "openssl", configs = {options = "OpenSSL:shared=True"}})
target("test")
set_kind("binary")
add_files("src/*.c")
add_packages("openssl", "zlib")
執(zhí)行xmake進(jìn)行編譯后:
ruki:test_package ruki$ xmake
checking for the architecture ... x86_64
checking for the Xcode directory ... /Applications/Xcode.app
checking for the SDK version of Xcode ... 10.14
note: try installing these packages (pass -y to skip confirm)?
-> conan::zlib/1.2.11@conan/stable (debug)
-> conan::OpenSSL/1.0.2n@conan/stable
please input: y (y/n)
=> installing conan::zlib/1.2.11@conan/stable .. ok
=> installing conan::OpenSSL/1.0.2n@conan/stable .. ok
[ 0%]: ccache compiling.release src/main.c
[100%]: linking.release test
內(nèi)置依賴包查找支持
之前的版本提供了lib.detect.find_package
來對依賴庫進(jìn)行查找,但是這需要通過import后才能使用,并且一次只能查找一個(gè)包,比較繁瑣:
target("test")
set_kind("binary")
add_files("src/*.c")
on_load(function (target)
import("lib.detect.find_package")
target:add(find_package("openssl"))
target:add(find_package("zlib"))
end)
而新版本中通過內(nèi)置find_packages
接口,對lib.detect.find_package
進(jìn)行了進(jìn)一步的封裝,來提升易用性:
target("test")
set_kind("binary")
add_files("src/*.c")
on_load(function (target)
target:add(find_packages("openssl", "zlib"))
end)
并且還支持從指定的第三方包管理器中進(jìn)行查找:
find_packages("conan::OpenSSL/1.0.2n@conan/stable", "brew::zlib")
參數(shù)配置依賴包安裝
新版本中對內(nèi)置的包管理進(jìn)行了大規(guī)模重構(gòu)和升級,并且對參數(shù)可配置編譯安裝依賴包進(jìn)行了更好的支持,我們可以在包倉庫中定義一些編譯安裝配置參數(shù),來定制安裝包。
例如, 我們以pcre2的包為例:
package("pcre2")
set_homepage("https://www.pcre.org/")
set_description("A Perl Compatible Regular Expressions Library")
set_urls("https://ftp.pcre.org/pub/pcre/pcre2-$(version).zip",
"ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-$(version).zip")
add_versions("10.23", "6301a525a8a7e63a5fac0c2fbfa0374d3eb133e511d886771e097e427707094a")
add_versions("10.30", "3677ce17854fffa68fce6b66442858f48f0de1f537f18439e4bd2771f8b4c7fb")
add_versions("10.31", "b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444")
add_configs("shared", {description = "Enable shared library.", default = false, type = "boolean"})
add_configs("jit", {description = "Enable jit.", default = true, type = "boolean"})
add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}})
上面我們通過add_configs
定義了三個(gè)條件配置參數(shù),使得用戶在集成使用pcre2庫的時(shí)候,可以定制化選擇是否需要啟用jit版本、bit位寬版本等,例如:
add_requires("pcre2", {configs = {jit = true, bitwidth = 8}})
而且,配置參數(shù)是強(qiáng)約束檢測的,如果傳的值不對,會提示報(bào)錯(cuò),避免傳遞無效的參數(shù)進(jìn)來,像bitwidth參數(shù)配置,被限制了只能在values = {"8", "16", "32"}
里面取值。
那么,用戶如何知道我們的包當(dāng)前支持哪些配置參數(shù)呢,很簡單,我們可以通過下面的命令,快速查看pcre2包的所有信息:
$ xmake require --info pcre2
輸出結(jié)果如下:
The package info of project:
require(pcre2):
-> description: A Perl Compatible Regular Expressions Library
-> version: 10.31
-> urls:
-> https://ftp.pcre.org/pub/pcre/pcre2-10.31.zip
-> b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444
-> ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-10.31.zip
-> b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444
-> repo: local-repo /Users/ruki/projects/personal/xmake-repo/
-> cachedir: /Users/ruki/.xmake/cache/packages/p/pcre2/10.31
-> installdir: /Users/ruki/.xmake/packages/p/pcre2/10.31/23b52ca1c6c8634f5f935903c9e7ea0e
-> fetchinfo: 10.31, system, optional
-> linkdirs: /usr/local/Cellar/pcre2/10.32/lib
-> defines: PCRE2_CODE_UNIT_WIDTH=8
-> links: pcre2-8
-> version: 10.32
-> includedirs: /usr/local/Cellar/pcre2/10.32/include
-> platforms: linux, macosx
-> requires:
-> plat: macosx
-> arch: x86_64
-> configs:
-> vs_runtime: MT
-> shared: false
-> jit: true
-> bitwidth: 8
-> debug: false
-> configs:
-> shared: Enable shared library. (default: false)
-> jit: Enable jit. (default: true)
-> bitwidth: Set the code unit width. (default: 8)
-> values: {"8","16","32"}
-> configs (builtin):
-> debug: Enable debug symbols. (default: false)
-> cflags: Set the C compiler flags.
-> cxflags: Set the C/C++ compiler flags.
-> cxxflags: Set the C++ compiler flags.
-> asflags: Set the assembler flags.
-> vs_runtime: Set vs compiler runtime. (default: MT)
-> values: {"MT","MD"}
其中,里面的configs:
部分,就是目前可提供配置的參數(shù)描述以及取值范圍,而configs (builtin):
中是一些xmake內(nèi)置的配置參數(shù),用戶也可直接配置使用。
例如最常用的debug模式包:
add_requires("pcre2", {configs = {debug = true}})
由于這個(gè)太過于常用,xmake提供了更方便的配置支持:
add_requires("pcre2", {debug = true})
另外requires:
里面的內(nèi)容,就是當(dāng)前依賴包的配置狀態(tài),方便用戶查看當(dāng)前使用了哪個(gè)模式的包。
預(yù)處理模板配置文件
xmake提供了三個(gè)新的接口api,用于在編譯前,添加一些需要預(yù)處理的配置文件,用于替代set_config_header等老接口。
add_configfiles
set_configdir
set_configvar
其中add_configfiles
相當(dāng)于cmake中的configure_file
接口,xmake中參考了它的api設(shè)計(jì),并且在其基礎(chǔ)上進(jìn)行了擴(kuò)展支持,提供更多的靈活性。
此接口相比以前的set_config_header
更加的通用,不僅用于處理config.h的自動生成和預(yù)處理,還可以處理各種文件類型,而set_config_header
僅用于處理頭文件,并且不支持模板變量替換。
先來一個(gè)簡單的例子:
target("test")
set_kind("binary")
add_files("src/*.c")
set_configdir("$(buildir)/config")
add_configfiles("src/config.h.in")
上面的設(shè)置,會在編譯前,自動的將config.h.in
這個(gè)頭文件配置模板,經(jīng)過預(yù)處理后,生成輸出到指定的build/config/config.h
。
這個(gè)接口的一個(gè)最重要的特性就是,可以在預(yù)處理的時(shí)候,對里面的一些模板變量進(jìn)行預(yù)處理替換,例如:
config.h.in
#define VAR1 "${VAR1}"
#define VAR2 "${VAR2}"
#define HELLO "${HELLO}"
set_configvar("VAR1", "1")
target("test")
set_kind("binary")
add_files("main.c")
set_configvar("VAR2", 2)
add_configfiles("config.h.in", {variables = {hello = "xmake"}})
add_configfiles("*.man", {copyonly = true})
通過set_configvar接口設(shè)置模板變量,裹著通過{variables = {xxx = ""}}
中設(shè)置的變量進(jìn)行替換處理。
預(yù)處理后的文件config.h
內(nèi)容為:
#define VAR1 "1"
#define VAR2 "2"
#define HELLO "xmake"
而{copyonly = true}
設(shè)置,會強(qiáng)制將*.man
作為普通文件處理,僅在預(yù)處理階段copy文件,不進(jìn)行變量替換。
默認(rèn)的模板變量匹配模式為${var}
,當(dāng)然我們也可以設(shè)置其他的匹配模式,例如,改為@var@
匹配規(guī)則:
target("test")
add_configfiles("config.h.in", {pattern = "@(.-)@"})
我們也有提供了一些內(nèi)置的變量,即使不通過此接口設(shè)置,也是可以進(jìn)行默認(rèn)變量替換的:
${VERSION} -> 1.6.3
${VERSION_MAJOR} -> 1
${VERSION_MINOR} -> 6
${VERSION_ALTER} -> 3
${VERSION_BUILD} -> set_version("1.6.3", {build = "%Y%m%d%H%M"}) -> 201902031421
${PLAT} and ${plat} -> MACOS and macosx
${ARCH} and ${arch} -> ARM and arm
${MODE} and ${mode} -> DEBUG/RELEASE and debug/release
${DEBUG} and ${debug} -> 1 or 0
${OS} and ${os} -> IOS or ios
例如:
config.h.in
#define CONFIG_VERSION "${VERSION}"
#define CONFIG_VERSION_MAJOR ${VERSION_MAJOR}
#define CONFIG_VERSION_MINOR ${VERSION_MINOR}
#define CONFIG_VERSION_ALTER ${VERSION_ALTER}
#define CONFIG_VERSION_BUILD ${VERSION_BUILD}
config.h
#define CONFIG_VERSION "1.6.3"
#define CONFIG_VERSION_MAJOR 1
#define CONFIG_VERSION_MINOR 6
#define CONFIG_VERSION_ALTER 3
#define CONFIG_VERSION_BUILD 201902031401
我們還可以對#define
定義進(jìn)行一些變量狀態(tài)控制處理:
config.h.in
${define FOO_ENABLE}
set_configvar("FOO_ENABLE", 1) -- or pass true
set_configvar("FOO_STRING", "foo")
通過上面的變量設(shè)置后,${define xxx}
就會替換成:
#define FOO_ENABLE 1
#define FOO_STRING "foo"
或者(設(shè)置為0禁用的時(shí)候)
/* #undef FOO_ENABLE */
/* #undef FOO_STRING */
這種方式,對于一些自動檢測生成config.h非常有用,比如配合option來做自動檢測:
option("foo")
set_default(true)
set_description("Enable Foo")
set_configvar("FOO_ENABLE", 1) -- 或者傳遞true,啟用FOO_ENABLE變量
set_configvar("FOO_STRING", "foo")
target("test")
add_configfiles("config.h.in")
-- 如果啟用foo選項(xiàng) -> 天劍 FOO_ENABLE 和 FOO_STRING 定義
add_options("foo")
config.h.in
${define FOO_ENABLE}
${define FOO_STRING}
config.h
#define FOO_ENABLE 1
#define FOO_STRING "foo"
關(guān)于option選項(xiàng)檢測,以及config.h的自動生成,有一些輔助函數(shù),可以看下:https://github.com/xmake-io/xmake/issues/342
除了#define
,如果想要對其他非#define xxx
也做狀態(tài)切換處理,可以使用 ${default xxx 0}
模式,設(shè)置默認(rèn)值,例如:
HAVE_SSE2 equ ${default VAR_HAVE_SSE2 0}
通過set_configvar("HAVE_SSE2", 1)
啟用變量后,變?yōu)?code>HAVE_SSE2 equ 1,如果沒有設(shè)置變量,則使用默認(rèn)值:HAVE_SSE2 equ 0
關(guān)于這個(gè)的詳細(xì)說明,見:https://github.com/xmake-io/xmake/issues/320
更加方便的特性檢測
我們通過add_configfiles
配合option檢測,可以做到檢測一些頭文件、接口函數(shù)、類型、編譯器特性是否存在,如果存在則自動寫入config.h中,例如:
option("foo")
set_default(true)
set_description("Has pthread library")
add_cincludes("pthread.h")
add_cfuncs("pthread_create")
add_links("pthread")
set_configvar("HAS_PTHREAD", 1)
target("test")
add_configfiles("config.h.in")
add_options("pthread")
config.h.in
${define HAS_PTHREAD}
config.h
#define HAS_PTHREAD 1
上面的配置,我們通過option檢測pthread.h里面的接口以及l(fā)ink庫是否都存在,如果能正常使用pthread庫,那么自動在config.h中定義HAS_PTHREAD
,并且test target中追加上相關(guān)的links。
上面的option可以支持各種檢測,但是配置上少許復(fù)雜繁瑣了些,為了讓xmake.lua更加的簡潔直觀,對于一些常用檢測,xmake通過擴(kuò)展includes接口,
提供了一些內(nèi)置封裝好的輔助接口函數(shù),來快速實(shí)現(xiàn)上面的option檢測,寫入config.h的功能。
上面的代碼我們可以簡化為:
includes("check_cfuncs.lua")
target("test")
add_configfiles("config.h.in")
configvar_check_cfuncs("HAS_PTHREAD", "pthread_create", {includes = "pthread.h", links = "pthread"})
除了configvar_check_cfuncs
,我們還有check_cfuncs
函數(shù),僅吧檢測結(jié)果直接在編譯時(shí)候追加,不再寫入configfiles文件中。
我們再來看個(gè)綜合性的例子:
includes("check_links.lua")
includes("check_ctypes.lua")
includes("check_cfuncs.lua")
includes("check_features.lua")
includes("check_csnippets.lua")
includes("check_cincludes.lua")
target("test")
set_kind("binary")
add_files("*.c")
add_configfiles("config.h.in")
configvar_check_ctypes("HAS_WCHAR", "wchar_t")
configvar_check_cincludes("HAS_STRING_H", "string.h")
configvar_check_cincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"})
configvar_check_ctypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"})
configvar_check_links("HAS_PTHREAD", {"pthread", "m", "dl"})
configvar_check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");")
configvar_check_cfuncs("HAS_SETJMP", "setjmp", {includes = {"signal.h", "setjmp.h"}})
configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr")
configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"})
config.h.in
${define HAS_STRING_H}
${define HAS_STRING_AND_STDIO_H}
${define HAS_WCHAR}
${define HAS_WCHAR_AND_FLOAT}
${define HAS_PTHREAD}
${define HAS_STATIC_ASSERT}
${define HAS_SETJMP}
${define HAS_CONSTEXPR}
${define HAS_CONSEXPR_AND_STATIC_ASSERT}
config.h
/* #undef HAS_STRING_H */
#define HAS_STRING_AND_STDIO_H 1
/* #undef HAS_WCHAR */
/* #undef HAS_WCHAR_AND_FLOAT */
#define HAS_PTHREAD 1
#define HAS_STATIC_ASSERT 1
#define HAS_SETJMP 1
/* #undef HAS_CONSTEXPR */
#define HAS_CONSEXPR_AND_STATIC_ASSERT 1
可以看到,xmake還提供了其他的輔助函數(shù),用于檢測:c/c++類型,c/c++代碼片段,c/c++函數(shù)接口,鏈接庫,頭文件是否存在,甚至是c/c++編譯器特性支持力度等。
關(guān)于這塊的更加完整的說明,可以看下:https://github.com/xmake-io/xmake/issues/342
配置自定義安裝文件
對于xmake install/uninstall
命令,xmake新增了add_installfiles
接口來設(shè)置一些安裝文件,比起on_install
,此接口用起來更加的方便簡潔,基本能夠滿足大部分安裝需求。
比如我們可以指定安裝各種類型的文件到安裝目錄:
target("test")
add_installfiles("src/*.h")
add_installfiles("doc/*.md")
默認(rèn)在linux等系統(tǒng)上,我們會安裝到/usr/local/*.h, /usr/local/*.md
,不過我們也可以指定安裝到特定子目錄:
target("test")
add_installfiles("src/*.h", {prefixdir = "include"})
add_installfiles("doc/*.md", {prefixdir = "share/doc"})
上面的設(shè)置,我們會安裝到/usr/local/include/*.h, /usr/local/share/doc/*.md
我們也可以通過()
去提取源文件中的子目錄來安裝,例如:
target("test")
add_installfiles("src/(tbox/*.h)", {prefixdir = "include"})
add_installfiles("doc/(tbox/*.md)", {prefixdir = "share/doc"})
我們把src/tbox/*.h
中的文件,提取tbox/*.h
子目錄結(jié)構(gòu)后,在進(jìn)行安裝:/usr/local/include/tbox/*.h, /usr/local/share/doc/tbox/*.md
當(dāng)然,用戶也可以通過set_installdir接口,來配合使用。
關(guān)于此接口的詳細(xì)說明,見:https://github.com/xmake-io/xmake/issues/318
CMakelists.txt導(dǎo)出
新版本對xmake project
工程生成插件進(jìn)行了擴(kuò)展,新增了對CMakelists.txt文件的導(dǎo)出支持,方便使用xmake的用戶可以快速導(dǎo)出CMakelists.txt提供給cmake,
以及CLion等一些支持cmake的工具使用,使用方式如下:
$ xmake project -k cmakelists
即可在當(dāng)前工程目錄下,生成對應(yīng)的CMakelists.txt文件。
原文出處:https://tboox.org/cn/2019/04/01/xmake-v2.2.5-new-features/