サブプロジェクト

一部のプラットフォームでは、ネイティブなパッケージングシステムが提供されていません。このような場合、すべてのサードパーティライブラリをソースツリーにバンドルするのが一般的です。これは通常、バンドルされたライブラリを禁止するLinuxディストリビューションなどにこのようなプロジェクトを追加することを困難にするため、好ましくないとされています。

Mesonは、両方を同時に非常に簡単に提供できるようにすることで、この問題を解決しようとしています。この方法は、Mesonを使用すると、他のMesonプロジェクトを、そのMeson設定を変更することなく(最良の場合)、ビルドの一部にできるというものです。それはプロジェクトの透過的な一部になります。

これは、Mesonでビルドされたサブプロジェクトでのみ動作することが保証されていることに注意してください。その理由は、混合ビルドシステムでこれを確実に行う方法がないという単純な事実です。このため、ここではMesonサブプロジェクトのみについて説明します。 CMakeベースのサブプロジェクトもサポートされていますが、動作は保証されていません。

サブプロジェクトの例

通常、依存関係はいくつかのヘッダーファイルとリンクするライブラリで構成されます。この内部依存関係を宣言するには、declare_dependency関数を使用します。

例として、共有ライブラリを提供する単純なプロジェクトがあると仮定します。そのmeson.buildは次のようになります。

project('libsimple', 'c')

inc = include_directories('include')
libsimple = shared_library('simple',
  'simple.c',
  include_directories : inc,
  install : true)

libsimple_dep = declare_dependency(include_directories : inc,
  link_with : libsimple)

依存関係変数の命名規則

理想的には、依存関係変数名は<project_name>_depの形式にする必要があります。これにより、サブプロジェクトのビルド定義の中を見なくてもそのまま使用できます。

複数の依存関係を宣言する必要がある場合、デフォルトの依存関係は<project_name>_dep(例:gtest_dep)と名付け、その他の依存関係は<project_name>_<other>_<name>_depの形式(例:gtest_main_dep - メイン関数を持つgtest)にすることができます。

これらのルールには例外がある可能性があり、常識を適用する必要があります。

変数への依存関係の追加

0.54.0で新機能

場合によっては、プロジェクトがpkg-configまたはcmakeを介して、呼び出し元が知る必要のある特別な変数を定義することがあります。Mesonは、どのような種類の依存関係が提供されているかを隠すためのdependency.get_variableメソッドを提供しており、これはサブプロジェクトでも利用できます。文字列のdictを追加するには、variablesキーワードを使用します

my_dep = declare_dependency(..., variables : {'var': 'value', 'number': '3'})

別のプロジェクトは、次のようにアクセスできます

var = my_dep.get_variable(internal : 'var', cmake : 'CMAKE_VAR')

pkg-configとcmakeは変数を文字列として返すため、dictの値は文字列である必要があります。

サブプロジェクトでのビルドオプション

プロジェクトオプションなどのサブプロジェクトのすべてのMeson機能は引き続き動作し、マスタープロジェクトで設定できます。いくつかの制限があり、最も重要なのは、グローバルコンパイラ引数がサブプロジェクトを呼び出す前にメインプロジェクトで設定する必要があることです。複数のサブプロジェクトで確実に行う方法がないため、サブプロジェクトはグローバル引数を設定してはなりません。サブプロジェクトとして実行しているかどうかを確認するには、meson.is_subproject()を使用します。

サブプロジェクトの使用

すべてのサブプロジェクトはsubprojectsディレクトリ内にある必要があります。subprojectsディレクトリは、プロジェクトの最上位にある必要があります。サブプロジェクトの宣言は、最上位のmeson.buildにある必要があります。

簡単な例

libsimpleをサブプロジェクトとして使用してみましょう。

プロジェクトの最上位にsubprojectsディレクトリを作成します。次に、libsimplesubprojectsディレクトリにコピーします。

プロジェクトのmeson.buildは次のようになります。

project('my_project', 'cpp')

libsimple_proj = subproject('libsimple')
libsimple_dep = libsimple_proj.get_variable('libsimple_dep')

executable('my_project',
  'my_project.cpp',
  dependencies : libsimple_dep,
  install : true)

