Xmake v2.8.6 發佈,新的打包插件:XPack

Xmake 是一個基於 Lua 的輕量級跨平臺構建工具。

它非常的輕量,沒有任何依賴,因爲它內置了 Lua 運行時。

它使用 xmake.lua 維護項目構建,相比 makefile/CMakeLists.txt,配置語法更加簡潔直觀,對新手非常友好,短時間內就能快速入門,能夠讓用戶把更多的精力集中在實際的項目開發上。

我們能夠使用它像 Make/Ninja 那樣可以直接編譯項目,也可以像 CMake/Meson 那樣生成工程文件,另外它還有內置的包管理系統來幫助用戶解決 C/C++ 依賴庫的集成使用問題。

目前,Xmake 主要用於 C/C++ 項目的構建,但是同時也支持其他 native 語言的構建,可以實現跟 C/C++ 進行混合編譯,同時編譯速度也是非常的快,可以跟 Ninja 持平。

Xmake = Build backend + Project Generator + Package Manager + [Remote|Distributed] Build + Cache

儘管不是很準確,但我們還是可以把 Xmake 按下面的方式來理解:

Xmake ≈ Make/Ninja + CMake/Meson + Vcpkg/Conan + distcc + ccache/sccache

新特性介紹

在介紹新特性之前,還有個好消息告訴大家,上個版本 Xmake 被收入到了 debian 倉庫,而最近 Xmake 又進入了 Fedora 官方倉庫,大家可以在 Fedora 39 上,直接通過下面的命令安裝 Xmake。

$ sudo dnf install xmake

非常感謝 @topazus @mochaaP 對 Xmake 的貢獻,相關信息見:#941

接下來,我們來介紹下,新版本帶來的重量級特性:XPack。

它類似於 CMake 的 CPack 命令,可以將用戶工程快速打包生成各種格式的安裝包。

目前 Xmake 的 XPack 已經支持以下格式的打包:

  • nsis: Windows 下的可執行安裝包
  • runself: shell 自編譯安裝包
  • targz: 二進制文件 tar.gz 包(綠色版)
  • zip: 二進制文件 zip 包(綠色版)
  • srctargz:源文件 tar.gz 包
  • srczip: 源文件 zip 包
  • srpm: rpm 源碼安裝包
  • rpm: rpm 二進制安裝包

除了上述已經支持的打包格式,還有 deb 等包格式也在陸續支持中,並且用戶也可以配置生成自定義的包格式文件。

XPack 打包

下面是一個完整例子,我們可以先簡單看下:

set_version("1.0.0")
add_rules("mode.debug", "mode.release")

includes("@builtin/xpack")

target("test")
    set_kind("binary")
    add_files("src/*.cpp")

xpack("test")
    set_formats("nsis", "zip", "targz", "runself")
    set_title("hello")
    set_author("ruki")
    set_description("A test installer.")
    set_homepage("https://xmake.io")
    set_licensefile("LICENSE.md")
    add_targets("test")
    add_installfiles("src/(assets/*.png)", {prefixdir = "images"})
    add_sourcefiles("(src/**)")
    set_iconfile("src/assets/xmake.ico")

    after_installcmd(function (package, batchcmds)
        batchcmds:mkdir(package:installdir("resources"))
        batchcmds:cp("src/assets/*.txt", package:installdir("resources"), {rootdir = "src"})
        batchcmds:mkdir(package:installdir("stub"))
    end)

    after_uninstallcmd(function (package, batchcmds)
        batchcmds:rmdir(package:installdir("resources"))
        batchcmds:rmdir(package:installdir("stub"))
    end)

我們通過 includes("@builtin/xpack") 引入 xpack 的所有配置接口,包括 xpack 配置域,以及它的所有域接口。

然後我們執行:

$ xmake pack

即可生成所有安裝包。

生成 NSIS 安裝包

只要配置了 set_formats("nsis") 格式,然後執行 xmake pack 命令,就能生成 NSIS 格式的安裝包。

另外,xmake 還會自動安裝生成 NSIS 包所需的工具,實現真正的一鍵打包。

$ xmake pack
note: install or modify (m) these packages (pass -y to skip confirm)?
in xmake-repo:
  -> nsis 3.09
please input: y (y/n/m)

  => install nsis 3.09 .. ok

[ 25%]: compiling.release src\main.cpp
[ 37%]: compiling.release src\main.cpp
[ 50%]: linking.release foo.dll
[ 62%]: linking.release test.exe
packing build\xpack\test\test-windows-x64-v1.0.0.exe
pack ok

test-windows-x64-v1.0.0.exe 就是我們生成的安裝包,雙擊運行它,就能安裝我們的二進制文件到指定目錄。



增加組件安裝

我們還可以給 NSIS 增加組件安裝命令,只有當用戶選擇指定組件的時候,它的安裝命令纔會被執行。

