Wrap 依賴系統手冊
跨平台開發的主要問題之一,就是處理所有依賴項。這在許多平台上都很麻煩,尤其是在沒有內建套件管理員的平台上。後者問題的解決方案是使用第三方套件管理員。但它們並非最終用戶部署的真正解決方案,因為你不能要求他們為了使用你的應用程式而安裝套件管理員。在這些平台上,你必須產生自我包含的應用程式。當目標平台缺少你的應用程式的依賴項(或最新版本)時,情況也是如此。
傳統的方法是將依賴項捆綁到你自己的專案中。可以是預先建置的程式庫和標頭,也可以將原始碼嵌入到你的原始碼樹中,並重新編寫你的建構系統,將它們建構成你專案的一部分。
這既繁瑣又容易出錯,因為它總是手工完成的。Meson 的 Wrap 依賴系統旨在提供一種自動化的方法來做到這一點。
運作方式
Meson 有子專案的概念。它們是一種將一個 Meson 專案嵌套在另一個專案中的方法。任何使用 Meson 建構的專案都可以檢測到它是作為子專案建構的,並以使其易於使用的方式建構自身(通常這意味著作為靜態程式庫)。
要使用這種專案作為依賴項,你只需將其複製並解壓縮到你專案的 subprojects
目錄中。
但是,有一種更簡單的方法。你可以指定一個 Wrap 檔案,告訴 Meson 如何為你下載它。如果你隨後在你的建構中使用這個子專案,Meson 將在建構期間自動下載並解壓縮它。這使得子專案嵌入變得非常容易。
所有 wrap 檔案都必須具有 <project_name>.wrap
形式的名稱,並且位於 subprojects
目錄中。
目前 Meson 有四種類型的 wrap
- wrap-file
- wrap-git
- wrap-hg
- wrap-svn
wrap 格式
Wrap 檔案以 ini 格式編寫,包含一個標頭,其中包含 wrap 的類型,後接描述如何獲取原始碼、驗證它們以及在需要時修改它們的屬性。名為 libfoobar
的 wrap 的範例 wrap-file 將具有檔案名稱 libfoobar.wrap
,並且看起來像這樣
[wrap-file]
directory = libfoobar-1.0
source_url = https://example.com/foobar-1.0.tar.gz
source_filename = foobar-1.0.tar.gz
source_hash = 5ebeea0dfb75d090ea0e7ff84799b2a7a1550db3fe61eb5f6f61c2e971e57663
範例 wrap-git 將看起來像這樣
[wrap-git]
url = https://github.com/libfoobar/libfoobar.git
revision = head
depth = 1
wrap 可接受的組態屬性
-
directory
- 子專案根目錄的名稱,預設為 wrap 的名稱。
自 0.55.0 版起,這些屬性可用於所有 wrap 類型,之前僅保留給 wrap-file
-
patch_url
- 下載 URL 以檢索可選的覆蓋封存檔 -
patch_fallback_url
- 從patch_url
下載失敗時使用的備用 URL 自:0.55.0 -
patch_filename
- 已下載覆蓋封存檔的檔案名稱 -
patch_hash
- 已下載覆蓋封存檔的 sha256 總和檢查碼 -
patch_directory
- 自 0.55.0 起 覆蓋目錄,如果檔案是本地檔案而不是下載的封存檔,則為patch_filename
的替代方案。目錄必須放在subprojects/packagefiles
中。 -
diff_files
- 自 0.63.0 起 以逗號分隔的本地差異檔案清單(請參閱下方的 差異檔案)。 -
method
- 自 1.3.0 起 此子專案使用的建構系統。預設為meson
。支援的方法
特定於 wrap-file
-
source_url
- 下載 URL 以檢索 wrap-file 原始碼封存檔 -
source_fallback_url
- 從source_url
下載失敗時使用的備用 URL 自:0.55.0 -
source_filename
- 已下載原始碼封存檔的檔案名稱 -
source_hash
- 已下載原始碼封存檔的 sha256 總和檢查碼 -
lead_directory_missing
- 對於wrap-file
,建立前置目錄名稱。當原始碼檔案沒有前置目錄時需要此項。
自 0.55.0 版起,可以在 .wrap 檔案中僅使用 source_filename
和 patch_filename
值(沒有 source_url
和 patch_url
)來指定 subprojects/packagefiles
目錄中的本機封存檔。使用此方法時,*_hash
條目是選用的。此方法應優先於以下描述的舊版 packagecache
方法。
自 0.49.0 版起,如果在專案的 subprojects/packagecache
目錄中找到 source_filename
或 patch_filename
,即使 --wrap-mode
選項設定為 nodownload
,也會使用它,而不會下載檔案。將會檢查檔案的雜湊值。
自 1.3.0 版起,如果設定了 MESON_PACKAGE_CACHE_DIR
環境變數,則會使用它來代替專案的 subprojects/packagecache
。這允許在多個專案之間共用快取。此外,它還可以包含已解壓縮的原始碼樹,只要它的目錄名稱與 wrap 檔案中的 directory
欄位相同。在這種情況下,將在應用修補程式之前,將目錄複製到 subprojects/
中。
特定於基於 VCS 的 wrap
-
url
- 要複製的 wrap-git 儲存庫名稱。必填。 -
revision
- 要簽出的修訂名稱。必須是:VCS 的checkout
命令的有效值(例如 git 標籤),或是(對於 git)head
以追蹤上游的預設分支。必填。
特定於 wrap-git
-
depth
- 將儲存庫淺層複製到 X 個 commit。這可以節省頻寬和磁碟空間,通常應該始終指定,除非需要 commit 歷史記錄。請注意,git 始終允許淺層複製分支,但是為了淺層複製 commit id,伺服器必須支援uploadpack.allowReachableSHA1InWant=true
。(自 0.52.0 起) -
push-url
- 設定為 git 推送 URL 的替代 URL。如果將開發子專案並將變更推送到上游,則很有用。(自 0.37.0 起) -
clone-recursive
- 也複製儲存庫的子模組 (自 0.48.0 起)
具有 Meson 建構修補程式的 wrap-file
不幸的是,世界上大多數軟體專案都不是使用 Meson 建構的。因此,Meson 允許你指定修補程式 URL。
由於歷史原因,這稱為「修補程式」,但是,它的作用是覆蓋來新增或取代檔案,而不是修改它們。檔案必須是封存檔;它會被下載並自動解壓縮到子專案中。解壓縮的檔案將包含給定子專案的 Meson 建構定義。
這種方法可以非常簡單地嵌入需要建構系統變更的依賴項。你可以在完全隔離的情況下為依賴項編寫 Meson 建構定義。這比在你自己的原始碼樹中執行此操作要好得多,尤其是在它包含數十萬行程式碼的情況下。一旦你有了可用的建構定義,只需將 Meson 建構檔案(以及你已變更的其他檔案)壓縮起來,並將它們放在你可以下載它們的位置。
在 0.55.0 之前,Meson 建構修補程式僅支援 wrap-file 模式。使用 wrap-git 時,儲存庫必須包含所有 Meson 建構定義。自 0.55.0 起,任何 wrap 模式(包括 wrap-git)都支援 Meson 建構修補程式。
差異檔案
自:0.63.0
你也可以提供 diff
格式的本機修補程式檔案。由於歷史原因,它們被稱為「差異檔案」,因為「修補程式」名稱已用於覆蓋封存檔。
差異檔案由 diff_files
屬性(以逗號分隔的清單)描述,並且必須在本機的 subprojects/packagefiles
目錄中可用。
Meson 將在解壓縮或複製專案後,以及在應用覆蓋封存檔 (patch_*
) 後,應用差異檔案。對於此功能,必須提供 patch
或 git
命令列工具。
將以 -p1
應用差異檔案,也就是說,將第一個路徑元件視為要剝離的前置詞。這是 Git 產生的差異的預設值。
[wrap-file]
directory = libfoobar-1.0
source_url = https://example.com/foobar-1.0.tar.gz
source_filename = foobar-1.0.tar.gz
source_hash = 5ebeea0dfb75d090ea0e7ff84799b2a7a1550db3fe61eb5f6f61c2e971e57663
diff_files = libfoobar-1.0/0001.patch, libfoobar-1.0/0002.patch
provide
區段
*自 0.55.0 起
Wrap 檔案可以在 [provide]
區段中定義它提供的依賴項。
[provide]
dependency_names = foo-1.0
當 wrap 檔案如上所示提供依賴項 foo-1.0
時,即使未給出 fallback
關鍵字引數,任何對 dependency('foo-1.0')
的呼叫都會自動回復到該子專案。即使缺少 [provide]
區段,名為 foo.wrap
的 wrap 檔案也會隱式提供依賴項名稱 foo
。
選用依賴項,例如 dependency('foo-1.0', required: get_option('foo_opt'))
(其中 foo_opt
是設定為 auto
的功能選項),基於兩個原因,不會回復到 wrap 檔案中定義的子專案
- 它允許首先以其他方式尋找依賴項,例如使用
cc.find_library('foo')
,並且僅在失敗時才回復
# this won't use fallback defined in foo.wrap
foo_dep = dependency('foo-1.0', required: false)
if not foo_dep.found()
foo_dep = cc.find_library('foo', has_headers: 'foo.h', required: false)
if not foo_dep.found()
# This will use the fallback
foo_dep = dependency('foo-1.0')
# or
foo_dep = dependency('foo-1.0', required: false, fallback: 'foo')
endif
endif
- 有時,當使用者未明確要求該功能時,找不到依賴項比回復更好。在這種情況下,只有在使用者將
foo_opt
設定為enabled
而不是auto
時,dependency('foo-1.0', required: get_option('foo_opt'))
才會回復。自 0.58.0 起,如果wrap_mode
設定為forcefallback
或force_fallback_for
包含子專案,則如上所示的選用依賴項將回復到 wrap 檔案中定義的子專案。
如果希望回復選用依賴項,則必須明確傳遞 fallback
或 allow_fallback
關鍵字引數。自 0.56.0 起,即使 foo_opt
設定為 auto
,dependency('foo-1.0', required: get_option('foo_opt'), allow_fallback: true)
也會使用回復。在 0.55.0 版中,可以使用 dependency('foo-1.0', required: get_option('foo_opt'), fallback: 'foo')
達到相同的效果。
此機制假設子專案呼叫 meson.override_dependency('foo-1.0', foo_dep)
,以便 Meson 知道應該使用哪個依賴項物件作為回復。由於該方法是在 0.54.0 版中引入的,因此為了過渡期,對於尚未使用該方法的專案,可以在 wrap 檔案中使用 foo-1.0 = foo_dep
格式的條目來提供變數名稱。
例如,當使用足夠新版本的 glib(使用 meson.override_dependency()
來覆寫 glib-2.0
、gobject-2.0
和 gio-2.0
)時,wrap 檔案將如下所示
[wrap-git]
url=https://gitlab.gnome.org/GNOME/glib.git
revision=glib-2-62
depth=1
[provide]
dependency_names = glib-2.0, gobject-2.0, gio-2.0
對於較舊版本的 glib,需要指定依賴項變數名稱
[wrap-git]
url=https://gitlab.gnome.org/GNOME/glib.git
revision=glib-2-62
depth=1
[provide]
glib-2.0=glib_dep
gobject-2.0=gobject_dep
gio-2.0=gio_dep
程式也可以由 wrap 檔案提供,使用 program_names
鍵
[provide]
program_names = myprog, otherprog
使用這樣的 wrap 檔案,find_program('myprog')
將自動回復為使用子專案,假設它使用 meson.override_find_program('myprog')
。
CMake wrap
注意:這是實驗性的,沒有向後或向前相容性保證。請參閱Meson 關於混合建構系統的規則。
由於 CMake 模組不知道所提供依賴項的公開名稱,因此 CMake .wrap
檔案無法使用 dependency_names = foo
語法。相反,應使用 dep_name = <target_name>_dep
語法,其中 <target_name>
是 CMake 程式庫的名稱,其中所有非字母數字字元都替換為底線 _
。
舉例來說,一個 CMake 專案在其 CMakeList.txt
中包含 add_library(foo-bar ...)
,且應用程式通常會使用依賴名稱 foo-bar-1.0
(例如透過 pkg-config) 來找到它,則其包裝檔會像這樣:
[wrap-file]
...
method = cmake
[provide]
foo-bar-1.0 = foo_bar_dep
Cargo 包裝
注意:這是實驗性的,沒有向後或向前相容性保證。請參閱Meson 關於混合建構系統的規則。
Cargo 子專案會自動覆寫 <package_name>-<version>-rs
依賴名稱
-
package_name
定義在Cargo.toml
的[package] name = ...
區段中。 -
version
是從[package] version = ...
推導出的 API 版本,規則如下:-
x.y.z
-> 'x' -
0.x.y
-> '0.x' -
0.0.x
-> '0' 這允許為同一個 crate 的不相容版本建立不同的依賴。
-
-
-rs
後綴是用來區分一般系統依賴,例如gstreamer-1.0
是一個系統 pkg-config 依賴,而gstreamer-0.22-rs
則是一個 Cargo 依賴。
這表示當 Cargo.toml
的套件名稱為 foo
且版本為 1.2
時,.wrap
檔案的 [provide]
區段應該包含 dependency_names = foo-1-rs
。
請注意,版本組件是在 Meson 1.4 中加入的,先前的版本使用的是 <package_name>-rs
格式。
Cargo 子專案需要一個 toml 解析器。Python >= 3.11 內建了這個解析器,較舊的 Python 版本則需要外部的 tomli
模組或 toml2json
程式。
舉例來說,一個套件名稱為 foo-bar
的 Cargo 專案會擁有像這樣的包裝檔:
[wrap-file]
...
method = cargo
[provide]
dependency_names = foo-bar-0.1-rs
此外,如果存在 meson/meson.build
檔案,Meson 會呼叫 subdir('meson')
,專案可以在其中加入通常屬於 build.rs
的手動邏輯。有一些命名慣例需要遵守
extra_args
變數是預先定義好的,可以用來新增任何 Rust 引數。這通常被用作extra_args += ['--cfg', 'foo']
。extra_deps
變數是預先定義好的,可以用來新增額外的依賴。這通常被用作extra_deps += dependency('foo')
。
自 1.5.0 版起,Cargo 包裝也可以在 (子)專案原始碼樹的根目錄中提供 Cargo.lock
檔案。Meson 會自動載入該檔案並將其轉換為一系列的包裝定義。
使用包裝專案
包裝提供了一種方便的方式,將專案取得至您的子專案目錄中。然後,您可以像使用常規的子專案一樣使用它 (請參閱 子專案)。
取得包裝
通常您不會想手動撰寫包裝檔。
有一個名為 WrapDB 的線上儲存庫,提供了許多現成的依賴可以使用。您可以在這裡閱讀更多關於 WrapDB 的資訊。
Meson 也有一個子指令可以用來取得和管理包裝 (請參閱 使用 wraptool)。
搜尋結果如下