サブプロジェクトオブジェクトは依存関係として使用されないことに注意してください。そうではなく、サブプロジェクトには複数の宣言された依存関係がある可能性があるため、get_variableを使用してそこから宣言された依存関係を取得する必要があります。

システムライブラリと組み込みソースの切り替え

ディストリビューションパッケージをビルドする場合、ソースを埋め込まないことが非常に重要です。一部のディストリビューションには、埋め込み依存関係を禁止するルールがあるため、プロジェクトはそれらなしでビルド可能である必要があり、そうでない場合、パッケージャーはあなたを嫌うでしょう。

依存関係が利用できない場合に、システムライブラリを使用してソースの埋め込みにフォールバックする方法を次に示します。

project('my_project', 'cpp')

libsimple_dep = dependency('libsimple', required : false)

if not libsimple_dep.found()
  libsimple_proj = subproject('libsimple')
  libsimple_dep = libsimple_proj.get_variable('libsimple_dep')
endif

executable('my_project',
  'my_project.cpp',
  dependencies : libsimple_dep,
  install : true)

これは非常に一般的な操作であるため、Mesonはこのユースケースのショートカットを提供しています。

dep = dependency('foo', fallback : ['subproject_name', 'variable_name'])

fallbackキーワード引数は、サブプロジェクトの名前と依存関係を保持する変数の名前の2つの項目を受け取ります。複数の異なる変数を抽出するなど、より複雑なことを行う必要がある場合は、上記の手動の方法で自分で実行する必要があります。

このショートカットを使用すると、ビルド定義は次のようになります。

project('my_project', 'cpp')

libsimple_dep = dependency('libsimple', fallback : ['libsimple', 'libsimple_dep'])

executable('my_project',
  'my_project.cpp',
  dependencies : libsimple_dep,
  install : true)

呼び出しにキーワード引数を追加して、サブプロジェクトのデフォルトオプションを変更できます。たとえば、デフォルトのライブラリタイプを変更するには

libsimple_dep = dependency(
  'libsimple',
  fallback : ['libsimple', 'libsimple_dep'],
  default_options: ['default_library=static']
)

この設定では、libsimpleがシステムによって提供されている場合、それを使用し、サブプロジェクトのオプションを完全に無視します(つまり、共有システムライブラリにリンクします)。そうでない場合は、埋め込みバージョン(サブプロジェクトのバージョン)を使用します。

libsimple_depは外部または内部の依存関係を指すことができますが、それらの違いについて心配する必要はありません。Mesonが詳細を処理します。

他のサブプロジェクトに依存するサブプロジェクト

サブプロジェクトは他のサブプロジェクトを使用できますが、すべてのサブプロジェクトは最上位のsubprojectsディレクトリにある必要があります。ただし、サブプロジェクトの再帰的な使用は許可されていないため、サブプロジェクトaがサブプロジェクトbを使用し、baを使用することはできません。

サブプロジェクトの取得

Mesonには、依存関係サブプロジェクトを自動的に取得するための依存関係システムが付属しています。これは、Wrap依存関係システムマニュアルで説明されています。

コマンドラインオプション

