パソコンでプログラミングしよう ウィンドウズC++プログラミング環境の構築
1.7.0.5(5)
自作ツール

統合開発環境Code::Blocksの機能補助として導入する自作ツールの使用方法を説明する。

C++プログラミング環境の構築目的で以下の自作ツールを公開する。これらはCode::BlocksのToolsメニューあるいはプレ/ポストビルドステップから利用される。

名称 実行ファイル 機能 タイプ
KGetText KGetText.exe GNU gettextの実行単純化 コンソール
KUdCheck KUdCheck.exe コンパイルビルドされるファイルの更新判断 コンソール
KAutoVer KAutoVer.exe バージョン番号の統一管理 GUIを持つコンソール
KGitWVer KGitWVer.exe Git for Windowsの実行単純化 GUIを持つコンソール

全てコンソールアプリケーションで標準出力する。オプションは起動時のコマンドラインで与えるが、KAutoVerとKGitWVerはGUIメインウィンドウとなるダイアログで起動後に変更または設定できる。標準出力は全てサイト作成者が自己理解するための英語風表記で、これは利用するCode::Blocksの[Tool Output]ウィンドウの表示がASCII文字に限定されている事を理由とする。ダイアログも標準出力とCode::Blocksとの統一感から英語風表記のままとする。

KGetText

GNU gettextツールチェーンの実行を単純化し、GetとEditと名付ける二つのコマンドに集約する。

コマンド オプション 機能
Get -g [ --get ] ソースコード/インクルードファイル(*.cpp、*.c、*.h)を解析してテキスト形式翻訳ファイル(*.po)を作成/更新する。
Edit -e [ --edit ] *.poを編集してからバイナリ形式翻訳ファイル(*.mo)を作成する。

ヘルプ表示(--help)する場合を除きどちらかのコマンドオプションは必須だが、同時指定はできない。翻訳対象の文字列を取得するファイルはプロジェクトディレクトリ(-d)内の*.cpp、*.c、*.hに制限される。翻訳対象の文字列を検索するキーワードはxgettextデフォルトと"_"に固定される。

オプション

--help
ヘルプを表示する。
-g [ --get ]
Getコマンドとしてxgettextとmsginit/msgmergeを実行する。xgettextは<output-dir>\messages.potという名称でgettextテンプレートファイル(potファイル)を作成する。<output-dir>\<lang-dir>\<target-base-name>.poという名称のテキスト形式翻訳ファイル(poファイル)が存在していない場合はmsginitがpotファイルから作成し、存在する場合はmsgmergeがpotファイルをpoファイルにマージする。poファイルが作成/更新された場合はEditコマンドに進むか終了するかをダイアログで尋ねる。
-e [ --edit ]
Editコマンドとしてpoファイルを編集してmsgfmtを実行する。poファイルエディタ(--editor)をpoファイルを読み込んだ状態で起動して編集する。エディタ終了でpoファイルが更新されかつ--no-msgfmtオプションが与えられていない場合、msgfmtが<output-dir>\<lang-dir>\<target-base-name>.moという名称のバイナリ形式翻訳ファイル(moファイル)を作成/更新する。
-d [ --directory ] arg (=.)
プロジェクトディレクトリ。翻訳対象の文字列を取得するファイルはこのディレクトリ内に制限される。デフォルトは現在のワーキングディレクトリ。
-o [ --output-directory ] arg (=bin)
出力ディレクトリのプロジェクトディレクトリ(-d)からの相対パス。potファイルはこのディレクトリに出力され、poファイルとmoファイルはそのサブディレクトリに出力される。サブディレクトリ名はロケール(-l)の最初2文字で構成する文字列で、これを<lang-dir>として参照する。
-t [ --target ] arg
poファイルとmoファイルのベースネームとして用いられるターゲット名で、通常はプロジェクト名が与えられる。デフォルトを持たず省略できない。
-l [ --locale ] arg (=ja_JP.UTF-8)
翻訳のターゲットとするロケールでll_CC.encodingという書式で与える。MSYS2定義のロケールでデフォルトはja_JP.UTF-8。
--gettext-directory arg (=C:\msys64\usr\bin)
GNU gettextツールがインストールされたディレクトリの絶対パス。デフォルトはC:\msys64\usr\bin。
--gettext-envlang arg (=ja_JP.UTF-8)
GNU gettextツールが実行される時に与えられる環境変数LANGの値。MSYS2定義ロケールでデフォルトはja_JP.UTF-8。
--editor arg (=C:\Windows\notepad.exe)
poファイルエディタ実行形式ファイルの絶対パス。デフォルトはウィンドウズのノートパッド(C:\Windows\notepad.exe)だが推奨しない。ノートパッドはUTF-8文字列を扱えるがファイル保存時にBOM(規格非準拠)を加えるため、そのままではmsgfmtがエラーを起こす。KGetTextは編集終了をエディタ終了で検知するため、エディタはファイル毎に独立したインスタンスでなければならない。この制約は--no-msgfmtオプションで緩和される。
--no-msgfmt
poファイルエディタ(--editor)がmoファイルを作成する機能がある場合に不要なmsgfmtの実行を抑止する。例えばPoeditは編集したpoファイルの保存時に自動的にmoファイルを作成するため、KGetTextはエディタ終了後にmsgfmgを起動する必要は無く、エディタはファイル毎に独立したインスタンスでなくとも良い。

