CDT ベースのエディターを構築する、第 1 回: C/C++ Development Tooling モデル

CDT 情報を含むクラスを探る

Eclipse の CDT (C/C++ Development Tooling) プロジェクトは、Eclipse のダウンロードとして利用できるものの中で最も人気のあるものの 1 つです。しかし、この IDE (integrated development environment) の機能はあまりにも豊富なため、コードを理解したりカスタマイズしたりすることは難しくなっています。これは、自分たちのアプリケーションに CDT を統合しようとする組織にとって大きな懸念事項です。この、5 回シリーズの「CDT ベースのエディターを構築する」は、CDT エディターの動作を解説します。第 1 回の今回は、CDT が行う操作の対象となる、データ構造について紹介します。

Matthew Scarpino, Java Developer, Eclipse Engineering, LLC

Matthew Scarpino は、Eclipse Engineering LLC のプロジェクト・マネージャーであり、Java 開発者です。彼は SWT/JFace in Action の中心著者であり、また SWT (Standard Widget Toolkit) に対して、小さいながらも重要な貢献をしました。彼が好きなものはアイルランドの民族音楽やマラソン、William Blake の詩、そして GEF (Graphical Editing Framework) です。


developerWorks 貢献著者レベル

2006年 9月 12日

私は自分の上司に CDT を勧めたつもりでしたが、彼は、機能が多すぎると言うのです。よく聞いてみると、彼はソース・エディターだけが欲しかったのです。つまり構文の色分けや自動構文解析、そして特に、コード・コンプリーションが欲しいのです。彼は私に、エディターをカスタマイズして私達の RCP (Rich Client Platform) アプリケーションに追加できないか尋ねました。私は「まったく問題ありません」と答えました。「これは Eclipse です。難しいはずがありません。」

しかし実は、非常に難しいことがわかったのです。現在、CDT V3.1 は100 以上のパッケージと何千ものインターフェースやクラスを含む、20 のプラグインで構成されています。私の上司が求めるものを作り出す仕事は、長期計画になってしまいました。しかし私は、なんとか動作するエディターを作り上げ、上司を満足させることができたのです。そこで、その中から私が学んだことを皆さんに紹介することにします。

CDT はオープンソースで利用可能な C/C++ IDE として、おそらく最も優れたものです。完全機能のエディターや、デバッグやインデックス機能に加え、信じられないほど柔軟にビルド・プロセスをコントロールすることができます。独自の makefile を自分で作りたくなければ、CDT が作成してくれます。しかも、プロジェクト全体をとおして makefile をアップデートしてくれるのです。CDT の中にある GCC (GNU Compiler Collection) や他の GNU C/C++ アプリケーションはもちろん利用でき、他の任意のオープンソースや商用のツール・チェーンを統合することもできます。

QNX Inc. は 2002 年に CDT を提案し、開発と維持管理のリーダーの役割を果たしてきました。コードの大部分は Eclipse の JDT (Java Development Tools) に基づくものですが、QNX は (特に Doug Schaefer は)、高度な C/C++ 構文解析や、標準あるいは管理 make プロジェクト、構成可能なビルド・プロセスなど、多くの機能を追加しました。さらに詳しい情報が必要な方は、Eclipse CDT のページを見るのが一番です。また Doug Schaefer のブログにもよく説明されています (「参考文献」を参照)。

The Bare Bones CDT

このシリーズの目標は、皆さんが CDT の編集機能を理解し、カスタムの C/C++ ツールをビルドできるようにすることです。このプロセスを容易にするために、私は完全機能の CDT から大部分の機能を省略した簡略版の CDT を作り、BBCDT (Bare Bones CDT) と呼ぶことにしました (コードについては「ダウンロード」セクションを参照してください)。CDT のクラスの大部分は削除しましたが、命名規則は同じままです。これは CDT コードを BBCDT に追加するプロセスを単純にするためですが、私が怠惰なことも理由の 1 つです。

