ハウツー MPS Make フレームワークへの統合
ファセットを構築
概要
基本的に他のビルドシステムや make システムと同様に、MPS make はアーティファクトをビルドするために一連のステップ、つまりターゲットを実行します。必要な make ステップのグローバルな順序付けは、各ビルドターゲットに指定された相対的な優先順位から導き出されます(ターゲット A は B の前に実行し、B は C の前に実行する必要があるため、グローバル順序は A、B、C です)。
完全なビルドプロセスでは、モデルのテキストへの生成、これらのモデルのコンパイル、サーバーへのデプロイ、graphviz ソースファイルからの .png ファイルの生成など、いくつかの問題に対処できます。MPS では、このようなさまざまなビルドアスペクトはビルドファセットで実装されます。ファセットは、共通の懸念事項に対処するターゲットの集合です。
ファセット内のターゲットは設定パラメーターを交換できます。例: 全体的な make プロセスの早い段階で実行するように宣言されているターゲットは、設定パラメーターを収集し、第 2 のファセットに渡します。このファセット内パラメーター交換を実現するためのメカニズムは、プロパティと呼ばれます。さらに、ターゲットは、make プロセス中にクエリを使用してユーザーから情報を取得できます。
全体的な make プロセスは、パイプとフィルターのパターンに沿って編成されています。ターゲットはフィルターとして機能し、配信されているデータストリームを処理します。ターゲット間を流れるデータはリソースと呼ばれます。さまざまな種類のリソースがあり、すべて異なる Java インターフェースおよびタプルとして表されます。
MResource には、ユーザーが作成した MPS モデルが含まれています。これらのモデルは、プロジェクトのソリューションと言語に含まれています。
GResource は、出力モデルを含む生成プロセスの結果、つまり生成が完了した後のモデルの最終状態を表します。これらは一時的なモデルであり、一時的なモデルを保存ビルドオプションを使用してインスペクションできます。
TResource は text-gen の結果を表します
CResource は、Java クラスのコレクションを表します
DResource は、モデルに対するデルタ変更のコレクションを表します (IDelta)
TextGenOutcomeResource は、textgen によって生成されたテキストファイルを表します
ビルドターゲットはインターフェースを指定します。パイプとフィルターのパターンに従って、インターフェースは make ターゲットに出入りするデータの種類を記述します。これは、上記のリソースタイプ、ターゲットがこれらのリソースに適用する処理の種類の観点から指定されます。次の 4 つの処理ポリシーが定義されています。
transform がデフォルトです。このポリシーは、入力リソースタイプのインスタンスを消費し、出力リソースタイプのインスタンスを生成します。(たとえば
MResources
を消費し、TResources
を生成する可能性があります。)宣言する入力を消費しますが、出力は生成しません。* produce は何も消費しませんが、出力を生成します
パススルーはいかなるリソースにもアクセスせず、生産も消費もしません。
作成プロセスはモデル生成よりも粒度が粗いことに注意してください。言い換えれば、すべてのモデルジェネレーターを実行する 1 つのファセットがあります。(モデル生成の前後に何かを行うのではなく) MPS 生成プロセスに追加のターゲットを「挿入」する必要がある場合は、generate
ファセットをリファクタリングする必要があります。これはこの議論の範囲を超えています。
サンプルファセットの構築
MPS の C 基本言語をビルドする mbeddr.com プロジェクトの一部として、実際の C コンパイラーを MPS ビルドプロセスに統合する必要があります。より具体的には、C 基本言語で記述されたプログラムには、Makefile
を生成する方法が含まれています。この Makefile
は、対応するすべての .c ファイルと .h ファイルが生成されたら、つまり MPS make プロセスの最後に実行する必要があります。
これを行うために、2 つのターゲットを持つ make ファセットを構築しました。1 つ目は、入力モデルをインスペクションし、textgen の後に Makefile
を含む可能性のあるディレクトリの絶対パスを収集します。次に、2 番目のターゲットは、このディレクトリに Makefile
というファイルが実際にあるかどうかを確認し、そこで make を実行します。上記の概要で説明したように、2 つのターゲットはプロパティを介してディレクトリを交換します。
最初のターゲット: ディレクトリの収集
ファセットは、言語定義の plugins
の側面に存在します。FacetDeclaration
のインスタンスを作成できるように、プラグインモデルに {{jetbrains.mps.make.facets} 言語が含まれていることを確認してください。モデル uses
がファセットを宣言する言語である場合、ファセットはモデルの作成プロセスの一部として実行されます。
ファセットは runMake
と呼ばれます。TextGen
と Generate
に依存します。これら 2 つのファセットへの依存関係は、それらのファセット内のターゲットに対するターゲットの優先順位を宣言できるように指定する必要があります。
最初のターゲットは collectPaths
と呼ばれます。入力モデルと連絡を取るために、{{transform IMResource-> IMResource} として指定されています。ファセットは、優先順位として after configure
と before generate
を指定します。後者は明らかです。なぜなら、モデルがテキストに生成される前にモデルを取得したいからです。前者の優先順位は、基本的に、make プロセスが初期化された後にこのターゲットを実行することを示しています (言い換えれば、「最初に」何かをしたい場合は、これら 2 つの優先順位を使用してください。)
次に、make ファイルを含むモジュールに関する情報と生成されたコードが存在するディレクトリへのパスを格納するために使用するプロパティ pathes
を宣言します。
次に、ターゲットの実装コードを見てみましょう。基本的な構造は次のとおりです。まず、pathes
リストを初期化します。次に、入力(リソースのコレクション)を繰り返し、各入力(以下で説明)に対して何かを実行します。次に、output
ステートメントを使用して入力データを出力します。つまり、ターゲットに出力されたものをすべて通過させます。success
ステートメントを使用して、このターゲットを正常に終了します(これがデフォルトであるため、最後に success
を使用することはオプションです)。何か問題が発生した場合は、failure
ステートメントを使用してターゲットを正常に終了できません。
実際の処理は、MPS データ構造に対する単純な Java プログラミングです。
モジュールの GenerationTargetFacet
ファセットの getOutputLocation
メソッドを使用して、特定のモジュールがそのコードを生成するパスを取得します (これはモデルプロパティでユーザーが構成できます)。次に、モデルのドット名を取得し、ドットをスラッシュに置き換えます。これは、そのモジュールでモデルの生成されたファイルが最終的に配置される場所であるためです (これを確認するには、サンプル MPS プロジェクトを調べましょう)。次に、モジュールの名前とモデルの名前をスラッシュで区切って保存し、2 番目のターゲット (変数 locationInfo}). We add the two strings to the {{pathes
コレクションを介して) のログメッセージを改善します。この pathes
プロパティは、ファセットの 2 番目のターゲットによってクエリされます。
2 番目のターゲット: 実行
リソースを扱う必要がないため、これは pass through
ポリシーを使用します。それが必要とするすべての入力は、上記の collectPaths
ターゲットのプロパティから取得できます。この 2 番目のターゲットは after collectPaths}, {{after textGen
と before reconcile
を実行します。それが collectPaths}, since it uses the property data populated by it. It has to run after {{textGen}, otherwise the make files aren't there yet. And it has to run before {{reconcile}, because basically everything has to run before {{reconcile
の後に走らなければならないのは明らかです
実装コードを見てみましょう。まず、実際に Makefile
を含むすべてのエントリを collectPathes.pathes
プロパティから取得します。何も見つからない場合は、success
を返します。
次に、プログレスインジケータ言語を使用して、make ファイルを含むディレクトリがあるのと同じ数のワークユニットでプログレスバーを設定します。
次に、{{modelDirectoriesWithMakefile} コレクションのすべてのエントリを繰り返し処理します。ループでは、進行状況インジケーターを進めてから、Java 標準 API を使用して make ファイルを実行します。
ターゲットをまとめるには、finish
ステートメントを使用してプログレスバーをクリーンアップします。
関連ページ:
共通言語パターン
この章では、MPS を学習する初心者が頻繁に遭遇する一般的な言語設計パターンについて説明します。これらは、MPS ユーザーがオンラインフォーラムで最も頻繁に確認する質問であることが長年にわたり判明しており、簡単に参照できるように回答を 1 か所にまとめることにしました。言語パターン付きのサンプルプロジェクト:MPS にはサンプルプロジェクトがバンドルされています。ここで説明するパターンの多くは、languagePatterns サンプルプロジェクトに実装されています。これを MPS で開き (M...
HowTo- 追加のツールを追加する (別名再生)
追加のツールを追加する (別名再生):このドキュメントでは、MPS 用の新しいツール(Eclipse ユーザーの場合、MPS のツールは Eclipse のビューのようなもの)を作成する方法について説明します。これは、MPS に任意の追加ツールを組み込むための例として役立ちます。このテキストは、ツール開発の側面、つまり言語とメニューシステムに新しいツールを追加する方法、および現在編集されているものとビューを同期する方法を強調しています。他のすべての点で、ツールは単なる Swing UI プログラ...