Doxygen latest release v1.8.11 - last update Mon Oct 25 2021

外部インデックスと検索

はじめに

バージョン1.8.3で、doxygenは外部インデックスツールと検索エンジンを使ってHTMLを検索できるようになりました。 これには、いくつか利点があります。

  • 大きなプロジェクトでは、doxygenに組込済みの検索エンジンよりもパフォーマンスの点で、大きな利点があります。doxygenは、単純な索引づけアルゴリズムを用います。
  • 複数プロジェクトの検索データを一つのインデックスに結合でき、それによって、複数のdoxygenプロジェクト全体を検索できます。
  • 検索インデックスに、doxygenでは生成しないほかのウェブページのデータを検索インデックスに追加できます。
  • 検索エンジンはウェブサーバー上で動く必要がありますが、一方クライアントはウェブページをローカルにブラウジングできます。

自分でインデックス作成や検索エンジンを書かなくてよいように、doxygenは、各アクション用のサンプルツールを提供します。データインデックス作成には doxyindexer を、インデックス検索用には doxysearch.cgi を提供します。

データの流れを以下の図に示します。

extsearch_flow.png
外部検索でのデータの流れ
  • doxygen は生の検索データを作成します。
  • doxyindexer がそのデータを索引付けして、検索データベース doxysearch.db に書き込みます。
  • ユーザが、doxygenが作成したHTMLページから検索を実行すると、CGIバイナリの doxysearch.cgi が起動されます。
  • doxysearch.cgi ツールは、データベースにクエリーを行い、その結果を返します。
  • ブラウザが検索結果を表示します。

設定

最初のステップは、ウェブサーバーを通して検索エンジンを使えるようにすることです。 doxysearch.cgi を使うのであれば、CGI バイナリをウェブサーバーから入手可能にするということです(つまり、http:で始まるURLを使ってブラウザから実行できるように)。

ウェブサーバーのセットアップ方法は、このドキュメントの範囲外です。しかし、Apacheをインストール済みであれば、doxygenの bin ディレクトリから Apache ウェブサーバーの cgi-bin ディレクトリへ、doxysearch.cgi をコピーするだけですみます。詳しくは、apache ドキュメント をお読みください。

doxysearch.cgi が使えるかどうかテストするには、ウェブブラウザを起動して、バイナリへのURLを入力して、?test を最後に付け加えてください。

http://yoursite.com/path/to/cgi/doxysearch.cgi?test

次のようなメッセージが出るはずです。

Test failed: cannot find search index doxysearch.db

Internet Explorer であれば、ファイルをダウンロードするよう促され、このメッセージが出ます。

doxysearch.db は作成もインストールもしていないので、テストが失敗するのはこのためです。これを修正する方法は、次のセクションで説明します。

次のセクションに行く前に、設定ファイルで、上のURL(?test は省いて)を SEARCHENGINE_URL タグに加えてください。

SEARCHENGINE_URL = http://yoursite.com/path/to/cgi/doxysearch.cgi

単一のプロジェクトインデックス

外部検索オプションを使うには、設定ファイルで、以下のオプションを有効にしてください。

SEARCHENGINE           = YES
SERVER_BASED_SEARCH    = YES
EXTERNAL_SEARCH        = YES

これで、doxygenは、出力ディレクトリ(OUTPUT_DIRECTORY で設定します)に searchdata.xml ファイルを生成します。SEARCHDATA_FILE で、ファイル名(と場所)を変更できます。

次のステップは、生の検索データをインデックスに入れ込み、効率的な検索ができるようにします。この作業には、doxyindexer を使えます。コマンドラインから実行するだけです。

doxyindexer searchdata.xml

これにより、doxysearch.db というディレクトリが作られます。中にいくつかファイルが含まれます。デフォルトで、このディレクトリはdoxyindexerが起動された場所につくられますが、-o オプションを使って変更できます。

doxysearch.cgi の場所と同じディレクトリに doxysearch.db ディレクトリをコピーしてください。そして、ブラウザで次のURLを再テストしてください。

http://yoursite.com/path/to/cgi/doxysearch.cgi?test

すると、次のメッセージが出ます。

Test successful.

これで、HTML出力から単語やシンボルの検索が可能になります。

