Valaアプリケーションとライブラリのコンパイル

Mesonは、ValaGenieで記述されたアプリケーションとライブラリのコンパイルをサポートしています。スケルトンのmeson.buildファイル

project('vala app', 'vala', 'c')

dependencies = [
    dependency('glib-2.0'),
    dependency('gobject-2.0'),
]

sources = files('app.vala')

executable('app_name', sources, dependencies: dependencies)

すべての現在のValaアプリケーションはそれらを使用するため、glib-2.0およびgobject-2.0ライブラリを依存関係として常に指定する必要があります。GLibは基本的なデータ型に使用され、GObjectはランタイム型システムに使用されます。

ライブラリの使用

Mesonは、ビルドターゲットでValaソースファイルを見つけると、関連するVAPI、Cヘッダー、リンカーフラグを見つけるためにdependency()関数を使用します。Valaはライブラリを使用するためにVAPIファイルとCヘッダーまたはヘッダーを必要とします。VAPIファイルは、ValaコードをライブラリのCプログラミングインターフェースにマッピングするのに役立ちます。これらのインストール済みファイルの検索をシームレスに動作させるのは、pkg-configツールです。ライブラリにpkg-configファイルが存在しない場合、compilerオブジェクトのfind_library()メソッドを使用する必要があります。例は後ほど示します。

注記 ValaはCアプリケーションバイナリインターフェース(C ABI)に従うライブラリを使用します。ただし、ライブラリはC、Vala、Rust、Go、C++、またはC ABIと互換性のあるバイナリを生成できるその他の言語で記述できます。そのため、Cヘッダーを提供します。

最も簡単なケース

この最初の例は、meson.buildファイルへの簡単な追加です。

  • ライブラリにpkg-configファイル(gtk+-3.0.pc)があるため
  • VAPIはValaと共に配布され、Valaコンパイラと共にインストールされるため
  • VAPIはValaの標準検索パスにインストールされるため
  • VAPI(gtk+-3.0.vapi)はpkg-configファイルと同じ名前であるため

すべてがバックグラウンドでシームレスに動作し、追加の行は1行だけ必要です

project('vala app', 'vala', 'c')

dependencies = [
    dependency('glib-2.0'),
    dependency('gobject-2.0'),
    dependency('gtk+-3.0'),
]

sources = files('app.vala')

executable('app_name', sources, dependencies: dependencies)

GTK+は、GNOME、elementary OS、その他のデスクトップ環境で使用されるグラフィカルツールキットです。ライブラリへのバインディングであるVAPIファイルは、Valaと共に配布されています。

他のライブラリには、ライブラリ自体に配布されているVAPIがある場合があります。このようなライブラリでは、VAPIファイルが他の開発ファイルと共にインストールされます。VAPIはValaの標準検索パスにインストールされるため、dependency()関数を使用して同様にシームレスに機能します。

GLibのバージョンをターゲットにする

Mesonのdependency()関数は、ライブラリのバージョンチェックを許可します。これは、インストールされている最小バージョンをチェックするために頻繁に使用されます。GLibの最小バージョンを設定すると、Mesonは--target-glibオプションを使用してValaコンパイラにも渡します。

これは、Valaの[GtkTemplate][GtkChild][GtkCallback]属性を使用してGTK+のユーザーインターフェース定義ファイルを使用する場合に必要です。これには、Valaに--target-glib 2.38以降のバージョンを渡す必要があります。Mesonでは、これは次のように簡単に実行できます。

project('vala app', 'vala', 'c')

dependencies = [
    dependency('glib-2.0', version: '>=2.38'),
    dependency('gobject-2.0'),
    dependency('gtk+-3.0'),
]

sources = files('app.vala')

executable('app_name', sources, dependencies: dependencies)

[GtkTemplate]を使用するには、GTK+ユーザーインターフェース定義ファイルをGResourcesとしてバイナリにビルドする必要もあります。完全性を期すために、次の例に示します。

project('vala app', 'vala', 'c')

