如何在 Meson 中執行 X?

此頁面列出常用任務的程式碼片段。這些程式碼片段主要使用 C 編譯器編寫,但相同的方法應適用於幾乎所有其他編譯器。

設定編譯器

首次執行 Meson 時,請在環境變數中設定它。

$ CC=mycc meson <options>

請注意,像 CC 這樣的環境變數僅在交叉編譯中參照主機平台。也就是說,CC 參照用於編譯將在我們最終安裝專案的機器上執行的程式之編譯器。用於建置在我們進行建置的機器上執行的程式之編譯器可以使用 CC_FOR_BUILD 指定。您可以在交叉編譯中使用它。

請注意,環境變數絕不是使用 Meson 執行任何操作的慣用方式。最好使用原生和交叉檔案。而且,只能使用交叉檔案指定交叉編譯中主機平台的工具。

這裡有一個支援的所有環境變數表:這裡

設定連結器

0.53.0 版新增功能

與編譯器類似,連結器是透過 <compiler variable>_LD 環境變數選取的,或是透過原生或交叉檔案中的 <compiler entry>_ld 項目選取的。您必須知道您使用的是會自行叫用連結器的編譯器(大多數編譯器,包括 GCC 和 Clang),還是直接叫用的連結器(當使用 MSVC 或像它的編譯器時,包括 Clang-Cl)。前者 c_ldCC_LD 應該是要傳遞給編譯器特殊引數的值(例如 clang 和 gcc 的 -fuse-ld),後者應該是可執行檔,例如 lld-link.exe

注意 在 Meson 0.53.0 中,使用了交叉/原生檔案中的 ld 項目和 LD 環境變數,這導致了大量的回歸,並在 0.53.1 中變更為 <lang>_ld<comp variable>_LD

$ CC=clang CC_LD=lld meson <options>

$ CC=clang-cl CC_LD=link meson <options>

或在交叉或原生檔案中

[binaries]
c = 'clang'
c_ld = 'lld'

這裡有一個支援的所有環境變數表:這裡

設定預設 C/C++ 語言版本

project('myproj', 'c', 'cpp',
        default_options : ['c_std=c11', 'cpp_std=c++11'])

語言版本也可以在每個目標的基礎上設定。

executable(..., override_options : ['c_std=c11'])

啟用執行緒

很多人似乎使用 cc.find_library('pthread') 或類似的東西來手動執行此操作。請勿這麼做。它不具可攜性。請改為執行此操作。

thread_dep = dependency('threads')
executable(..., dependencies : thread_dep)

從外部設定額外的編譯器和連結器標誌(例如,在建置發行套件時)

其行為與其他建置系統相同,在第一次叫用時使用環境變數。當您需要重建原始碼時,請勿使用這些變數

$ CFLAGS=-fsomething LDFLAGS=-Wl,--linker-flag meson <options>

僅對特定編譯器使用引數

首先檢查要使用哪些引數。

if meson.get_compiler('c').get_id() == 'clang'
  extra_args = ['-fclang-flag']
else
  extra_args = []
endif

然後在目標中使用它。

executable(..., c_args : extra_args)

如果您想在所有目標上使用這些引數,請執行此操作。

if meson.get_compiler('c').get_id() == 'clang'
  add_global_arguments('-fclang-flag', language : 'c')
endif

將命令的輸出設定為組態設定

txt = run_command('script', 'argument', check: true).stdout().strip()
cdata = configuration_data()
cdata.set('SOMETHING', txt)
configure_file(...)

從檔案產生組態設定資料

fs 模組 提供 read 函式,可讓您將任意檔案的內容新增至組態設定資料(以及其他用途)

fs = import('fs')
cdata = configuration_data()
copyright = fs.read('LICENSE')
cdata.set('COPYRIGHT', copyright)
if build_machine.system() == 'linux'
    os_release = fs.read('/etc/os-release')
    cdata.set('LINUX_BUILDER', os_release)
endif
configure_file(...)

使用 configure_file 產生可執行的腳本

configure_file 會保留中繼資料,因此如果您的範本檔案具有執行權限,則產生的檔案也會具有這些權限。

產生涵蓋率報告

首先使用此命令初始化建置目錄。

$ meson setup <other flags> -Db_coverage=true

然後發出下列命令。

$ meson compile
$ meson test
$ ninja coverage-html (or coverage-xml)

