ルーチン/クラスの一括コンパイルの結果からエラー情報を取得する方法
これは InterSystems FAQ サイトの記事です。
ターミナルでルーチンやクラスのコンパイルを行う際、コンパイル結果が画面に表示されるのでエラーが発生した場合でも確認しやすいですが、一括コンパイルの場合は、大量のコンパイル結果の中にエラー情報が含まれてしまうためエラー情報だけを取得したい場合には少し工夫が必要です。
以下、ルーチン/クラスの一括コンパイル時の結果からエラー情報を取得する方法をご紹介します。
ルーチンの場合
ネームスペースにあるルーチンをターミナルで一括コンパイルするには、%Library.Routine クラスの CompileAll() メソッドを使用します。
以下実行例は、USERネームスペースにあるルーチンを一括コンパイルした結果です。TestRoutine1でコンパイルエラーが発生しています。
USER>do##class(%Routine).CompileAll()
Compiling in namespace USER at 11:50:47
Routine1.MAC TestRoutine1.MAC
TestRoutine1.MAC - Errors compiling routine
TestRoutine1.INT(3) : Error 8: <NOLINE> : ' do sub3()'
2 routines compiled with 1 errors at 11:50:47 in 00:00:00.030
USER>大量にルーチンがある場合、出力結果が流れて画面から消えてしまうため、カレントデバイスに出力されている内容をファイル保存し、保存したファイルの中からエラー情報を取得するようにします。
1) コンパイル結果をファイルに保存する
CompileAll() メソッドの第2引数にファイル名をフルパスで指定します。
このメソッドは、第2引数に指定したデバイスがオープンされている場合、そのデバイスにログを書き込みます。
そのため、一旦ファイルを新規書き込みモードでオープンします(OPENコマンドを使用します)。
// ログファイルのフルパスを変数に設定しますset log="C:\temp\result.log"//ファイルを新規書き込みモードでオープンしますopen log:"NWS"//第2引数にログ出力するファイル名を指定し、一括コンパイルを実行します。do##class(%Routine).CompileAll(,log)
//ファイルをクローズします。close log
2) 1)で作成したファイルからエラー情報を取得する。
ファイルをオープンし、エラー発生時の文字列「Errors compiling routine」が含まれている場合にルーチン名を取り出して変数に設定する例をご紹介します。
//文字列ファイル操作用のインスタンスを生成set file=##class(%Stream.FileCharacter).%New()
//ファイルとのリンク付けdo file.LinkToFile("c:\temp\result.log")
//ファイルの終わりを検出するまで読み取りながら情報抽出//ファイルの終わりが検出されるとAtEndプロパティに1が設定されるwhile file.AtEnd=0 {
set reco=file.ReadLine()
//読み取った行にエラー字の文字列が含まれる場合if reco["Errors compiling routine" {
//スペース区切りの1番目にルーチン名が含まれているので取得set rtn=$piece(reco," ",1)
}
//ルーチン名が空だったら次のループへ移動if$get(rtn)="" {
continue
}
//ローカル変数の添え字にルーチン名をセットset val(rtn)=""
}
zwrite valターミナルで実行する場合
set file=##class(%Stream.FileCharacter).%New()
do file.LinkToFile("c:\temp\result.log")
while file.AtEnd=0 { set reco=file.ReadLine() if reco["Errors compiling routine" { set rtn=$piece(reco," ",1)} if$get(rtn)="" { continue } set val(rtn)=""}
zwrite val
クラスの場合
ネームスペースにあるクラスをターミナルで一括コンパイルするには、%SYSTEM.OBJクラスのCompileAll()メソッドを使用します。
以下実行例は、USERネームスペースにあるクラスを一括コンパイルした結果で、Dummy.ErrorClass1でコンパイルエラーが発生しています。
USER>do$system.OBJ.CompileAll("ck")
04/20/202312:17:49 に修飾子 'ck' でコンパイルを開始しました。
エラー #5373: クラス 'Dummy.ErrorClass1:property:XYZ' が使用するクラス '%Library.Strig' は、存在しません
Skip class Dummy.ErrorClass1
, 72 クラスをコンパイル中
クラスのコンパイル中 CookBook.Class1
クラスのコンパイル中 A.b3
クラスのコンパイル中 A.B1
《省略》
ルーチンのコンパイル中 F4.GoldMember.1
クラスのコンパイル中 MyApp.MyService.Test
ルーチンのコンパイル中 MyApp.MyService.Test.1
1.091s のコンパイル中に 1 エラーを検出しました。第2引数を参照渡しで指定するとエラー情報が配列変数として設定されます。
USER>do$system.OBJ.CompileAll("ck",.log)
USER>zwrite log
log=1
log(1)="エラー #5373: クラス 'Dummy.ErrorClass1:property:XYZ' が使用するクラス '%Library.Strin' は、存在しません"
log(1,"caller")="findalldependencyclasses+149^%occDepend"
log(1,"code")=5373
log(1,"dcode")=5373
log(1,"domain")="%ObjectErrors"
log(1,"namespace")="USER"
log(1,"param")=2
log(1,"param",1)="%Library.Strin"
log(1,"param",2)="Dummy.ErrorClass1:property:XYZ"
log(1,"stack")=$lb("e^findalldependencyclasses+149^%occDepend^2","e^findalldependencyclasses+58^%occDepend^1","e^findalldependencyclasses+8^%occDepend^1","e^IncludeClasses+44^%occCompile^1","e^CompileList+59^%occCompile^1","e^CompileList+23^%apiOBJ^1","e^CompileAll+15^%apiOBJ^1","e^zCompileAll+1^%SYSTEM.OBJ.1^1","d^^^0")複数エラーが発生した場合は、ログ用に指定した変数直下にエラー個数が設定されます。
エラーメッセージだけを取り出す方法は以下の通りです。
for i=1:1:log { write log(i),! }マッピングされているクラス・ルーチンのコンパイル方法については、以下開発者コミュニティの記事をご参照ください。