xpack("test")
    add_components("LongPath")

xpack_component("LongPath")
    set_default(false)
    set_title("Enable Long Path")
    set_description("Increases the maximum path length limit, up to 32,767 characters (before 256).")
    on_installcmd(function (component, batchcmds)
        batchcmds:rawcmd("nsis", [[
  ${If} $NoAdmin == "false"
    ; Enable long path
    WriteRegDWORD ${HKLM} "SYSTEM\CurrentControlSet\Control\FileSystem" "LongPathsEnabled" 1
  ${EndIf}]])
    end)

這個例子中,我們在裏面添加了一個 NSIS 特有的自定義命令,去實現對長路徑的支持。

生成自安裝包

我們也可以生成基於 shell 腳本的自編譯安裝包。我們需要配置 runself 打包格式,然後通過 add_sourcefiles 添加需要參與編譯安裝的源文件。

接着,我們需要自定義 on_installcmd 安裝腳本,裏面去配置如果編譯源碼包,我們可以簡單的調用一個內置的編譯安裝腳本文件,也可以直接配置 make install 等編譯安裝命令。

例如:

xpack("test")
    set_formats("runself")
    add_sourcefiles("(src/**)")
    on_installcmd(function (package, batchcmds)
        batchcmds:runv("make", {"install"})
    end)

然後,我們執行 xmake pack 命令,就可以生成一個自安裝的 xxx.gz.run 包,默認採用 gzip 壓縮。

$ xmake pack
packing build/xpack/test/test-macosx-src-v1.0.0.gz.run
pack ok

我們可以使用 sh 去加載運行它來安裝我們的程序。

$ sh ./build/xpack/test/test-macosx-src-v1.0.0.gz.run

我們也可以看一個比較完整的例子:

xpack("xmakesrc")
    set_formats("runself")
    set_basename("xmake-v$(version)")
    set_prefixdir("xmake-$(version)")
    before_package(function (package)
        import("devel.git")

        local rootdir = path.join(os.tmpfile(package:basename()) .. ".dir", "repo")
        if not os.isdir(rootdir) then
            os.tryrm(rootdir)
            os.cp(path.directory(os.projectdir()), rootdir)

            git.clean({repodir = rootdir, force = true, all = true})
            git.reset({repodir = rootdir, hard = true})
            if os.isfile(path.join(rootdir, ".gitmodules")) then
                git.submodule.clean({repodir = rootdir, force = true, all = true})
                git.submodule.reset({repodir = rootdir, hard = true})
            end
        end

        local extraconf = {rootdir = rootdir}
        package:add("sourcefiles", path.join(rootdir, "core/**|src/pdcurses/**|src/luajit/**|src/tbox/tbox/src/demo/**"), extraconf)
        package:add("sourcefiles", path.join(rootdir, "xmake/**"), extraconf)
        package:add("sourcefiles", path.join(rootdir, "*.md"), extraconf)
        package:add("sourcefiles", path.join(rootdir, "configure"), extraconf)
        package:add("sourcefiles", path.join(rootdir, "scripts/*.sh"), extraconf)
        package:add("sourcefiles", path.join(rootdir, "scripts/man/**"), extraconf)
        package:add("sourcefiles", path.join(rootdir, "scripts/debian/**"), extraconf)
        package:add("sourcefiles", path.join(rootdir, "scripts/msys/**"), extraconf)
    end)

    on_installcmd(function (package, batchcmds)
        batchcmds:runv("./scripts/get.sh", {"__local__"})
    end)

它是 xmake 自身源碼的安裝包配置腳本,更完整的配置可以參考:xpack.lua

這裏,它通過調用源碼包內置的 ./scripts/get.sh 安裝腳本去執行編譯安裝。

生成源碼歸檔包

另外,我們也可以配置 srczipsrctargz 格式,來生成源碼壓縮包,它不是完整的安裝包,也沒有安裝命令,僅僅用於源碼包分發。

xpack("test")
    set_formats("srczip", "srctargz")
    add_sourcefiles("(src/**)")
$ xmake pack
packing build/xpack/test/test-macosx-src-v1.0.0.zip ..
packing build/xpack/test/test-macosx-src-v1.0.0.tar.gz ..
pack ok

生成二進制歸檔包

我們也可以配置 ziptargz 來生成二進制的壓縮包,它會先自動編譯所有綁定的 target 目標程序,將所有需要的二進制程序,庫文件打包到 zip/tar.gz 格式。

這通常用於製作綠色版的安裝包,內部不太任何自動安裝腳本,用戶需要自己設置 PATH 等環境變量。

xpack("test")
    set_formats("zip", "targz")
    add_installfiles("(src/**)")