BBCDT には、org.dworks.bbcdt.core (Core プラグイン) と org.dworks.bbcdt.ui (UI (ユーザー・インターフェース) プラグイン) という、2 つのプラグインしか含まれていません。前者は CDT モデルを構成するクラスとインターフェースを提供しています。後者は UI を作成します。後者の中には CEditor とその関連クラス、そして新しいソース・ファイルやプロジェクトの作成に必要なウィザードやページが含まれています。

この第 1 回では、この BBCDT は何も面白いことはせず、基本的な CDT クラス同士がどのように動作するかを示すのみです。今後の記事では、CDT がどのようにパーティショニングや構文色分け、構文解析、コード・コンプリーションなどを行っているかを説明し、BBCDT の拡張として、こうした機能をコードに追加していきます。

CDT モデルの要素

通常の Java™ コードは、File オブジェクトを介してファイルやディレクトリーにアクセスします。しかしワークスペースのファイル上で Eclipse 特有の操作を行う場合には、Resource API (application program interface) に次のようなアダプターが必要です。

  • IFile
  • IProject
  • IFolder
  • IWorkspaceRoot

こうした IResource は、ファイル・アクセスを提供する以外に、ワークスペースに構造を与えます。最上位レベルのリソースは IWorkspaceRoot であり、その子は IProject です。各 IProjectIFolderIFile を含んでいます。ここまでは問題ないでしょう。

CDT モデルでは、それらとは異なった、しかしよく似た一連のアダプターを、ワークスペース・リソースに対して持っています。図 1 は、そうしたアダプターの継承の階層を示しています。

図 1. CDT モデル要素の階層構造
CDT モデル要素の階層構造

図 2 は、CDT がこうした要素を使ってワークスペースを構成している様子を示したものです。一番上のICModel は、 ICContainerICProject を含んでいます。 ICProjectISourceRoot を含んでいます。ISourceRoot はJDT パッケージのように機能しますが、ファイルシステム上の様々な場所にあるコードを含むことができます。こうした位置を管理するために、ISourceRoot には ISourceEntry インスタンスが含まれており、それぞれのインスタンスは各ソースへの IPath を持っています。各 ICElement は特定の名前と、基礎となる IResource にアクセスするためのメソッドを持っています。

図 2. CDT ワークスペースの構造
CDT ワークスペースの構造

ITranslationUnit

ITranslationUnit は C/C++ コードの 1 つのファイルを表し、CDT モデルの中で最も重要な要素です。各ユニットは、ソースコード・ファイルの様々な側面を表現する子 (IInclude や IUsingINamespace など) を含んでいます。(ITranslationUnit の構造については、今後の記事で CDT の構文解析を解説する際に詳しく説明する予定です)。

また、それぞれの ITranslationUnit は 1 つの IWorkingCopy を持ち、保存されていないコード変更を管理します。ITranslationUnit も IWorkingCopy も、それぞれの内容を別の IBufferCache インスタンスに保存します。このインスタンスは、BufferManager や LRU (Least Recently Used) キャッシュのような機能によって割り当てられます。これは複雑な話題ですが、興味のある方は、org.dworks.bbcdt.internal.core.util パッケージを調べてみてください。

Info オブジェクト

ICModelICContainerICProjectITranslationUnit なども、それぞれに対応する info オブジェクト ( CModelInfoCContainerInfo など) を持っています。こうした info オブジェクトは、要素の子への参照を含んでおり、子へのアクセスを提供します。CModelICProjects のリストが必要な場合は、CModel.getCProjects() メソッドを呼びます。そうすると CModelInfo.getChildren() メソッドが呼ばれます。CDT は、要素が最初にオープンされた時に info オブジェクトを作成し、その要素がクローズされた時に info オブジェクトを破棄します。


CDT モデルの 3 つのステップ

CDT モデルの基本的な要素は理解できたので、そうした要素が CDT の動作中にどのように相互動作するかを知る必要があります。CDTモデルのライフ・サイクルは、3 つの重要なステップから構成されています。最初はCDT モデルの作成、次に CProject の作成、そして CDT エディターの中での TranslationUnit の作成というステップです。

CDT モデル要素と IAdapters