dependencies = [
    dependency('glib-2.0', version: '>=2.38'),
    dependency('gobject-2.0'),
    dependency('gtk+-3.0'),
]

sources = files('app.vala')

sources += import( 'gnome' ).compile_resources(
    'project-resources',
    'src/resources/resources.gresource.xml',
    source_dir: 'src/resources',
)

executable('app_name', sources, dependencies: dependencies)

Valaの検索パスに追加する

これまで、VAPIファイルがValaまたはライブラリに配布されている場合について説明しました。VAPIはプロジェクトのソースファイルにも含めることができます。慣例では、プロジェクトのvapiディレクトリに配置します。

これは、ライブラリにVAPIがない場合、またはプロジェクトがC ABIを使用するプロジェクトの別のコンポーネントにリンクする必要がある場合に必要です。たとえば、プロジェクトの一部がCで記述されている場合などです。

Valaコンパイラの--vapidirオプションは、プロジェクトディレクトリをVAPI検索パスに追加するために使用されます。Mesonでは、これはadd_project_arguments()関数を使用して行われます。

project('vala app', 'vala', 'c')

vapi_dir = meson.current_source_dir() / 'vapi'

add_project_arguments(['--vapidir', vapi_dir], language: 'vala')

dependencies = [
    dependency('glib-2.0'),
    dependency('gobject-2.0'),
    dependency('foo'), # 'foo.vapi' will be resolved as './vapi/foo.vapi'
]

sources = files('app.vala')

executable('app_name', sources, dependencies: dependencies)

VAPIが外部ライブラリのものである場合は、VAPIの名前がpkg-configファイル名に対応していることを確認してください。

vala-extra-vapisリポジトリは、配布されていないVAPIのコミュニティで管理されているリポジトリです。開発者は、このリポジトリを使用して、新しいバインディングの初期作業と既存のバインディングの改善を共有します。そのため、このリポジトリのVAPIは頻繁に変更される可能性があります。このリポジトリからのVAPIは、プロジェクトのソースファイルにコピーすることをお勧めします。

これは、vala-extra-vapisリポジトリで共有される前に、新しいバインディングの記述を開始する場合にも効果的です。

pkg-configファイルのないライブラリ

対応するpkg-configファイルがないライブラリでは、dependency()がCおよびValaインターフェースファイルを見つけるのに適さない場合があります。この場合、コンパイラオブジェクトのfind_library()メソッドを使用する必要があります。

最初の例では、ValaのPOSIXバインディングを使用しています。POSIXはUnixシステムで標準Cライブラリを含んでいるため、pkg-configファイルはありません。必要なのはVAPIファイル(posix.vapi)だけです。これはValaに含まれており、Valaの標準検索パスにインストールされています。Mesonは、Valaコンパイラに対してのみライブラリを見つけるように指示するだけです。

project('vala app', 'vala', 'c')

dependencies = [
    dependency('glib-2.0'),
    dependency('gobject-2.0'),
    meson.get_compiler('vala').find_library('posix'),
]

sources = files('app.vala')

executable('app_name', sources, dependencies: dependencies)

次の例は、追加のVAPIが不要なCライブラリとのリンク方法を示しています。標準的な数学関数は既にglib-2.0.vapiにバインドされていますが、GNU Cライブラリでは数学ライブラリに個別にリンクする必要があります。この例では、MesonはCコンパイラに対してのみライブラリを見つけるように指示されています。

project('vala app', 'vala', 'c')

dependencies = [
    dependency('glib-2.0'),
    dependency('gobject-2.0'),
    meson.get_compiler('c').find_library('m', required: false),
]

sources = files('app.vala')

executable('app_name', sources, dependencies: dependencies)

required: falseは、数学ライブラリを分離しない別のCライブラリを使用する場合でもビルドが継続されることを意味します。数学ライブラリ(-lm)の移植可能な追加方法を参照してください。

最後の例は、pkg-configファイルがなく、VAPIがプロジェクトのソースファイルのvapiディレクトリにあるライブラリの使用方法を示しています。