詳解

MSYS2定義のロケールはPOSIX互換コンソールで確認できる。文字コード(encoding)は英数小文字のみに縮約されて例えばUTF-8はutf8と表示される。

user@THINKPAD-L430 MSYS ~
$ locale -a | grep ja
ja_JP
ja_JP
ja_JP.utf8
ja_JP.ujis
ja_JP@cjknarrow
ja_JP.utf8@cjknarrow
japanese
japanese.euc
japanese.sjis

ja_JP.CP932ロケールは存在しない一方でGNU gettextはja_JP.SJISロケールでCP932文字コードを選択する。文字コード変換ライブラリ(iconv)ではSJIS文字コードとCP932文字コードが異なっている(0x5Cが円マークかバックスラッシュ)点を改めて注意しよう。以下に環境変数LANGとロケール(-l)との組み合わせで作成されるpoファイルの言語(Language)、文字コード(Content-typeのcharset)、コメント文字列を示す。

LANG ロケール(-l) Language charset コメント
ja_JP.UTF-8 ja_JP.UTF-8 ja UTF-8 日本語
ja_JP ja EUC-JP 日本語
ja_JP.SJIS ja CP932 日本語
ja_JP.CP932 ja ASCII 英語
ko_KR.UTF-8 ko ASCII 英語
en_US.UTF-8 ja_JP.UTF-8 ja ASCII 英語
ja_JP ja EUC-JP 日本語
ja_JP.SJIS ja CP932 日本語
ja_JP.CP932 ja ASCII 英語
ko_KR.UTF-8 ko ASCII 英語
ko_KR.UTF-8 ja_JP.UTF-8 ja ASCII 英語
ja_JP ja EUC-JP 日本語
ja_JP.SJIS ja CP932 日本語
ja_JP.CP932 ja ASCII 英語
ko_KR.UTF-8 ko UTF-8 韓国語

存在しないja_JP.CP932ロケールはエラーなのでASCII文字コードを出力する。ja_JPロケールとja_JP.SJISロケールはLANGに関係なくEUC-CPとCP932を出力する。ja_JP.UTF-8ロケールはLANGと一致する場合のみUTF-8を出力し、そうでない場合はエラーでASCIIを出力する。すなわちGNU gettextでUTF-8文字コードを翻訳ターゲットとするにはLANGとロケールを一致させなければならない。

KUdCheck

ビルドターゲットに前回ビルド後に更新されたファイルがあるかどうかをチェックし、ファイルのタイムスタンプをデータファイルに記憶する。前回のビルドターゲットが異なる場合は必ずファイル更新があったものとして扱う。CheckとUpdateと名付ける2ステップで構成する。

ステップ オプション 機能
Check -c [ --check-only ] ファイル更新を確認する。
Update -u [ --update-only ] タイムスタンプデータファイルを更新する。

これらのオプションは重複指定できる。どちらも与えない場合は重複指定(-c -u)と解釈する。終了コードを示す。

終了コード 意味
0 ファイルが更新された。
1 エラーが発生した。
2 -cオプションでファイルは更新されていない。
3 -uオプションでファイルは更新されていない。

バッチファイル、Code::BlocksのToolsメニューおよびプレ/ポストビルドステップは終了コードを判断してファイル更新時のみの処理を行う。

オプション