$ xmake pack
packing build/xpack/test/test-macosx-v1.0.0.zip ..
packing build/xpack/test/test-macosx-v1.0.0.tar.gz ..
pack ok

!> 需要注意的是,打二進制文件到包裏,使用的是 add_installfiles 而不是 add_sourcefiles

我們也可以通過 add_targets 去綁定需要安裝的 target 目標程序和庫。更多詳情見下面關於 add_targets 的接口描述。

生成 SRPM 源碼安裝包

它可以生成 .src.rpm 格式的源碼安裝包。

我們可以通過配置 add_targets 關聯需要構建的目標,在生成的 srpm 包中,它會自動調用 xmake buildxmake install 去構建和安裝包。

xpack("test")
    set_homepage("https://xmake.io")
    set_license("Apache-2.0")
    set_description("A cross-platform build utility based on Lua.")

    set_formats("srpm")
    add_sourcefiles("(src/**)")
    add_sourcefiles("./xmake.lua")

    add_targets("demo")

它會生成類似下面的 spec 文件,然後自動調用 rpmbuild 去生成 .src.rpm 包。

Name:       test
Version:    1.0.0
Release:    1%{?dist}
Summary:    hello

License:    Apache-2.0
URL:        https://xmake.io
Source0:    test-linux-src-v1.0.0.tar.gz

BuildRequires: xmake
BuildRequires: gcc
BuildRequires: gcc-c++

%description
A test installer.

%prep
%autosetup -n test-1.0.0 -p1

%build
xmake build -y test

%install
xmake install -o %{buildroot}/%{_exec_prefix} test
cd %{buildroot}
find . -type f | sed 's!^\./!/!' > %{_builddir}/_installedfiles.txt

%check

%files -f %{_builddir}/_installedfiles.txt

%changelog
* Fri Dec 22 2023 ruki - 1.0.0-1
- Update to 1.0.0

我們也可以通過 on_buildcmdon_installcmd 自定義構建和安裝腳本。

xpack("test")
    set_homepage("https://xmake.io")
    set_license("Apache-2.0")
    set_description("A cross-platform build utility based on Lua.")

    set_formats("srpm")
    add_sourcefiles("(src/**)")
    add_sourcefiles("./configure")

    on_buildcmd(function (package, batchcmds)
        batchcmds:runv("./configure")
        batchcmds:runv("make")
    end)

    on_installcmd(function (package, batchcmds)
        batchcmds:runv("make", {"install", "PREFIX=%{buildroot}"})
    end)

生成 RPM 二進制安裝包

RPM 包將會直接生成編譯好的二進制安裝包。xmake 會自動調用 rpmbuild --rebuild 命令去構建 SRPM 包生成它。

而在 XPack 中,我們僅僅只需要配置 set_formats("rpm") 即可支持 rpm 包生成,其他配置與 srpm 包完全一致。

xpack("test")
    set_formats("rpm")
    -- TODO

打包命令參數

指定打包格式

如果我們在配置文件中已經使用 set_formats 配置了多個打包格式,那麼默認情況下,xmake pack 會自動生成所有這些格式的包。

當然,我們也可以通過 xmake pack --formats=nsis,targz 來選擇性指定當前需要打哪些格式的包。

修改打包文件名

我們可以在配置文件中,通過 set_basename() 來修改包名,也可以通過命令行去修改它。

$ xmake pack --basename="foo"
packing build/xpack/test/foo.zip ..
pack ok

指定輸出目錄

默認的輸出目錄是在 build 目錄下,但我們也可以修改輸出的路徑。

$ xmake pack -o /tmp/output

禁用自動構建

如果是打 NSIS 等二進制包,xmake pack 會先自動編譯所有被綁定的 target 目標文件,然後再去執行打包邏輯。

但是如果我們已經編譯過了,不想每次都去編譯它,而是直接去打包,可以通過下面的參數禁用自動構建。

$ xmake pack --autobuild=n

接口描述

更多 XPack 打包接口描述見:XPack 打包接口文檔

安裝包到本地

默認情況先,通過 add_requires("xxx") 配置的包都會被安裝到全局目錄,不同項目共用這些包。

而新版本中,我們新增了一個 package.install_locally 策略,可以配置讓 xmake 將包安裝到當前本地項目目錄。

set_policy("package.install_locally", true)

更新日誌

新特性

  • 添加 network.mode 策略
  • #1433: 添加 xmake pack 命令去生成 NSIS/zip/tar.gz/srpm/rpm/runself 安裝包
  • #4435: 爲 UnityBuild 的組模式增加 batchsize 支持
  • #4485: 新增 package.install_locally 策略支持
  • 新增 NetBSD 支持

Changes

  • #4484: 改進 swig 規則
  • 改進 Haiku 支持

Bugs 修復

  • #4372: 修復 protobuf 規則
  • #4439: 修復 asn1c 規則
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章