複数プロジェクトのインデックス

複数のプロジェクトがあって、関連がある場合は、どのプロジェクトのドキュメント内からも、すべてのプロジェクトにある単語を検索できるようにするほうがいいでしょう。

これを可能にするには、全プロジェクトの検索データを単一のインデックスに結合することです。例えば、AとBというプロジェクトがあって、searchdata.xml が project_A と project_B ディレクトリに生成されます。そして次のように実行します。

doxyindexer project_A/searchdata.xml project_B/searchdata.xml

次に、その結果できる doxysearch.dbdoxysearch.cgi があるディレクトリにコピーしてください。

searchdata.xml ファイルには、絶対パスやリンクが含まれません。複数プロジェクトからの検索結果を、どうやって正しいドキュメント・セットにリンク・バックさせることができるでしょうか? EXTERNAL_SEARCH_IDEXTRA_SEARCH_MAPPINGS オプションが、ここで活動を開始します。

それぞれのプロジェクトを識別するには、各プロジェクトに EXTERNAL_SEARCH_ID を使ってユニークなIDをセットする必要があります。

検索結果を正しいプロジェクトにリンクするため、EXTRA_SEARCH_MAPPINGS タグを使って、プロジェクトごとにマッピングを定義する必要があります。このオプションで、他のプロジェクトのIDから、そのプロジェクトのドキュメントの(相対的な)場所へのマッピングを定義できます。

設定ファイル内でのプロジェクトA,Bに関連する箇所は、次のようになります。まずプロジェクトAは、

project_A/Doxyfile
------------------
EXTERNAL_SEARCH_ID    = A
EXTRA_SEARCH_MAPPINGS = B=../../project_B/html

次にプロジェクトBは、

project_B/Doxyfile
------------------
EXTERNAL_SEARCH_ID    = B
EXTRA_SEARCH_MAPPINGS = A=../../project_A/html

これらの設定により、プロジェクトA,Bは同じ検索データベースを共有できます。そして検索結果は、正しいドキュメント・セットにリンクするようになります。

インデックスの更新

ソース・コードを変更したら、doxygenを実行してドキュメントを再度更新しなければなりません。外部検索機能をお使いの場合は、doxyindexer を再実行して検索データも更新する必要があります。この処理を簡単にするため、doxygenとdoxyindexerの呼び出しをスクリプトにまとめることが可能です。

プログラミング・インタフェース

前節までは、インデックスと検索を行うために、doxyindexerdoxysearch.cgi を使用していると仮定してきました。しかし、オリジナルのインデックスと検索ツールを書くことも可能です。

このためには、次の3インタフェースが重要です。

  • インデックスツールの入力フォーマット
  • 検索エンジンの入力フォーマット
  • 検索エンジンからの出力フォーマット

次以降のセクションでは、これらのインタフェースを詳しく説明します。

インデックスツールの入力フォーマット

doxygenが作成する検索データは、Solr XML インデックスメッセージのフォーマットに従います。

インデックスツールの入力は、XMLファイルで、<add> タグ一つと <doc> タグ複数からなり、<doc> タグは <field> タグ複数からなります。

docノード一つの例を挙げます。一つのメソッドに対する検索データとメタデータが含まれます。

<add>
  ...
  <doc>
    <field name="type">function</field>
    <field name="name">QXmlReader::setDTDHandler</field>
    <field name="args">(QXmlDTDHandler *handler)=0</field>
    <field name="tag">qtools.tag</field>
    <field name="url">de/df6/class_q_xml_reader.html#a0b24b1fe26a4c32a8032d68ee14d5dba</field>
    <field name="keywords">setDTDHandler QXmlReader::setDTDHandler QXmlReader</field>
    <field name="text">Sets the DTD handler to handler DTDHandler()</field>
  </doc>
  ...
</add>

各フィールドにはnameがついています。次のようなフィールド名がサポートされます。

  • type: 検索エントリの種類: source, function, slot, signal, variable, typedef, enum, enumvalue, property, event, related, friend, define, file, namespace, group, package, page, dir
  • name: 検索エントリの名前。メソッドの場合、メソッドの修飾名、クラスの場合、クラス名、など。
  • args: 引数リスト (関数やメソッドの場合)
  • tag: このプロジェクトに使われているタグファイルの名前
  • url: このエントリのHTMLドキュメントへの(相対的)URL
  • keywords: エントリを代表する重要な単語。キーワード検索する際、検索結果内でのランクが高いエントリでないといけません。
  • text: 要素のドキュメント。単語だけで、マークアップは使用できません。