--help
ヘルプを表示する。
-d [ --directory ] arg (=.)
プロジェクトディレクトリ。デフォルトは現在のワーキングディレクトリ。
-c [ --check-only ]
更新確認するファイルのタイムスタンプとタイムスタンプデータファイル(-f)の正規タイムスタンプ記憶値を比較する。もし更新があればデータファイルの一時タイムスタンプ記憶値を更新して終了コード0を設定し、更新が無ければ一時記憶値を削除して終了コード2を設定する。
-u [ --update-only ]
一時タイムスタンプ記憶値があればそれを正規記憶値へコピーし、一時記憶値を削除して終了コード0を設定する。一時記憶値が無ければ終了コード3を設定する。
-t [ --target ] arg
タイムスタンプデータファイル(-f)の記憶領域を指定する名前。デフォルトを持たず省略できない。これにビルドターゲット名を指定すればターゲット毎に独立して更新確認を行える。"_temporary"と"_prevtarget"は内部利用に予約されて使用できない。
-f [ --file ] arg (=timestamps.tmp)
タイムスタンプデータを記憶するデータファイル名でプロジェクトディレクトリ(-d)からの相対パス。データファイルは-tで指定される複数の記憶領域を持ち、各記憶領域はそれぞれが正規タイムスタンプ記憶値と一時タイムスタンプ記憶値を持つ。
-i [ --inspecting-files ] arg
更新確認するファイル名で複数指定が可能。オペコード-iあるいは--inspecting-filesは省略可能。ファイル名はプロジェクトディレクトリ(-d)からの相対パスでワイルドカードを含むことができる。

詳解

KUdCheckはKAutoVerと組み合わせて使用する。KAutoVerはファイル更新の無いビルドターゲットでも統一管理対象ファイルに書き込まれるファイルバージョン番号を更新して不要なビルドを行うため、事前にKUdCheckでファイル更新をチェックし終了コード0の場合のみKAutoVerを実行させる。終了コード2あるいは3の場合はKAutoVerを実行させないが、コマンドプロンプトのエラー表示を避けるため最後に0にリセットする。if not ERRORLEVEL 2 exit 1がそのリセットコマンドとして機能するが直感的でない。これらコマンドはコマンドシェル構文の論理オペレータ(&&、||)で組み合わされる。

