xmake集成了內置的遠程包依賴管理,用戶只須要簡單地在項目中添加本身所須要的包和版本,便可自動下載和集成對應的包到項目中,而且實現編譯和連接。
例如:
add_requires("libuv master", "ffmpeg", "zlib 1.20.*")
add_requires("tbox >1.6.1", {optional = true, debug = true})
add_requires("boost", {alias = "boost_context", configs = {context = true}})
target("test")
set_kind("binary")
add_files("src/*.c")
add_packages("libuv", "ffmpeg", "tbox", "boost_context", "zlib")
xmake的包倉庫設計之初,就考慮到了語義版本支持,以及依賴包的跨平臺支持,只要包自身能支持的平臺,均可以集成進來,好比zlib包,在xmake中使用,iphoneos, android以及mingw平臺下都是徹底可用的。
用戶只須要簡單的切下構建平臺:
xmake f -p iphoneos -a arm64
xmake
note: try installing these packages (pass -y to skip confirm)?
in xmake-repo:
-> zlib 1.2.11
please input: y (y/n)
=> download https://www.xcdeyiju.com downloads.sourceforge.net/project/libpng/zlib/1.2.11/zlib-1.2.11.tar.gz .. ok
=> install zlib 1.2.11 .. ok
就能夠對iphoneos平臺下載集成add_requires中對應的包,xmake的最終目標,是打造一個跨平臺的包倉庫,用戶再也不須要滿地找c/c++庫,而後研究各類平臺的移植,只須要簡單的添加上包依賴,便可在各個平臺都能方便使用。
固然了,目前xmake的官方倉庫還在發展初期,裏面的包還不多,支持的平臺也不是很完善,所以,這裏我簡單介紹下用戶如何去本身製做和上傳本身須要的c/c++包,並如何提交到咱們的倉庫中(也能夠自建私有倉庫), 但願有興趣的小夥伴能夠幫忙貢獻一份微薄之力,一塊兒共同打造和創建c/c++依賴包生態。
項目源碼
官方文檔
添加包到倉庫
倉庫包結構
在製做本身的包以前,咱們須要先了解下一個包倉庫的結構,不論是官方包倉庫,仍是自建私有包倉庫,結構都是相同的:
xmake-repo
- packages
- t/tbox/xmake.lua
- z/zlib/xmake.lua
經過上面的結構,能夠看到每一個包都會有個xmake.lua用於描述它的安裝規則,而且根據z/zlib兩級子目錄分類存儲,方便快速檢索。
包描述說明
關於包的描述規則,基本上都是在它的xmake.lua裏面完成的,這跟項目工程裏面的xmake.lua描述很相似,不一樣的是描述域僅支持package(),
不過,在項目xmake.lua裏面,也是能夠直接添加package()來內置包描述的,連包倉庫都省了,有時候這樣會更加方便。
首先,咱們先拿zlib的描述規則,來直觀感覺下,這個規則能夠在xmake-repo/z/zlib/xmake.lua下找到。
package("zlib")
set_homepage("http://www.chengmingdl.com ")
set_description("A Massively Spiffy Yet Delicately Unobtrusive Compression Library")
set_urls(http://www.senta7.net/content/?729.html,
"https://www.yuechaoyule.com downloads.sourceforge.net/project/libpng/zlib/$(version)/zlib-$(version).tar.gz")
add_versions("1.2.10", "8d7e9f698ce48787b6e1c67e6bff79e487303e66077e25cb9784ac8835978017")
add_versions("1.2.11", "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1")
on_install("windows", function (package)
io.gsub("win32/Makefile.msc", "%-MD", "-" .. package:config("vs_runtime"))
os.vrun("nmake -f win32\\Makefile.msc zlib.lib")
os.cp("zlib.lib", package:installdir("lib"))
os.cp("*.h", package:installdir("include"))
end)
on_install("linux", "macosx"www.seocelve.com, function (package)
import("package.tools.autoconf").install(package, {"--static"})
end)
on_install("iphoneos", "android@linux,macosx", "mingw@linux,macosx", function (package)
import("package.tools.autoconf"www.csyldl.com).configure(package, {host = "", "--static"})
io.gsub("Makefile", "\nAR=.-\n", "\nAR=" .. (package:build_getenv("ar") or "") .. "\n")
io.gsub("Makefile", "\nARFLAGS=.-\n", "\nARFLAGS=cr\n")
io.gsub("Makefile", "\nRANLIB=.-\n", "\nRANLIB=\n")
os.vrun("make install -j4")
end)
on_test(function (package)
assert(package:has_cfuncs("inflate",www.baiyiyulgw.com {includes = "zlib.h"}))
end)
這個包規則對windows, linux, macosx, iphoneos,mingw等平臺都添加了安裝規則,基本上已經作到了全平臺覆蓋,甚至一些交叉編譯平臺,算是一個比較典型的例子了。
固然,有些包依賴源碼實現力度,並不能徹底跨平臺,那麼只需對它支持的平臺設置安裝規則便可。
set_homepage
設置包所在項目的官方頁面地址。
set_description
設置包的相關描述信息,通常經過xmake require --info zlib查看相關包信息時候,會看到。
set_kind
設置包類型,對於依賴庫,則不用設置,若是是可執行包,須要設置爲binary。
package("cmake")
set_kind("binary")
set_homepage("https://cmake.org")
set_description("A cross-platform family of tool designed to build, test and package software")
set_urls
設置包的源碼包或者git倉庫地址,跟add_urls不一樣的是,此接口是覆蓋性設置,而add_urls是追加設置,其餘使用方式相似,這個根據不一樣須要來選擇。
add_urls
添加包的源碼包或者git倉庫地址,此接口通常跟add_version配對使用,用於設置每一個源碼包的版本和對應的sha256值。
!> 能夠經過添加多個urls做爲鏡像源,xmake會自動檢測優先選用最快的url進行下載,若是下載失敗則會嘗試其餘urls。
add_urls("https://github.com/protobuf-c/protobuf-c/releases/download/v$(version)/protobuf-c-$(version).tar.gz")
add_versions("1.3.1", "51472d3a191d6d7b425e32b612e477c06f73fe23e07f6a6a839b11808e9d2267")
urls裏面的$(version)內置變量,會根據實際安裝時候選擇的版本適配進去,而版本號都是從add_versions中指定的版本列表中選擇的。
若是對於urls裏面帶有比較複雜的版本串,沒有跟add_versions有直接對應關係,則須要經過下面的方式定製化轉換下:
add_urls("https://sqlite.org/2018/sqlite-autoconf-$(version)000.tar.gz",
{version = function (version) return version:gsub("%.", "") end})
add_versions("3.24.0", "d9d14e88c6fb6d68de9ca0d1f9797477d82fc3aed613558f87ffbdbbc5ceb74a")
add_versions("3.23.0", "b7711a1800a071674c2bf76898ae8584fc6c9643cfe933cfc1bc54361e3a6e49")
固然,咱們也只能夠添加git源碼地址:
add_urls("https://gitlab.gnome.org/GNOME/libxml2.git")
若是設置的多個鏡像地址對應的源碼包sha256是不一樣的,咱們能夠經過alias的方式來分別設置
add_urls("https://ffmpeg.org/releases/ffmpeg-$(version).tar.bz2", {alias = "home"})
add_urls("https://github.com/FFmpeg/FFmpeg/archive/n$(version).zip", {alias = "github"})
add_versions("home:4.0.2", "346c51735f42c37e0712e0b3d2f6476c86ac15863e4445d9e823fe396420d056")
add_versions("github:4.0.2", "4df1ef0bf73b7148caea1270539ef7bd06607e0ea8aa2fbf1bb34062a097f026")
add_versions
用於設置每一個源碼包的版本和對應的sha256值,具體描述見:add_urls
add_patches
此接口用於針對源碼包,在編譯安裝前,先打對應設置的補丁包,再對其進行編譯,而且可支持同時打多個補丁。
if is_plat("macosx") then
add_patches("1.15", "https://www.yacuangyl.com raw.githubusercontent.com/Homebrew/patches/9be2793af/libiconv/patch-utf8mac.diff",
"e8128732f22f63b5c656659786d2cf76f1450008f36bcf541285268c66cabeab")
end
例如,上面的代碼,就是針對macosx下編譯的時候,打上對應的patch-utf8mac.diff補丁,而且每一個補丁後面也是要設置sha256值的,確保完整性。
add_links
默認狀況下,xmake會去自動檢測安裝後的庫,設置連接關係,可是有時候並非很準,若是要本身手動調整連接順序,以及連接名,則能夠經過這個接口來設置。
add_links("mbedtls", "mbedx509", "mbedcrypto")
add_syslinks
添加一些系統庫連接,有些包集成連接的時候,還須要依賴一些系統庫,才能連接經過,這個時候能夠在包描述裏面都附加上去。
if is_plat("macosx") then
add_frameworks("CoreGraphics", "CoreFoundation", "Foundation")
elseif is_plat("windows") then
add_defines("CAIRO_WIN32_STATIC_BUILD=1")
add_syslinks("gdi32", "msimg32", "user32")
else
add_syslinks("pthread")
end
add_frameworks
添加依賴的系統frameworks連接。
示例見:add_syslinks
add_linkdirs
包的連接庫搜索目錄也是能夠調整的,不過一般都不須要,除非一些庫安裝完不在prefix/lib下面,而在lib的子目錄下,默認搜索不到的話。
add_includedirs
添加其餘頭文件搜索目錄。
add_defines
能夠對集成的包對外輸出一些特定的定義選項。
add_configs
咱們能夠經過此接口添加每一個包的對外輸出配置參數:
package("pcre2")
set_homepage("https://www.pcre.org/")
set_description("A Perl Compatible Regular Expressions Library")
add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}})
on_load(function (package)
local bitwidth = package:config("bitwidth") or "8"
package:add("links", "pcre2-" .. bitwidth)
package:add("defines", "PCRE2_CODE_UNIT_WIDTH=" .. bitwidth)
end)
在工程項目裏面,咱們也能夠查看特定包的可配置參數和值列表:
$ xmake require --info pcre2
The package info of project:
require(pcre2):
-> description: A Perl Compatible Regular Expressions Library
-> version: 10.31
...
-> configs:
-> bitwidth:
-> description: Set the code unit width.
-> values: {"8","16","32"}
-> default: 8
而後在項目裏面,啓用這些配置,編譯集成帶有特定配置的包:
add_requires("pcre2", {configs = {bitwidth = 16}})
on_load
這是個可選的接口,若是要更加靈活的動態判斷各類平臺架構,針對性作設置,能夠在這個裏面完成,例如:
on_load(function (package)
local bitwidth = package:config("bitwidth") or "8"
package:add("links", "pcre" .. (bitwidth ~= "8" and bitwidth or ""))
if not package:config("shared") then
package:add("defines", "PCRE_STATIC")
end
end)
pcre包須要作一些針對bitwidth的判斷,才能肯定對外輸出的連接庫名字,還須要針對動態庫增長一些defines導出,這個時候在on_load裏面設置,就更加靈活了。
on_install
這個接口主要用於添加安裝腳本,前面的字符串參數用於設置支持的平臺,像on_load, on_test等其餘腳本域也是一樣支持的。
平臺過濾
完整的過濾語法以下:plat|arch1,arch2@host|arch1,arch2
看上去很是的複雜,其實很簡單,其中每一個階段都是可選的,可部分省略,對應:編譯平臺|編譯架構@主機平臺|主機架構
若是不設置任何平臺過濾條件,那麼默認全平臺支持,裏面的腳本對全部平臺生效,例如:
on_install(function (package)
-- TODO
end)
若是安裝腳本對特定平臺生效,那麼直接指定對應的編譯平臺,能夠同時指定多個:
on_install("linux", "macosx", function (package)
-- TODO
end)
若是還要細分到指定架構才能生效,能夠這麼寫:
on_install("linux|x86_64", "iphoneos|arm64", function (package)
-- TODO
end)
若是還要限制執行的主機環境平臺和架構,能夠在後面追加@host|arch,例如:
on_install("mingw@windows", function (package)
-- TODO
end)
意思就是僅對windows下編譯mingw平臺生效。
咱們也能夠不指定比那一平臺和架構,僅設置主機平臺和架構,這一般用於描述一些跟編譯工具相關的依賴包,只能在主機環境運行。
例如,咱們編譯的包,依賴了cmake,須要添加cmake的包描述,那麼裏面編譯安裝環境,只能是主機平臺:
on_install("@windows", "@linux", "@macosx", function (package)
-- TODO
end)
其餘一些例子:
-- `@linux`
-- `@linux|x86_64`
-- `@macosx,linux`
-- `android@macosx,linux`
-- `android|armv7-a@macosx,linux`
-- `android|armv7-a@macosx,linux|x86_64`
-- `android|armv7-a@linux|x86_64`
編譯工具
咱們內置了一些安裝經常使用編譯工具腳本,用於針對不一樣源碼依賴的構建工具鏈,進行方便的構架支持,例如:autoconf, cmake, meson等,
xmake
若是是基於xmake的依賴包,那麼集成起來就很是簡單了,xmake對其作了很是好的內置集成支持,能夠直接對其進行跨平臺編譯支持,通常狀況下只須要:
on_install(function (package)
import("package.tools.xmake").install(package)
end)
若是要傳遞一些特有的編譯配置參數:
on_install(function (package)
import("package.tools.xmake").install(package, {"--xxx=y"})
end)
cmake
若是是基於cmake的包,集成起來也很簡答,一般也只須要設置一些配置參數便可,不過還須要先添加上cmake的依賴才行:
add_deps("cmake")
on_install(function (package)
import("package.tools.cmake").install(package, {"-Dxxx=ON"})
end)
autoconf
若是是基於autoconf的包,集成方式跟cmake相似,只是傳遞的配置參數不一樣而已,不過一般狀況下,unix系統都內置了autoconf系列工具,因此不加相關依賴也沒事。
on_install(function (package)
import("package.tools.autoconf").install(package, {"--enable-shared=no"})
end)
不過,有些源碼包用系統內置的autoconf可能不能徹底知足,那麼能夠加上autoconf系列依賴,對其進行構建:
add_deps("autoconf", "automake", "libtool", "pkg-config")
on_install(function (package)
import("package.tools.autoconf").install(package, {"--enable-shared=no"})
end)
meson
若是是meson,還須要加上ninja的依賴來執行構建才行。
add_deps("meson", "ninja")
on_install(function (package)
import("package.tools.meson").install(package, {"-Dxxx=ON"})
end)
on_test
安裝後,須要設置對應的測試腳本,執行一些測試,確保安裝包的可靠性,若是測試不經過,則會撤銷整個安裝包。
on_test(function (package)
assert(package:has_cfuncs("inflate", {includes = "zlib.h"}))
end)
上面的腳本調用包內置的has_cfuncs接口,檢測安裝後的包是否存在zlib.h頭文件,以及庫和頭文件裏面是否存在inflate這個接口函數。
xmake會去嘗試編譯連接來作測試,has_cfuncs用於檢測c函數,而has_cxxfuncs則能夠檢測c++庫函數。
而includes裏面能夠設置多個頭文件,例如:includes = {"xxx.h", "yyy.h"}
咱們還能夠傳遞一些本身的編譯參數進去檢測,例如:
on_test(function (package)
assert(package:has_cxxfuncs("func1", {includes = "xxx.h", configs = {defines = "c++14", cxflags = "-Dxxx"}}))
end)
咱們也能夠經過check_csnippets和check_cxxsnippets檢測一個代碼片斷:
on_test(function (package)
assert(package:check_cxxsnippets({test = [[
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <assert.h>
using namespace boost::algorithm;
using namespace std;
static void test() {
string str("a,b");
vector<string> strVec;
split(strVec, str, is_any_of(","));
assert(strVec.size()==2);
assert(strVec[0]=="a");
assert(strVec[1]=="b");
}
]]}, {configs = {languages = "c++14"}}))
end)
若是是可執行包,也能夠經過嘗試運行來檢測:
on_test(function (package)
os.run("xxx --help")
end)
若是運行失敗,那麼測試不會經過。
擴展配置參數
詳情見:add_configs
內置配置參數
除了能夠經過add_configs設置一些擴展的配置參數之外,xmake還提供了一些內置的配置參數,可使用
啓用調試包
add_requires("xxx", {debug = true})
包描述裏面必須有相關處理才能支持:
on_install(function (package)
local configs = {}
if package:debug() then
table.insert(configs, "--enable-debug")
end
import("package.tools.autoconf").install(package)
end)
設置msvc運行時庫
add_requires("xxx", {configs = {vs_runtime = "MT"}})
一般狀況下,經過import("package.tools.autoconf").install等內置工具腳本安裝的包,內部都對vs_runtime自動處理過了。
可是若是是一些特殊的源碼包,構建規則比較特殊,那麼須要本身處理了:
on_install(function (package)
io.gsub("build/Makefile.win32.common", "%-MD", "-" .. package:config("vs_runtime"))
end)
添加環境變量
對於一些庫,裏面也帶了可執行的工具,若是須要在集成包的時候,使用上這些工具,那麼也能夠設置上對應PATH環境變量:
package("luajit")
on_load(function (package)
if is_plat("windows") then
package:addenv("PATH", "lib")
end
package:addenv("PATH", "bin")
end)
而在項目工程中,只有經過add_packages集成對應的包後,對應的環境變量纔會生效。
add_requires("luajit")
target("test")
set_kind("binary")
add_packages("luajit")
after_run(function (package)
os.exec("luajit --version")
end)
安裝二進制包
xmake也是支持直接引用二進制版本包,直接安裝使用,例如:
if is_plat("windows") then
set_urls("https://www.libsdl.org/release/SDL2-devel-$(version)-VC.zip")
add_versions("2.0.8", "68505e1f7c16d8538e116405411205355a029dcf2df738dbbc768b2fe95d20fd")
end
on_install("windows", function (package)
os.cp("include", package:installdir())
os.cp("lib/$(arch)/*.lib", package:installdir("lib"))
os.cp("lib/$(arch)/*.dll", package:installdir("lib"))
end)
本地測試
若是在本地xmake-repo倉庫中,已經添加和製做好了新的包,能夠在本地運行測試下,是否經過,若是測試經過,便可提交pr到官方倉庫,請求merge。
咱們能夠執行下面的腳本進行測試指定包:
cd xmake-repo
xmake l scripts/test.lua -v -D zlib
上面的命令,會強制從新下載和安裝zlib包,測試整個安裝流程是否ok,加上-v -D是爲了能夠看到完整詳細的日誌信息和出錯信息,方便調試分析。
若是網絡環境很差,不想每次測試都去從新下載全部依賴,能夠加上--shallow參數來執行,這個參數告訴腳本,僅僅從新解壓本地緩存的zlib源碼包,從新執行安裝命令,但不會下載各類依賴。
cd xmake-repo
xmake l scripts/test.lua -v -D --shallow zlib
若是咱們想測試其餘平臺的包規則是否正常,好比: android, iphoneos等平臺,能夠經過-p/--plat或者-a/--arch來指定。
cd xmake-repo
xmake l scripts/test.lua -v -D --shallow -p iphoneos -a arm64 zlib
xmake l scripts/test.lua -v -D --shallow -p android --ndk=/xxxx zlib
提交包到官方倉庫
目前這個特性剛完成不久,目前官方倉庫的包還不是不少,有些包也許還不支持部分平臺,不過這並非太大問題,後期迭代幾個版本後,我會不斷擴充完善包倉庫。
若是你須要的包,當前的官方倉庫尚未收錄,能夠提交issues或者本身能夠在本地調通後,貢獻提交到官方倉庫:xmake-repo
詳細的貢獻說明,見:CONTRIBUTING.md
關於如何製做本身的包,能夠看下上文:添加包到倉庫。html