CDT モデルの要素 (ICModelICProjectITranslationUnit など) は、Eclipse ワークベンチを構成するリソースと同様、どれも IAdaptable インターフェースから派生したものです。このインターフェースによって、CDT は CDT 特有の機能を、サブクラス化せずに既存のクラスに追加することができます。コーディングの観点から見ると、IAdaptablegetAdapter(Class adapter) メソッドを使って、別のクラスに IAdaptable をキャストすることができます。

CDT は各要素に対して、完全定義されたメソッドを持つ実装クラス (CModelCProjectTranslationUnit など) を用意しています。しかし IAdaptable インターフェースを使うことによって、ICElement の持つ既存の機能を失うことなく、独自の C/C++ 要素を作成することができます。つまり、CDT要素がリソースを Eclipse ワークスペースで利用できるようにするのと同じ方法で、新しい要素はCDT 要素を利用できるのです。

ステップ 1: CDT モデルを作成する

ワークベンチが CDT プラグインを初期化すると、Core プラグインは CoreModelという (CModel ではありません) シングルトンを作成します。このプロセスによって、今度は 2 つの重要なクラスのインスタンス、PathEntryManager と CModelManager が作成されます。PathEntryManager は、ビルド・プロセスに必要なディレクトリー (included ディレクトリーやマクロ・ライブラリーなど) を追跡します。CDT モデルでは、各ディレクトリーへのパスは SourceEntry オブジェクトの中にあります。

しかし、ここでのポイントは CModelManager クラスです。このクラスは、CDT で次のような重要な役割を果たします。

  • 要素の階層構造の最上位要素となる CModelを作成する。
  • モデルのリソースが作成、削除される毎に新しいモデル要素を追加、削除する。
  • モデル要素と、その info オブジェクトを追跡する。
  • TranslationUnit と、それらの子である WorkingCopy のマップを保持する。
  • 現在オープンされている要素のキャッシュを保存する。
  • リソースのコンテンツ・タイプの変化に対応する。
  • リソースの記述子の変化に対応する。

このうち最も重要な機能は、最初の 2 つです。 CModelManager は CDT モデルのファクトリーとして動作し、CModel オブジェクトを作成することで動作を開始します。次に、ワークスペースのリソース変化をリッスンし、CDT要素が影響を受ける都度、モデルを更新します。

リソースが作成され、削除され、あるいは変更されると、Eclipse ワークスペースは、新旧の階層構造を保存する IResourceDelta を作成します。そうすると CModelManager は、これを DeltaProcessor を使って分析し、影響を受けたリソースが CElement かどうかを判断します。もし CElement である場合には、そのリソースに対応する新しい要素を作成し、その要素を、その親の子リストに追加します。

BBCDT の CModelManager 機能は、上記の機能をすべて実行します (ただし最後の 2 つは除きます)。リソースのコンテンツ・タイプは、plugin.xml ファイルの <content-type> リストによって設定され、新しいプロジェクトを記述した記述子ファイルが作成されます。

ステップ 2: 新しい CProject を作成する

CDT には、CDT リソースを作成するための、完全拡張可能なウィザード構造が用意されています。特に New Project Wizard は強力であり、環境変数からソースのインデックス付けまで、プロジェクトのビルド・プロセスのあらゆる側面を構成することができます。このウィザードが完成すると、このウィザードと Core プラグインは、下記の 4 つの主なタスクを実行します。

  1. 与えられたパスに IProject を作成し、オープンする。
  2. IProject の一般的な情報を保持する IProjectDescription を構築する。
  3. CDT 固有の情報を保持する CDescriptor を構築する。
  4. コンテンツ・タイプによって、IProjectCNature または CCNature を与える

最初のステップと 2 番目のステップは、どのような IProject を作成する場合も共通です。2 番目のタスクで、IProjectDescription は、ワークベンチがプロジェクトを定義するために使用する情報を保存します。このデータは、プロジェクトの最上位ディレクトリーにある.project ファイルの中に、XML フォーマットで持続的に存在しています。この中で重要な2 つの要素は、プロジェクトのビルド・コマンドをリストする <buildSpec></buildSpec> と、通常の IProject 以上の特性を持つものとしてプロジェクトをマーキングする <natures></natures> です。