通常はビルドターゲットのプレ/ポストビルドステップに定義してバージョン番号(例えばビルド回数)を自動更新する。-cおよび-uオプションの設定でバージョン番号更新をビルド前で行うかビルド後で行うかを選択できる。ビルトイン変数$(TARGET_NAME)でビルドターゲット名を取得し、グローバル変数$(#codeblocks.bin)で自作ツール実行形式ファイルのディレクトリを取得する。二重の角括弧[[...]]はスクリプト展開(Code::Block Manual 3.3 Script expansion)でビルドターゲットに属する全てのファイルをリストする。

バージョン更新 ステップ 実行
ビルド前に行う プレビルド cmd /c $(#codeblocks.bin)\KUdCheck -t $(TARGET_NAME) [[ local t=GetProjectManager().GetActiveProject().GetBuildTarget(ReplaceMacros(_T("$(TARGET_NAME)")));for (local i=0;i<t.GetFilesCount();++i) {print(t.GetFile(i).relativeFilename+_T(" "));} ]] && $(#codeblocks.bin)\KAutoVer -s $(TARGET_NAME) -i 0.0.0.0(1) --silent || if not ERRORLEVEL 2 exit 1
ポストビルド -
ビルド後に行う プレビルド cmd /c $(#codeblocks.bin)\KUdCheck -c -t $(TARGET_NAME) [[ local t=GetProjectManager().GetActiveProject().GetBuildTarget(ReplaceMacros(_T("$(TARGET_NAME)")));for (local i=0;i<t.GetFilesCount();++i) {print(t.GetFile(i).relativeFilename+_T(" "));} ]] && $(#codeblocks.bin)\KAutoVer -s $(TARGET_NAME) --silent || if not ERRORLEVEL 2 exit 1
ポストビルド cmd /c $(#codeblocks.bin)\KUdCheck -u -t $(TARGET_NAME) && $(#codeblocks.bin)\KAutoVer -s $(TARGET_NAME) --no-update-target -i 0.0.0.0(1) --silent || if not ERRORLEVEL 2 exit 1

KAutoVer

バージョン番号をバージョン番号データファイル(-f)から読み込み、更新指示(-i)、ソフトウェアステータス指定(-s)および日付指定(--date)に基づきバージョン番号を更新する。--no-update-targetオプションが無ければテンプレートファイルディレクトリ(-t)とその階層下ディレクトリにある全テンプレートファイルのプレースホルダー文字列を更新バージョン番号で置換したバージョン番号設定ファイルを作成し、プロジェクトディレクトリ(-d)へ相対パスを維持して保存する。バージョン番号設定ファイルは--no-read-onlyオプションが無い限り変更不可属性を持つ。オプションは実行直後に表示するダイアログで変更可能で、--silentオプションはそのダイアログ表示を抑止する。

終了コード 意味
0 実行に成功した。
1 エラーが発生した。
2 ダイアログで実行をキャンセルした。

バージョン番号データファイルを新しく作成するときにプロジェクト固有のGUID文字列を生成してファイルに保存する。これは固定値でオプションやダイアログで変更できない。アプリケーション固有IDとして利用し主にInno SetupスクリプトのAppId値に用いられる。

オプション

--help
ヘルプを表示する。
-v [ --version ]
バージョン番号データファイルのバージョンステータスを表示する。
-d [ --directory ] arg (=.)
プロジェクトディレクトリ。バージョン番号設定ファイルが保存されるディレクトリ。デフォルトは現在のワーキングディレクトリ。
-f [ --file ] arg (=autoversion.dat)
バージョン番号に関する情報を保存するバージョン番号データファイルで、プロジェクトディレクトリ(-d)からの相対パス。デフォルトはautoversion.data。
-t [ --template ] arg (=autoversion-template)
テンプレートファイルディレクトリで、プロジェクトディレクトリ(-d)からの相対パス。指定するディレクトリが存在せず、かつバージョン番号データファイル(-f)が存在する場合はデータファイルが記憶する前回のディレクトリを用いる。ディレクトリおよび階層下ディレクトリに収められるテンプレートファイルはUTF-8文字コードでプレースホルダー文字列を持ち、バージョン番号に置換してバージョン番号設定ファイルとしてプロジェクトディレクトリへ保存される。デフォルトはautoversion-template。
-i [ --increment ] arg (=0.0.0.0(0))
バージョン番号更新を指示する文字列でフォーマットは<major>.<minor>.<build>.<revision>(<build-count>)。以下において角括弧[...]は省略可能オプション、縦棒...|...は排他オプションを表現するものとする。<major>など各番号は[A|R]<number>[<range>]で更新指示する。<range>は番号範囲を指定する文字列で開き角括弧"["で開始し閉じ角括弧"]"で終了する。この角括弧は省略可能オプションを表示する[...]と混乱するためダブルコーテーションで囲んで表記すれば、<range>は"["[<lower-limit>-]<upper-limit>"]"である。先頭のAあるいはRを与えない場合、番号は<number>だけ増加する。Aを与える場合、番号を<number>に置き換える。Rを与える場合、番号を1以上最大<number>だけランダムに増加する。<upper-limit>を与える場合に番号が<upper-limit>を超えると、<lower-limit>を与えていなければ0にリセットして上位番号を1増加する。<lower-limit>を与えていれば<lower-limit>にリセットして上位番号を1増加する。例えば0.0.0.1(R5[1-10])はリビジョンを1増加しビルド回数をランダムに最大5増加し、ビルド回数が10を超えると1にリセットしてリビジョンをさらに1増加する。デフォルトは0.0.0.0(0)。
-s [ --status ] arg
ソフトウェアステータス。このオプションを与えず、かつバージョン番号データファイル(-f)が存在する場合はデータファイルが記憶する前回の値を用いる。フォーマットは<status>[(<abbreviation>]。(<abbreviation>)が省略されて<status>が以下のいずれかである場合、<abbreviation>は事前定義された値を用いる。空文字列を囲む丸括弧()を<status>に続けて与える場合は、<abbreviation>が事前定義されている場合でも空文字列を明示的に与える。
ステータス 定義済み省略形
Debug d
Release r
Debug32 d32
Release32 r32
Debug64 d64
Release64 r64
--date arg (=today)
日付で、boost::gregorian::from_string関数が日付として認識する文字列(例えばYYYY/MM/DD)、あるいはtoday、あるいはno-change。todayは今日の日付を用い、no-changeはバージョン番号データファイル(-f)が記憶する前回の値を用いる。
--silent
ダイアログによる確認を省略して実行する。これを与えない場合は実行前にダイアログが表示されほとんどのオプションを変更できる。
-m [ --messagebox ]
メッセージ出力を標準出力からダイアログに切り替える。
--no-update-target
バージョン番号データファイル(-f)のみを更新する。バージョン番号設定ファイルは作成または更新しない。
--no-read-only
バージョン番号設定ファイルを変更不可属性で作成しない。

詳解

テンプレートファイルに用いるプレースホルダー文字列を一覧する。

プレースホルダー 置換対象
#{DATE} 16
#{MONTH} 12
#{MONTH_SHORT_NAME} 月(短い英語名) Dec
#{YEAR} 2019
#{YEAR_2DIGIT} 年(2桁表記) 19
#{STATUS} ソフトウェアステータス Release32
#{STATUS_SHORT} ステータス省略形 r32
#{MAJOR} メジャーバージョン 0
#{MINOR} マイナーバージョン 0
#{BUILD} ビルドナンバー 5
#{REVISION} リビジョン 9
#{BUILD_COUNT} ビルド回数 72
#{GUID} プロジェクト固有のGUID文字列 410eb0f2-2b7f-4b7c-b47f-490603303911

KGitWVer

Git for Windowsの実行を単純化する。ヘルプ表示(--help)あるいはステータス表示(-s)以外でリポジトリへのコミットを行う。--autoversionオプションでKAutoVerのバージョン番号データファイルを参照してコミットメッセージ、タグ、アーカイブファイル名にバージョン番号を反映できる。オプションは実行直後に表示するダイアログで変更可能で、--silentオプションはそのダイアログ表示を抑止する。

終了コード 意味
0 実行に成功した。
1 エラーが発生した。
2 ダイアログで実行をキャンセルした。

リポジトリを持たないプロジェクトディレクトリ(-d)で実行すると最初に致命的エラー(fatal error)を表示するが、KGitWVerはリポジトリを自動作成するためこのエラーは無視して良い。管理対象ファイルが未更新(working tree clean)でかつ--amendオプションを持たない場合コミットは失敗する。コミット失敗時はタグ(-t)やアーカイブファイル(\–archive)は作成されない。

オプション

--help
ヘルプを表示する。
-s [ --status ]
リポジトリのステータスを表示する。
-d [ --directory ] arg (=.)
Git for Windowsが管理するプロジェクトディレクトリ。デフォルトは現在のワーキングディレクトリ。ディレクトリがリポジトリを持たない場合は作成する。
-g [ --git-exe ] arg (=C:\Program Files\Git\cmd\git.exe)
Git for Windowsの実行形式ファイル。デフォルトはC:\Program Files\Git\cmd\git.exe。
-c [ --commit-message ] arg
コミットメッセージ。デフォルトは空文字列だが--amendオプションが無いと空文字列ではコミットに失敗する。--autoversionオプションがあればargの含むプレースホルダー文字列をバージョン番号に置き換える。
-t [ --tag ] arg
タグを設定してコミットする。そのタグが既存の場合は新しいコミットへ移動する。--autoversionオプションがあればargの含むプレースホルダー文字列をバージョン番号に置き換える。
--archive [=arg(=archive.zip)]
アーカイブファイルを作成してコミットする。アーカイブファイル名はプロジェクトディレクトリ(-d)からの相対パスでデフォルトはarchive.zip。--autoversionオプションがあればargの含むプレースホルダー文字列をバージョン番号に置き換える。
--autoversion [=arg(=autoversion.dat)]
コミットメッセージ(-c)、タグ(-t)、アーカイブファイル名(--archive)のプレースホルダー文字列をバージョン番号に置き換える。バージョン番号データファイルはプロジェクトディレクトリ(-d)からの相対パスでデフォルトはautoversion.dat。
-a [ --amend ]
コミットに--amendオプションを加え、新たなコミットを作成せずに現在のコミットを修正する。コミットメッセージ(-c)があればコミットメッセージは変更され、そうでなければ変更されない。
--silent
ダイアログによる確認を省略して実行する。これを与えない場合は実行前にダイアログが表示されほとんどのオプションを変更できる。
-m [ --messagebox ]
メッセージ出力を標準出力からダイアログに切り替える。

詳解

コミットメッセージ(-c)、タグ(-t)、アーカイブファイル名(--archive)のプレースホルダー文字列はKAutoVerと共通である。

ビルドオプション

本サイトからダウンロードする自作ツールのアーカイブファイルは各ツールのCode::Blocksプロジェクトファイルを同梱する。ビルドオプションの概要をまとめる。

  • 32ビットビルドでターゲットはDebug32(デバッグ版)とRelease32(リリース版)。
  • Release32のみ生成する実行形式ファイルをC:\Users\user\codeblocks\binへコピーする。
  • ライブラリはダイナミックリンク

ダイナミックリンクなのでPATHがC:\msys64\mingw32\binを含む、あるいは実行形式ファイルをC:\msys64\mingw32\binに配置する必要がある。Code::Blocks内なら統合開発環境のカスタマイズ(1)がPATHを設定して問題ない。依存するダイナミックリンクライブラリが変更される可能性があるため、MSYS2をアップデートしたら全てのツールをリビルドする。スタティックリンクとするにはコンパイルオプション-staticを加えかつリンクライブラリを全てスタティック用に変更するが、結果として他のスタティックリンクライブラリを追加する必要が生じる場合がある。