サブプロジェクトの使用は、次のコマンドラインオプションを使用して、ユーザーとディストリビューションで制御できます

  • --wrap-mode=nodownload

    Mesonは、サブプロジェクトをダウンロードしたり、ラップ情報をフェッチしたりするためにネットワークを使用しません。既存のソースのみが使用されます。これは、ソフトウェアリリースで提供されるソースのみを使用し、手動で処理するか、不足している依存関係を提供する場合に役立ちます(主にディストリビューションの場合)。

  • --wrap-mode=nofallback

    Mesonは、ビルドファイル内の依存関係宣言にサブプロジェクトフォールバックを使用せず、システム内のみを検索します。これは、無条件のsubproject()呼び出しには適用されず、copylibsなど、システムによって提供できないソースに使用されることを意図していることに注意してください。

    このオプションは、特定の依存関係に対して--force-fallback-forでオーバーライドされる場合があります。

  • --wrap-mode=forcefallback

    Mesonは、サブプロジェクトフォールバックが利用可能な依存関係についてはシステムを調べず、それらにはサブプロジェクトのみを使用します。これは、フォールバック設定をテストする場合や、サブプロジェクトによって提供されるライブラリソースに対して具体的にビルドする場合に役立ちます。

  • --force-fallback-for=list,of,dependencies

    Mesonは、依存関係が宣言されたときにフォールバックが提供された場合、そこにリストされている依存関係についてはシステムを調べません。

    このオプションは--wrap-mode=nofallbackよりも優先され、--wrap-mode=nodownloadと組み合わせて使用​​すると、依存関係がすでにダウンロードされている場合にのみ機能します。

    これは、プロジェクトに多くのフォールバック依存関係があるが、それらの一部に対してのみライブラリソースに対してビルドする場合に役立ちます。

    警告:これにより、同じプロセスで同じライブラリのシステムバージョンとサブプロジェクトバージョンが混在する可能性があります。このケースを例に挙げてください

    • ライブラリglib-2.0gstreamer-1.0がシステムにインストールされています。
    • gstreamer-1.0glib-2.0に依存しており、pkg-configファイルgstreamer-1.0.pcにはRequires: glib-2.0があります。
    • アプリケーションのビルド定義では、次のようにします
      executable('app', ...,
        dependencies: [
          dependency('glib-2.0', fallback: 'glib'),
          dependency('gstreamer-1.0', fallback: 'gstreamer')],
      )
      
    • --force-fallback-for=glibで構成します。これにより、dependency('glib-2.0', fallback: 'glib')はサブプロジェクトの依存関係を返しますが、dependency('gstreamer-1.0', fallback: 'gstreamer')はフォールバックせず、glib-2.0ライブラリを含むシステムの依存関係を返すため、2つの異なるバージョンのライブラリglib-2.0にリンクされます。その状況を回避するには、glib-2.0自体に依存するすべての依存関係も、フォールバックを強制する必要があり、この場合は--force-fallback-for=glib,gsteamerを使用します。
  • --wrap-mode=nopromote

    0.56.0以降 Mesonはサブプロジェクトで見つかったラップファイルを自動的に使用し、メインプロジェクトにコピーします。その新しい動作は、--wrap-mode=nopromoteを渡すことで無効にできます。その場合、メインプロジェクトで見つかったラップのみが使用されます。

meson subprojectsコマンド

0.49.0以降

meson subprojectsには、すべてのサブプロジェクトを管理するためのさまざまなサブコマンドがあります。サブコマンドがサブプロジェクトで失敗した場合、実行は他のサブプロジェクトで続行されます。すべてのサブコマンドは、メインプロジェクトのルートソースディレクトリを指す--sourcedir引数を受け入れます。

0.56.0以降すべてのサブコマンドは、指定されたタイプのサブプロジェクトでのみサブコマンドを実行するための--types <file|git|hg|svn>引数を受け入れます。複数のタイプは、コンマ区切りのリストとして設定できます(例:--types git,file)。

0.56.0以降サブコマンドがサブプロジェクトで失敗した場合、成功を返す代わりに最後にエラーコードが返されます。

サブプロジェクトのダウンロード

0.49.0以降

--wrap-mode=nodownloadオプションが渡されない限り、Mesonは構成中に必要なサブプロジェクトを自動的にダウンロードします。Mesonの構成をオフラインで実行できるように、すべてのサブプロジェクトを事前にダウンロードすることをお勧めする場合があります。コマンドラインmeson subprojects downloadは、それを使用できます。これにより、不足しているすべてのサブプロジェクトがダウンロードされますが、既にフェッチされたサブプロジェクトは更新されません。

サブプロジェクトの更新

0.49.0以降

サブプロジェクトがフェッチされると、Mesonは自動的に更新しません。たとえば、ラップファイルがgitブランチを追跡している場合、最新のコミットはプルされません。

