コンパイラプロパティ

すべてのコンパイラとプラットフォームが同じとは限りません。そのため、Mesonは設定時にシステムのプロパティを検出するツールを提供します。この情報のほとんどを取得するには、まずコンパイラオブジェクトをメインのmeson変数から抽出する必要があります。

compiler = meson.get_compiler('c')

ここでは、Cコンパイラを抽出します。引数にcppを指定してC++コンパイラを取得したり、objcを指定してObjective Cコンパイラを取得したりすることもできます。この呼び出しは、project宣言で指定されたすべての言語で有効です。他のコンパイラを取得しようとすると、回復不能なエラーが発生します。

システム情報

これは少し複雑で、クロスコンパイルのページでより詳細に説明されています。しかし、コードが実行されるオペレーティングシステムを知りたいだけなら、次のコマンドを実行してください。

host_machine.system()

コンパイラID

コンパイラオブジェクトのメソッドcompiler.get_id()は、コンパイラの「ファミリー」を表す小文字の文字列を返します。0.53.0以降、compiler.get_linker_id()はリンカー名を表す小文字の文字列を返します。コンパイラは、オペレーティングシステムに応じて複数のリンカーから選択できることが多いため、get_linker_idは特定のリンカーの影響を処理または軽減するのに役立ちます。

コンパイラオブジェクトには、compiler.get_argument_syntax()というメソッドもあります。これは、gccmsvc、またはその他の未定義の文字列値の小文字の文字列を返します。コンパイラの引数がgccまたはmsvcと同じ構文を使用するかどうか、またはその引数がどちらにも似ていないかどうかを識別します。これは、compiler.has_argument()でテストする引数など、引数の構文を選択するためにのみ使用してください。

サポートされているコンパイラIDとその引数の種類については、リファレンステーブルを参照してください。

コードはコンパイルされますか?

システムをテストする唯一の方法は、サンプルコードをコンパイルしてみて、それが動作するかどうかを確認することです。たとえば、これにより、「C++17」コンパイラが特定のC++17機能を実際にサポートしているかどうかを、機能リストとコンパイラベンダー、コンパイラバージョン、およびオペレーティングシステムを比較して維持することなくテストできます。コードスニペットが実行されることをテストするには、2段階の操作が必要です。最初に、複数行文字列演算子を使用してコードを定義します。

code = '''#include<stdio.h>
void func() { printf("Compile me.\n"); }
'''

次に、テストを実行できます。

result = compiler.compiles(code, name : 'basic check')

変数*result*には、コンパイルが成功したかどうかに応じて、trueまたはfalseが含まれます。キーワード引数`name`はオプションです。指定されている場合、Mesonはチェックの結果をログに書き込みます。

特定のコードフラグメントがコンパイルされるだけでなく、正常にリンクされるかどうかを確認する必要がある場合があります。たとえば、シンボルがライブラリに実際に存在するかどうかを確認する場合です。これは、compiler.links()メソッドを使用して、次のように行うことができます。

code = '''#include<stdio.h>
void func() { printf("Compile me.\n"); }
'''

次に、テストを実行できます。

result = compiler.links(code, args : '-lfoo', name : 'link check')

変数*result*には、コンパイルとリンクが成功したかどうかに応じて、trueまたはfalseが含まれます。キーワード引数`name`はオプションです。指定されている場合、Mesonはチェックの結果をログに書き込みます。

テストアプリケーションのコンパイルと実行

小さなテストアプリケーションをコンパイルして実行する方法は次のとおりです。コードスニペットがリンクするだけでなく**実行される**かどうかをテストすることは、MPIなどの一部の依存関係にとって特に重要です。

code = '''#include<stdio.h>
int main(int argc, char **argv) {
  printf("%s\n", "stdout");
  fprintf(stderr, "%s\n", "stderr");
  return 0;
}
'''
result = compiler.run(code, name : 'basic check')

`result`変数はテストの状態をカプセル化しており、次のメソッドで抽出できます。 `name`キーワード引数は`compiles`と同じように機能します。