project('vala app', 'vala', 'c')

vapi_dir = meson.current_source_dir() / 'vapi'

add_project_arguments(['--vapidir', vapi_dir], language: 'vala')

dependencies = [
    dependency('glib-2.0'),
    dependency('gobject-2.0'),
    meson.get_compiler('c').find_library('foo'),
    meson.get_compiler('vala').find_library('foo', dirs: vapi_dir),
]

sources = files('app.vala')

executable('app_name', sources, dependencies: dependencies)

Cコンパイラオブジェクトのfind_library()メソッドは、Cヘッダーファイルとリンクするライブラリを見つけようとします。

Valaコンパイラオブジェクトのfind_library()メソッドには、プロジェクトVAPIディレクトリを含めるためにdirキーワードを追加する必要があります。これはadd_project_arguments()によって自動的に追加されません。

Valaプリプロセッサとの連携

Valaのプリプロセッサに引数を渡すには、言語をvalaとして指定する必要があります。たとえば、次のステートメントはプリプロセッサシンボルUSE_FUSEを設定します。

add_project_arguments('-D', 'USE_FUSE', language: 'vala')

Cプリプロセッサに引数を渡す必要がある場合は、言語をcとして指定します。たとえば、FUSE_USE_VERSIONを26に設定するには、次を使用します。

add_project_arguments('-DFUSE_USE_VERSION=26', language: 'c')

ライブラリのビルド

CヘッダーとVAPIの名前の変更

Mesonのlibrary()ターゲットは、CヘッダーとVAPIを自動的に出力します。これらは、それぞれvala_headervala_vapi引数を設定することで名前を変更できます。

foo_lib = shared_library('foo', 'foo.vala',
                  vala_header: 'foo.h',
                  vala_vapi: 'foo-1.0.vapi',
                  dependencies: [glib_dep, gobject_dep],
                  install: true,
                  install_dir: [true, true, true])

この例では、install_dir配列の2番目と3番目の要素は、デフォルトディレクトリ(つまり、includeshare/vala/vapi)を使用するためにtrueを使用して宛先を示しています。

GObjectイントロスペクションと言語バインディング

「バインディング」により、別のプログラミング言語でValaで記述されたライブラリを使用できます。ValaはGObject型システムをランタイム型システムとして使用するため、イントロスペクションを使用してバインディングを生成するのは非常に簡単です。ValaライブラリのMesonビルドは、GObjectイントロスペクションメタデータを生成できます。次に、メタデータは、言語固有のツールを使用して別のプロジェクトで使用され、バインディングが生成されます。

メタデータの主な形式は、GObjectイントロスペクションリポジトリ(GIR)XMLファイルです。GIRは、主にコンパイル時にバインディングを生成する言語で使用されます。ランタイムにバインディングを生成する言語は、主にGIRから生成されるtypelibファイルを使用します。

Mesonは、ビルドの一部としてGIRを生成できます。Valaライブラリの場合、libraryに対してvala_girオプションを設定する必要があります。

foo_lib = shared_library('foo', 'foo.vala',
                  vala_gir: 'Foo-1.0.gir',
                  dependencies: [glib_dep, gobject_dep],
                  install: true,
                  install_dir: [true, true, true, true])

install_dirtrue値は、Mesonにデフォルトディレクトリ(つまり、GIRの場合はshare/gir-1.0)を使用するように指示します。install_dir配列の4番目の要素は、GIRファイルがインストールされる場所を示しています。

次に、typelibファイルを作成するには、g-ir-compilerプログラムとライブラリへの依存関係を使用してカスタムターゲットを使用します。

g_ir_compiler = find_program('g-ir-compiler')
custom_target('foo typelib', command: [g_ir_compiler, '--output', '@OUTPUT@', '@INPUT@'],
              input: meson.current_build_dir() / 'Foo-1.0.gir',
              output: 'Foo-1.0.typelib',
              depends: foo_lib,
              install: true,
              install_dir: get_option('libdir') / 'girepository-1.0')

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