すべてのサブプロジェクトの最新バージョンを一度にプルするには、コマンド:meson subprojects updateを実行します。

  • ラップファイルがwrapdbからのものである場合、最新バージョンのラップファイルがプルされ、次回mesonがプロジェクトを再構成するときに使用されます。これは、meson --reconfigureを使用してトリガーできます。ローカルの変更が失われないように、以前のソースツリーは削除されません。0.58.0以降--resetが指定されている場合、ソースツリーは削除され、新しいソースが抽出されます。
  • サブプロジェクトが現在デタッチモードの場合、ラップファイルからのリビジョンのチェックアウトが実行されます。0.56.0以降リビジョンがローカルに既に存在しているが古くなっている場合は、リベースも実行されます。--resetが指定されている場合、リベースの代わりにハードリセットが実行されます。
  • サブプロジェクトが wrap ファイルで指定されたのと同じブランチにある場合、origin コミットに対してリベースが実行されます。0.56.0 以降 --reset が指定された場合、リベースの代わりにハードリセットが実行されます。
  • サブプロジェクトが wrap ファイルで指定されたものとは異なるブランチにある場合、--rebase オプションが渡されない限りスキップされます。--rebase オプションが渡された場合は、origin コミットに対してリベースが実行されます。0.56.0 以降--rebase 引数は非推奨となり、効果はありません。代わりに、wrap ファイルからリビジョンのチェックアウトが実行され、ローカルにすでに存在していたリビジョンが古くなっている場合は、リベースも実行されます。--reset が指定された場合、リベースの代わりにハードリセットが実行されます。
  • 0.56.0 以降 wrap ファイルで指定された url が git リポジトリの origin に設定された URL と異なる場合、--reset が指定されない限り更新されません。--reset が指定された場合は、まず origin の URL がリセットされます。
  • 0.56.0 以降 サブプロジェクトのディレクトリが git リポジトリではなく、[wrap-git] がある場合、--reset が指定されない限り、サブプロジェクトは無視されます。--reset が指定された場合は、ディレクトリが削除され、新しいリポジトリがクローンされます。

すべての git サブプロジェクトにわたってトピックブランチを開始します

0.49.0以降

コマンドライン meson subprojects checkout <branch_name> は、すべての git サブプロジェクトでブランチをチェックアウトするか、-b 引数付きでブランチを作成します。これは、複数のサブプロジェクトにわたってローカルな変更を開始するときに便利です。ローカルな変更を行った各リポジトリでコミットとプッシュを行うのは、依然としてあなたの責任です。

wrap ファイルで設定されたリビジョン(つまり、master)に戻るには、ブランチ名を指定せずに meson subprojects checkout を実行するだけです。

0.56.0 以降 新しいブランチをチェックアウトする前に、保留中の変更がすべて退避されるようになりました。

すべてのサブプロジェクトでコマンドを実行します

0.51.0 以降

コマンドライン meson subprojects foreach <command> [...] は、各サブプロジェクトのディレクトリでコマンドを実行します。たとえば、これはサブプロジェクトの状態を(例えば、git statusgit diff で)確認してから、他のアクションを実行するのに役立ちます。

なぜすべてのサブプロジェクトは単一のディレクトリ内にある必要があるのですか?

いくつかの理由があります。

まず第一に、ある程度の正気を保つために、システムは subdir() またはその変形で他のサブプロジェクト内に入らないようにする必要があります。サブプロジェクトを明確に定義された場所に置くと、これが簡単になります。サブプロジェクトがどこにでも存在できる場合、それははるかに難しくなります。

第二に、エンドユーザーがプロジェクトにどのようなサブプロジェクトがあるかを簡単に確認できることが非常に重要です。それらは1つ、そして1つの場所にのみあるため、レビューが簡単になります。

これは規約の問題でもあります。すべての Meson プロジェクトはサブプロジェクトに関して同じレイアウトを持っているため、プロジェクト間の切り替えが簡単になります。新しいプロジェクトで、サブプロジェクトを探してソースツリーをさまよう必要はありません。それらは常に同じ場所にあります。

最後に、サブプロジェクトをどこにでも配置できる場合、ソースツリーに依存関係のさまざまな(場合によっては互換性のない)バージョンが存在する可能性が高まります。その後、一部のコードを変更する(ディレクトリをトラバースする順序を変更するなど)と、誤ってサブプロジェクトのまったく異なるバージョンが使用される可能性があります。

検索の結果は次のとおりです