涵蓋率報告可以在 meson-logs 子目錄中找到。

0.55.0 版新增功能 llvm-cov 支援與 clang 搭配使用

為偵錯組建新增一些最佳化

預設情況下,偵錯組建不會使用任何最佳化。這是大多數情況下所需的做法。但是,有些專案受益於啟用一些次要最佳化。GCC 甚至有一個特定的編譯器標誌 -Og 來執行此操作。若要啟用其使用,只需發出下列命令。

$ meson configure -Dc_args=-Og

這會導致所有後續組建使用此命令列引數。

使用位址清理工具

Clang 和 gcc 隨附了一系列分析工具,例如 位址清理工具。Meson 使用 b_sanitize 選項對這些工具提供原生支援。

$ meson setup <other options> -Db_sanitize=address

在此之後,您只需編譯程式碼並執行測試套件。位址清理工具將中止有錯誤的可執行檔,因此它們會顯示為測試失敗。

使用 Clang 靜態分析工具

安裝 scan-build 程式,然後執行此操作

$ meson setup builddir
$ ninja -C builddir scan-build

您可以使用 SCANBUILD 環境變數來選擇 scan-build 可執行檔。

$ SCANBUILD=<your exe> ninja -C builddir scan-build

您可以使用它來將引數傳遞給 scan-build 程式,方法是建立一個腳本,例如

#!/bin/sh
scan-build -v --status-bugs "$@"

然後透過變數傳遞它(記得使用絕對路徑)

$ SCANBUILD=$(pwd)/my-scan-build.sh ninja -C builddir scan-build

使用設定檔引導最佳化

使用 GCC 的設定檔引導最佳化是分為兩個階段的操作。首先,我們使用已啟用的設定檔測量來設定專案並編譯它。

$ meson setup <Meson options, such as --buildtype=debugoptimized> -Db_pgo=generate
$ meson compile -C builddir

然後,我們需要使用一些代表性輸入來執行程式。此步驟取決於您的專案。

完成後,我們會變更編譯器標誌以使用產生的資訊並重建。

$ meson configure -Db_pgo=use
$ meson compile

完成這些步驟後,產生的二進位檔將完全最佳化。

可移植地新增數學程式庫 (-lm)

有些平台(例如 Linux)具有獨立的數學程式庫。其他平台(幾乎所有其他平台)則沒有。如何指定僅在需要時才使用 m

cc = meson.get_compiler('c')
m_dep = cc.find_library('m', required : false)
executable(..., dependencies : m_dep)

將可執行檔安裝到 libexecdir

executable(..., install : true, install_dir : get_option('libexecdir'))

使用現有的 Find<name>.cmake 檔案

如果安裝了 CMake,Meson 可以使用 CMake find_package() 生態系統。若要使用自訂 Find<name>.cmake 尋找依賴性,請將 cmake_module_path 屬性設定為專案中儲存 CMake 腳本的路徑。

cmake 子目錄中尋找 FindCmakeOnlyDep.cmake 的範例

cm_dep = dependency('CmakeOnlyDep', cmake_module_path : 'cmake')

cmake_module_path 屬性僅適用於自訂 CMake 腳本。系統範圍的 CMake 腳本會自動找到。

如需詳細資訊,請參閱這裡

取得預設的找不到依賴性?

null_dep = dependency('', required : false)

這可用於您想要預設值,但稍後可能會覆寫它的情況。

# Not needed on Windows!
my_dep = dependency('', required : false)
if host_machine.system() in ['freebsd', 'netbsd', 'openbsd', 'dragonfly']
  my_dep = dependency('some dep', required : false)
elif host_machine.system() == 'linux'
  my_dep = dependency('some other dep', required : false)
endif

executable(
  'myexe',
  my_sources,
  deps : [my_dep]
)

從整合建置中排除檔案

如果您的專案支援整合建置,您應該修復在將原始碼檔案串連在一起時出現的任何錯誤。不過,有時這是不可行的,例如,如果原始碼檔案是產生的。

在這種情況下,您可以將它們放在個別的靜態程式庫建置目標中,並覆寫整合設定。

generated_files = ...
unityproof_lib = static_library('unityproof', generated_files,
  override_options : ['unity=off'])

main_exe = executable('main', main_sources, link_with : unityproof_lib)

若要將靜態程式庫連結到另一個程式庫目標,您可能需要使用 link_whole 而不是 link_with

搜尋結果為