覚え書き
XMLファイルはサイズがかなり大きくなる可能性があるので、SAX ベースのパーサーで処理することをお勧めします。

検索URLのフォーマット

doxygenが生成するHTMLページから検索エンジンが起動されるとき、たくさんの引数がquery stringを使って渡されます。

次のフィールドを渡します。

  • q: ユーザが入力するクエリー・テキスト
  • n: 要求する検索結果の数
  • p: 結果を返却する検索ページの数。各ページに n の値がつきます。
  • cb: コールバック関数の名前。JSON with paddingに使います。次のセクションを参照してください。

検索結果の完全なリストから、[n*p - n*(p+1)-1] の範囲が返却されます。

クエリーの例を示します。

http://yoursite.com/path/to/cgi/doxysearch.cgi?q=list&n=20&p=1&cb=dummy

この例は、単語'list' (q=list)のクエリ、検索結果を20要求(n=20)、結果の番号20から始まる(p=1)、コールバック 'dummy' (cb=dummy)を使います。

覚え書き
これらの値は、URL エンコードされているため、使う前にデコードされなければなりません。

検索結果のフォーマット

前のサブセクションで説明したとおり、検索エンジンを起動すると結果を返却してきます。そのフォーマットは、JSON with paddingで、基本的に関数呼び出しにラップされたjavascriptの構造体です。関数の名前は、コールバックの名前(クエリ内の cb フィールドで渡されます)です。

前のサブセクションで説明した例では、返却の主構造は、以下のようになります。

dummy({
  "hits":179,
  "first":20,
  "count":20,
  "page":1,
  "pages":9,
  "query": "list",
  "items":[
  ...
 ]})

フィールドの意味を説明します。

  • hits: 検索結果の全体数(要求数を超えるかもしれません)
  • first: 最初に返却された結果のインデックス: $\min(n*p,\mbox{\em hits})$
  • count: 返却された結果の実数: $\min(n,\mbox{\em hits}-\mbox{\em first})$
  • page: 結果のページ番号: $p$
  • pages: ページの全体数: $\lceil\frac{\mbox{\em hits}}{n}\rceil$.
  • items: 結果ごとの検索データを含む配列

items 配列の要素がどのようなものを示す例を挙げます。

{"type": "function",
 "name": "QDir::entryInfoList(const QString &nameFilter, int filterSpec=DefaultFilter, int sortSpec=DefaultSort) const",
 "tag": "qtools.tag",
 "url": "d5/d8d/class_q_dir.html#a9439ea6b331957f38dbad981c4d050ef",
 "fragments":[
   "Returns a <span class=\"hl\">list</span> of QFileInfo objects for all files and directories...",
   "... pointer to a QFileInfoList The <span class=\"hl\">list</span> is owned by the QDir object...",
   "... to keep the entries of the <span class=\"hl\">list</span> after a subsequent call to this..."
 ]
},

このような要素のフィールドには次の意味があります。

  • type: 要素の種類: 生検索データ内では、"type" という名のフィールド
  • name: 要素の名前: 引数リストを含む。生検索データ内では、"name" と "args" という名のフィールド
  • tag: タグファイルの名前: 生検索データ内では、"tag" という名のフィールド
  • url: ドキュメントへの(相対的)URLの名前: 生検索データ内では、"url" という名のフィールド
  • "fragments": 検索に使った単語を含む、0以上のテキスト断片の配列 出力内で強調するため、<span class="hl"></span> タグで囲みます。
のセクションに行く / インデックス に戻る

This page was last modified on Mon Oct 25 2021.
© 1997-2021 Dimitri van Heesch, first release 27 oct 1997.
© 2001 OKA Toshiyuki (Japanese translation).
© 2006-2021 TSUJI Takahiro (Japanese translation).
© 2006-2014 TAKAGI Nobuhisa (Japanese translation).