3 番目のステップの CDescriptor は、IProjectDescription と似ています。主な違いは、CDescriptor は CDT 固有のデータを含んでおり、この情報を別の .cdtproject ファイルの中に挿入する点です。.cdtprojectファイルはビルド・プロセスに使われる様々なツールのプロファイルを含んでおり、また、それぞれのツールの構成パラメーターを規定します。このファイルは、IProjectDescription と似た XML フォーマットを使います。リスト 1 は、.cdtproject プロファイル宣言の例です。

リスト 1. .cdtproject ファイルの中のプロファイル情報
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
    <buildOutputProvider>
        <openAction enabled="false" filePath=""/>
        <parser enabled="true"/>
    </buildOutputProvider>
    <scannerInfoProvider id="makefileGenerator">
        <runAction arguments="-f ${project_name}_scd.mk" command="make"   
            useDefault="true"/>
        <parser enabled="false"/>
    </scannerInfoProvider>
</profile>

最後のステップでは、プロジェクトを、C プロジェクトあるいは C++ プロジェクトとしてタグ付けします。これは Core プラグインが、IProjectDescriptionCNature または CCNature を追加することで行います。これらのクラスは、それ自体では何も面白いことはしませんが、DeltaProcessor は新しいプロジェクトの nature (性質) を認識すると、プロジェクト・リソースに対応するCProject を作成するようにCModelManager に伝え、それを CDT モデルの階層構造に追加します。

ステップ 3: 新しい TranslationUnit と WorkingCopy を作成する

TranslationUnit は CProject とは異なり、基礎となる IFile が現れると即座に作成されるわけではありません。IFile が有効になり、エディターがオープンされると作成されます。この動作を説明するために、CDT 編集プロセスの中心的なクラス、CEditor から始めることにしましょう。

CEditor は基本的に、ワークベンチの中に収まる StyledText ウィジェットであり、IEditorInput インスタンスからコンテンツを取得します。Eclipse Text Editor API は MVC(Model-View-Controller) アーキテクチャーに従って、View 側面を提供するためにのみ、このウィジェットを使います。CEditor の情報は IDocument のインスタンスの中にカプセル化されています。SourceViewer はコントローラーとして動作し、CSourceViewer が CDT 文書へのアクセスを管理します。

plugin.xml は、Core プラグインの中で、様々なタイプの C/C++ ファイルに対するcontentType 拡張子を保持し、それぞれの contentType をファイルの接尾辞に関連付けます。また plugin.xml は UI プラグインの中で、CEditor をこうした contentType に関連付けます。BBCDT は、.bbc や .bbcpp、.bbh、.bbhpp などの接尾辞を持つファイルを認識します。こうしたファイルの1 つを作成するか、あるいはダブル・クリックすると、ワークベンチは IFileを IEditorInput に変換し、それを使って CEditor を初期化します。

CEditor が初期化されると、CDocumentProvider は次のような 3 つの重要なタスクを実行します。

  1. 入力のIFile を使って TranslationUnit オブジェクトと TranslationUnitInfo オブジェクトを作成する。
  2. 情報を IEditorInput に持つ、CEditorIDocument を作成する。
  3. TranslationUnit とそのバッファーに対する WorkingCopy を作成する。

新しい CDT 要素を作成するためには、プロバイダーがCoreModel をコールします。そうすると CModelManager がコールされます。こうしたワークスペース操作、CreateWorkingCopyOperationDestroyWorkingCopyOperation などは、すべて IWorkspaceRunnable インターフェースを実装しています。これらは非同期に実行し、他の操作がリソース変更に妨害されないようにワークスペースに伝えます。

CProject と同様、それぞれの TranslationUnit は、注釈など、独自の構成情報を持っています。しかし、プロバイダーが別のCDescriptor を作成することはありません。プロバイダーはそのデータを、IEditorInputFileInfo オブジェクトの中に持続して持っているのです。そのためプロバイダーは、次回その入力が有効になった時にも、ゼロから作らなくてもユニット情報にアクセスすることができます。