メソッド 戻り値
compiled コンパイルが成功した場合は`True`。`false`の場合、他のすべてのメソッドは未定義の値を返します。
returncode アプリケーションの戻りコード(整数)
stdout プログラムの標準出力(テキスト)
stderr プログラムの標準エラー(テキスト)

使用例を次に示します。

if result.stdout().strip() == 'some_value'
  # do something
endif

ヘッダーは存在しますか?

さまざまなプラットフォームによって提供されるヘッダーファイルはかなり異なります。Mesonには、特定のヘッダーファイルがシステムで利用可能かどうかを検出する機能があります。テストは、指定されたヘッダーを含む簡単なテストプログラムをコンパイルしてみることで行われます。次のスニペットは、この機能の使用方法を示しています。

if compiler.has_header('sys/fstat.h')
  # header exists, do something
endif

式のサイズ

多くの場合、特定の要素(`int`、`wchar_t`、`char*`など)のサイズを決定する必要があります。上記の`compiler`変数を使用すると、チェックは次のように行うことができます。

wcharsize = compiler.sizeof('wchar_t', prefix : '#include<wchar.h>')

これにより、sizeofによって報告された`wchar_t`のサイズが変数`wcharsize`に格納されます。キーワード引数`prefix`はオプションです。指定されている場合、その内容はソースファイルの先頭に配置されます。この引数は通常、設定ファイルで`#include`ディレクティブを設定するために使用されます。

古いバージョン(<= 0.30)では、サイズを決定できない場合、Mesonはエラーを発生させます。バージョン0.31以降、サイズを決定できない場合は-1を返します。

関数は存在しますか?

ヘッダーがあるだけでは、その内容については何もわかりません。明示的に関数が存在するかどうかを確認する必要がある場合があります。`stdio.h`ヘッダーに関数`open_memstream`が存在するかどうかを確認する方法は次のとおりです。

if compiler.has_function('open_memstream', prefix : '#include <stdio.h>')
  # function exists, do whatever is required.
endif

macOSでは、プログラムのコンパイル対象となるmacOSのバージョンを、プログラムのコンパイルに使用するmacOSのバージョンよりも古いバージョンにすることができることに注意してください。コンパイルされるOSバージョンが、バイナリが実行されるOSバージョンと一致すると想定することはできません。

したがって、compiler.has_function()を使用して関数の可用性を検出する場合、プレフィックス引数に正しいヘッダーを指定することが重要です。

上記の例では、macOS 10.13で導入された関数`open_memstream`が検出されます。ユーザーがmacOS 10.13でビルドしているが、macOS 10.11をターゲットにしている場合(`-mmacosx-version-min=10.11`)、これは関数が存在しないと正しく報告します。ただし、ヘッダーがないと、必要な可用性情報が不足し、関数が利用可能であると誤って報告されます。

構造体にメンバーが含まれていますか?

一部のプラットフォームでは、標準構造体が異なります。 `myheader.h`ヘッダーの`mystruct`という構造体に`some_member`というメンバーが含まれているかどうかを確認する方法は次のとおりです。

if compiler.has_member('struct mystruct', 'some_member', prefix : '#include<myheader.h>')
  # member exists, do whatever is required
endif

型の配置

ほとんどのプラットフォームは、任意のアドレスで一部のデータ型にアクセスできません。たとえば、`char`は任意のアドレスに配置できますが、32ビット整数は4で割り切れる場所にのみ配置できます。データ型の配置を決定するのは簡単です。

int_alignment = compiler.alignment('int') # Will most likely contain the value 4.

引数がある

このメソッドは、コンパイラが特定のコマンドライン引数をサポートしているかどうかをテストします。これは、指定された引数で小さなファイルをコンパイルすることで実装されます。

has_special_flags = compiler.has_argument('-Wspecialthing')

*注*:一部のコンパイラは、理解できないコマンドライン引数を黙って無視します。したがって、このテストを100%信頼できるものにすることはできません。

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