Quartus® II Tcl の例: ファイル内のバージョンナンバーのインクリメント

author-image

投稿者:

プロジェクトのバージョンナンバーを管理する 1 つの方法は、コンパイルのたびにファイル内のナンバーをインクリメントすることです。このタスクを実行するには、スクリプトがファイルを解析してナンバーを見つけてインクリメントし、新しいナンバーでファイルをリライトする必要があります。ファイルが短く、ナンバー以外にほとんど何も書かれていない場合は、スクリプトが実行されるたびに新しいファイルをゼロから書き出すことができます。ただし、大きいデザインファイルの場合は、最初から新しいファイルを書き出すのではなく、バージョンナンバーの行を編集する方が実用的な場合もあります。

ナンバーの確認

このスクリプトでは、正規表現を使ってファイル内のナンバーを探します。ナンバーのある行は固有のフォーマットでなければならず、そうでなければ複数の行が正規表現にマッチしてしまいます。固有のフォーマットを作る方法の 1 つは、ナンバーのある行に固有のコメントを入れることです。正規表現に、その固有のコメントを含めることができます。以下の例は、デザインファイルのバージョンナンバーの行に特殊なコメントが含まれている場合に、それにマッチする正規表現 Tcl コマンドです。

デザインファイル行

data_out <= 16'h41; // デザイン・バージョン・ナンバー

正規表現

regexp {^\s+data_out <= \d+'h([[:xdigit:]]+); // デザイン・バージョン・ナンバー$} \ $line match version_number

パターン ([[:xdigit:]]+) は、少なくとも 1 ディジットの 16 進数にマッチし、マッチ変数 version_number に保存されます。

ナンバーのインクリメント

Tcl では、16 進数をインクリメントできます。Tcl では、16 進数は先頭に 0x を付けて表示します。バージョンナンバーが 0x で始まらない場合は、ナンバーを 10 進数に変換してからインクリメントした方が楽かもしれません。以下のコマンドは、16 進数文字列を 10 を底として変換し、インクリメントした後で 16 進数に戻す例を示します。

set hex_value "AA"
scan $hex_value "%x" decimal_value
incr decimal_value
set new_hex_value [format "%X" $decimal_value]
# $new_hex_value はここで "AB" になります

ファイルのリライト

デザインファイルが短く、バージョンナンバーだけの情報しか含まれていない場合は、一連の puts コマンドを使って、インクリメントされたナンバーの新しいファイルを書き出すことができます。

デザインファイルが長い場合、Tcl スクリプトでファイルの内容をハードコーディングするのは現実的ではないため、通常はバージョンナンバーの行だけを変更するのが簡単です。

以下のプロシージャーは、デザインファイルを解析し、バージョン情報を使って行を更新します。正規表現にマッチしない行は、変更されずに新しいファイルに書き込まれます。正規表現にマッチする行は、バージョンナンバーがインクリメントされ、新しいファイルに書き込まれます。

proc update_version_number { input_file output_file} {

    # 入力ファイルを開けない場合は、エラーを返します。
    if { [catch {open $input_file} input] } {
        return -code error $input
    }

    # 出力ファイルを開けない場合は、エラーを返します
    if { [catch {open $output_file w} output] } {
        return -code error $output
    }

    # 入力ファイルを 1 行ずつ読み込みます
    while {-1 != [gets $input line] } {

        # この正規表現は、Web ページの先頭付近にある
        # デザインファイルの行に固有のものです。
        # ファイルに合わせて適宜変更する必要があります。
        if { [regexp {^\s+data_out <= \d+'h([[:xdigit:]]+); // Design Version Number$} \ $line match version_number] } { # 16 進数のバージョンナンバーを底 10 で変換してインクリメントします。 scan $version_number "%x" decimal_value incr decimal_value set new_version_number [format "%X" $decimal_value] # 新しいバージョンナンバーを古いものと置き換えます regsub h${version_number} $line h${new_version_number} line } # 新しいファイルにこの行を書き出します puts $output $line } close $input close $output }   </pre>

Tcl スクリプトでは、以下の例のようにプロシージャーを呼び出すことができます。この例では、システムのコマンドプロンプトで Tcl スクリプトを実行し、更新するファイル名をスクリプトの引数として指定することを想定しています。

set file_name [lindex $quartus(args) 0]
set output_file_name ${file_name}.updated_version_number

if { [catch { update_version_number $file_name $output_file_name } res] } {
    post_message -type critical_warning "Could not update version number: $res"
} else {

    if { [catch { file rename -force $output_file_name $file_name } res ] } {
        post_message -type critical_warning \
            "Could not update version number: $res"
    }
}