BBCDT を実行する

ここでは BBCDT を、プラグインとして、そしてプラグイン・プロジェクトとして提供しました。このツールの主な目的は、今後の作業のための基礎を提供することなので、Eclipse インストールにツールの機能を追加するよりも、こうしたプロジェクトをインポートするようにお勧めします。

私は BBCDT をできるだけ単純にするために、PathEntryManager は省略しました。これはつまり、BBCDT は SourceEntry オブジェクトも、さらにはSourceRoot さえも使わないということです。従って、ソースファイル (.bbc や .bbh、.bbcc、.bbhhなどのファイル) を、プロジェクトに直接追加する必要があります。私は BBCDTリソースを作成するために、org.dworks.bbcdt.ui.wizards パッケージの中に一連の新しいwizard/page クラスを作成しました。プロジェクトを作成するには、File > New > Project をクリックし、C または C++ オプションのいずれかを選択します。ファイルを作成するには、New > Other をクリックし、C または C++ オプションのいずれかを選択します。図 3 は、BBCDTプロジェクトと、このエディターの様子を示しています。

図 3. BBCDT
BBCDT

まとめ

もし皆さんが、Java コードの中の IFileIProject にアクセスしたのであれば、CDT モデルの要素で問題が起きることはないはずです。CModelCProject を含み、CProjectCSourceRoot を含んでいます。各 TranslationUnit は 1 つの C/C++ ソースファイルに対応するので、エディターはこうした要素にアクセスし、変更を加えることによって、CDTモデルと動作を行います。

強力さは複雑さを伴うものです。ここで述べた操作は詳しすぎるかもしれませんが、皆さんが独自の C/C++ エディターを構築しようとする際には役立つはずです。CDT の動作機構は、BBCDT のソースコードを見ると一層よくわかります。CDT の操作の実験として、実際にコードを追加し、削除し、そして修正してみるようにお勧めします。

CDT のモデルは、今後の記事で TranslationUnitWorkingCopyCEditor や UI クラスとの間の様々な相互動作を説明する中で、さらに明確になるはずです。第2 回では、Document がどのようにイベントを管理するか、パーティショニングはどのように行われるか、またパーティショニングによる構文色分けがどのように行われるか、などについて説明します。


ダウンロード

内容ファイル名サイズ
Part 1 source codeos-ecl-cdt1.zip574KB

参考文献

学ぶために

  • Eclipse.org で Eclipse CDT について調べてみてください。
  • CDT 開発チームのリーダー、Doug Schaefer による素晴らしいブログを読んでください。
  • Eclipse Foundation について、そしてその数多くのプロジェクトについて学んでください。
  • Eclipse プラットフォームへの素晴らしい入門記事として、「Eclipse Platform入門」を読んでください。
  • IBM developerWorks の Eclipse project resources を利用して、皆さんの Eclipse スキルを磨いてください。
  • developerWork には他にも Eclipse に関連する資料が豊富に用意されています。
  • developerWorks の Open source ゾーンを訪れてください。オープンソース技術を使った開発や、IBM 製品でオープンソース技術を使用するためのハウ・ツー情報やツール、プロジェクトの更新情報など、豊富な情報が用意されています。
  • developerWorks technical events and webcasts で最新情報を入手してください。

製品や技術を入手するために

  • Eclipse.org から Eclipse CDT をダウンロードしてください。
  • IBM alphaWorks に用意された、最新の Eclipse technology downloads を調べてみてください。
  • 皆さんの次期オープンソース開発プロジェクトを、IBM trial software を使って構築してください。ダウンロード、あるいは DVD で入手することができます。

議論するために

  • Eclipse newsgroups は、Eclipse を利用し、拡張することに関心を持つ人達のために、豊富なリソースを提供しています。
  • developerWorks blogs から developerWorks のコミュニティーに加わってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=236840
ArticleTitle=CDT ベースのエディターを構築する、第 1 回: C/C++ Development Tooling モデル
publish-date=09122006