RPG

134. 条件つきコンパイルとリリース/ディパッグの分離

RPG400 (ILE-RPG) ではコンパイラーに外部から条件を与えてコンパイルすることができる。
CRTRPGMODCRTBNDRPG コマンドで「条件名の定義」というパラメータを
見たことがあるかも知れない。
これはある適当な変数をコンパイル時に指定しておいて、その条件によって
ソースの一部を採用したりオミットしてコンパイルすることができる機能のことである。
例えば次の RPGソースを見て欲しい。
わかりやすくするために非常に単純な例としている。

ソースコード
0001.00 H DFTNAME(TESTDBG) DATEDIT(*YMD/)                                      
0002.00 F**********  条件つきコンパイル ***************************************
0003.00 F*                                                                     
0004.00 F**********************************************************************
0005.00 C     '* DEBUG *'   DSPLY                   ANS               1        
0006.00 C                   SETON                                        LR    
0007.00 C                   RETURN                                             

ここでは ディバッグ用の DSPLY 命令を入れているが、本稼動用(リリース) では
もちろん DSPLY 命令は不要であるので、除去してコンパイルしたいところである。
DSPLY の命令の行を本稼動ではコメント・アウトしてしまえば済むことなのであるが
それでは、いちいち RPGソースの修正が必要となってしまう。
大量にディバッグ命令がある場合は、ソースの修正に間違ってしまう場合もあるので
その方法は安全とは言えない。
次のソースを見て頂きたい。これは条件つきのコンパイルを指示するソースである。

0001.00 H DFTNAME(TESTDBG) DATEDIT(*YMD/)                                      
0002.00 F**********  条件つきコンパイル ***************************************
0003.00 F*                                                                     
0004.00 F**********************************************************************
0005.00  /IF DEFINED(DEBUG)                                                    
0006.00 C     '* DEBUG *'   DSPLY                   ANS               1        
0007.00  /ENDIF                                                                
0008.00 C                   SETON                                        LR    
0009.00 C                   RETURN                                             
【 解説 】

/IF DEFINED(DEBUG) 〜 /ENDIF までのあいだは、RPGコンパイラーで DEBUG という条件が定義されて
いる場合だけがインクルードされて有効となる。
これを

CRTBNDRPG PGM(MYLIB/TESTDBG) SRCFILE(MYSRCLIB/QRPGLESRC) AUT(*ALL) DEFINE(DEBUG)

のようにしてコンパイルするとコンパイル・リストは次のようになる。

ソースコード
1 H DFTNAME(TESTDBG) DATEDIT(*YMD/)                                   
2 F**********  条件つきコンパイル ************************************
3 F*                                                                  
4 F*******************************************************************
5  /IF DEFINED(DEBUG)                                                 
6 C     '* DEBUG *'   DSPLY                   ANS               1     
7  /ENDIF                                                            
8 C                   SETON                                        LR
9 C                   RETURN                                         

しかし、条件 DEBUG を定義せずに

CRTBNDRPG PGM(MYLIB/TESTDBG) SRCFILE(MYSRCLIB/QRPGLESRC) AUT(*ALL)

としてコンパイルしたのであれば、コンパイル・リストは次のようになる。

ソースコード
1 H DFTNAME(TESTDBG) DATEDIT(*YMD/)                                   
2 F**********  条件つきコンパイル ************************************
3 F*                                                                  
4 F*******************************************************************
5  /IF DEFINED(DEBUG)                                                 
       LINES EXCLUDED: 1                                              
6  /ENDIF                                                            
7 C                   SETON                                        LR
8 C                   RETURN                                         

つまり、ディバッグ用の DSPLY 命令の行がオミットされているのである。
この条件つきコンパイルを利用すれば

TESTDBG_P ..... リリース用オブジェクト (ディバッグ命令は含まれない)
TESTDBG_D ..... ディバッグ用オブジェクト (ディバッグ命令が含まれている)

との2種類のオブジェクトを同じソースから生成することができる。
このことは何を意味するのかと言うと、ディバッグ用とリリース用のオブジェクトを
分離させることである。従来のプログラムではさほど問題にはならなかったが大量の
ディバッグ命令を含んでいる。
プログラムに対して本番稼動用の実行モジュールでは、できるだけプログラム・サイズも
小さなものとして実行速度も上げたい場合には、有効な手段である。
ここに提案する手法は実は VisualC++ で使用されている方法である。
リリース用とディバッグ用を分離することができればリリース用では
ディバッグ用ビューを *NONE にしてコンパイルするなどしてさらに軽いオブジェクトを生成することができる。
ソフトウェア製品をリリースしてパフォーマンスも考慮するのであればこのような配慮が望ましい。