Eclipseを使用したメインフレーム・アプリケーション開発 - (4)ソース管理ツール/ビルドツール連携

# はじめに
メインフレームのアプリケーションについても、オープン系のアプリケーションで使われているような作法で、ソース管理やビルドのツールを利用することができます。
ここでは、Gitを使ったソース管理とDBB(Dependency Based Build)という有償のツールを使用したビルドをEclipseから行う方法について記載します。
当記事ではWazi Developer for Eclipse(V1.1.0)を使ってみた時の内容を記載します。

## 関連記事
[Eclipseを使用したメインフレーム・アプリケーション開発 - (1)概要](https://qiita.com/tomotagwork/items/0a6b273473333f849116)
[Eclipseを使用したメインフレーム・アプリケーション開発 - (2)z/OS基本操作](https://qiita.com/tomotagwork/items/67e7faac4ec30198f1d3)
[Eclipseを使用したメインフレーム・アプリケーション開発 - (3)ソース編集](https://qiita.com/tomotagwork/items/2db56a0981e8dac57a20)
[Eclipseを使用したメインフレーム・アプリケーション開発 - (4)ソース管理ツール/ビルドツール連携](https://qiita.com/tomotagwork/items/da039208be2f77c21285)
[Eclipseを使用したメインフレーム・アプリケーション開発 - (5)デバッガーの利用](https://qiita.com/tomotagwork/items/93457c9ba11870a7c357)


# 全体像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/181b743e-3425-0761-ecc6-538e5d8fa5fb.png)
オープン系で使われているような作法と同じように、以下のような手順でソースの編集が行えます。ここで主にターゲットとしているシチュエーションとしては、Small Scale User Buildと呼ばれているようなもので、個別のバグフィックスなど1～2つのソースを修正するようなケースです。

(1) **clone/pull**: リモートのリポジトリの内容ををローカル・リポジトリーに取り込みます。
(2) **編集**: Eclipse上でCOBOL, PL/Iなどのソースを編集します(前の関連記事のイメージ)。
(3) **ビルド**: z/OS上に変更したソースを転送してコンパイル/リンクします。
(4) **テスト**: 修正が正しく行われたかどうか単体テストします。
(5) **push**: 修正が完了したら修正内容をGit Serverのリポジトリーに反映させます。

(2)～(4)を回してソースの修正を行うことになると思いますが、「(4)テスト」の部分はz/OSアプリの場合一工夫必要になります。ここは言語(COBOL, PL/I, ASM)、利用するミドルウェア(CICS、Db2、IMS、MQ、...)、テスト対象のプログラムの呼び出し形態(バッチ実行、3270画面経由、サブルーチンコール、API、...)などによってテストのやり方が異なるからです。
テスト部分については用途に応じたテストツールが色々と提供されていたり、デバッガーなどを用いたトライ&エラーを行いたい場合があったりと、バリエーションも豊富なのでこの記事では取り上げません。例えばPCOM経由でこれまでと同じような手法で単体テストしたり、別途テストツールを用いてテストする、あるいは自動化してビルドスクリプトに組み込む、といったことが考えられますが、ここでは一旦なにかしらの方法で単体テストをするステップが入るものと考えておいてください。

## ソース管理
これは一般的なオープン系アプリケーションのソース管理で利用されている、Eclipseが元々持っているGit連携機能をそのまま使います(EGitプラグイン)。GitHubなどのGitサーバーと連携してソース管理が行えますので、COBOLやPL/Iなどz/OS向けのアプリケーションのソースもこれで管理しましょう、ということです。
これはz/OS特有の話ではないのでEclipseとGit連携そのものについてはここでは深くは触れませんが、以下参考まで。
参考: [LibertyによるWebサービスアプリ開発メモ: (6)Eclipse-GitHub連携](https://qiita.com/tomotagwork/items/63a1c75be844f28a0582)
(他にも世の中にはもっとよい情報が出回っていると思います)

## ビルド
オープン系のアプリケーションの場合、Javaやnodejsなどはローカルの環境でビルドやテストがある程度できたりしますが、z/OSアプリケーション(COBOL, PL/I, ASM,...)の場合はコンパイル/リンク、テストはz/OS上で実行する必要があります。そのためには、必要なファイル群をz/OS上に転送しソースにあったJCLを実行する、といったことをする必要があります。この辺りの操作を簡素化する仕組みを、DBBを中心とした機能で提供してくれています。

関連する要素技術を補足します。

### DBB(Dependency Based Build)
参考:
[IBM Dependency Based Build](https://www.ibm.com/docs/en/dbb/1.1.0)
[GitHub - DBB sample](https://github.com/IBM/dbb)

アプリケーションのビルドをサポートする機能を提供する有償製品です。基本的にはz/OS上にインストールして使用するものです。DBB Toolkitと呼ばれるコンポーネントがz/OS関連操作(コンパイラ実行、ソースコピーなど)を行うためのJava APIを提供しています。これにより、Groovyでビルド用のスクリプトを記述することができます。
DBB Toolkitが提供するのは基本的にAPIやGroovy関連のライブラリなので、必ずしもz/OS側で何らかのサーバー機能を常駐させておく必要はありません。ただ、これらはJVM上で動くことになりJVMの起動には一般的に大きなコストがかかります。このJVM起動に関するパフォーマンスを改善させるために、DBB Daemonを常駐させておいてビルド指示の度にJVM起動が走ることを回避する、といった使い方をすることもできます。その場合はDBB Daemonの構成をしてDaemonを起動させておく必要があります。
参考: [Improving performance with ZD&T or Java startup by using DBB daemon](https://www.ibm.com/docs/en/dbb/1.1.0?topic=improving-performance-by-using-dbb-daemon)

DBBではもう一つDBB Serverというコンポーネントも提供しています。これはz/OSではなくLinux上に立てるサーバー(実体はLiberty)で実装される機能で、ソースの依存関係のメタデータを管理したりビルド結果を管理させることができます。当記事ではこの部分については触れません。

ちなみにWazi Developer for Red Hat CodeReady Workspacesという製品にはDBBが含まれています。

### zAppBuild
参考: [GitHub - dbb-zappbuild](https://github.com/IBM/dbb-zappbuild)

DBBという製品は、VSCodeやEclipseなどオープン系の開発ツールと連携しやすいように、Groovyでビルドのスクリプトを書ける仕組みを提供してくれています。ただ、それはつまり、これまでJCLで書いていたコンパイル/リンクなどの一連の操作を別のスクリプトで書かないといけないということになります。一からそのようなスクリプトを作るのは大変なので、zAppBuildという汎用的に使えるビルドのスクリプトやプロパティーファイルの雛形を提供してくれています。これはGitHubで公開されておりダウンロードして自由に利用可能です( Apache-2.0 License)。
これは、z/OSのUSS上に展開して利用します。

### Dependency Based Build Integrationフィーチャー
使用するEclipseベースのツール側(IDz, Wazi Developer for Eclipseなど)では、EclipseのプラグインとしてIBM Dependency Based Build Integrationというフィーチャーが提供されています。インストール時に選択していなければこのフィーチャーを追加でインストールする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/82164094-3cc7-8310-6ba2-5e58af043d85.png)

# 構成(事前準備)

## z/OS側
DBB toolkitとzAppBuildの構成は基本的に環境毎に1度実施すれば複数ユーザーで共有して利用できます。

### DBB toolkit
DBB toolkitをz/OS上にインストールしてセットアップする必要があります。
ここでは詳細は割愛します。

参考: [Installing and configuring the DBB toolkit on z/OS](https://www.ibm.com/docs/en/dbb/1.1.0?topic=dbb-installing-configuring-toolkit-zos)

### zAppBuild
zAppBuildの構成としては、GitHubで提供されているファイル群をUSS上に展開し、環境依存の情報をプロパティ・ファイルに設定する、ということを行います。

#### ファイルの展開
USS上にもGitのクライアントを導入することができますので、USS上にGitクライアントがあってGitHubと接続できる環境であれば、直接USS上にzAppBuildのファイル群をCloneすることができます。
ただ、z/OSから直接外部のGitHubに接続できる環境を整えるのは難しいことも多いと思いますので、その場合は一旦PC上にCloneをしてそれをz/OSにz/OSMF経由(Zowe CLI経由)で転送するなどしてください。
参考: [zAppBuild - ファイルの展開](https://qiita.com/tomotagwork/items/4bdd0b5a7284b5102d10#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%B1%95%E9%96%8B)

#### プロパティ・ファイルの設定

USS上に展開されたファイルのうち、`dbb-zappbuild/build-conf/dataset.properties`を編集して、環境依存のデータセットの情報(LEや各ミドルウェアのライブラリの情報など)を指定します。

```properties:dbb-zappbuild/build-conf/dataset.properties設定例
# Dataset references
# Build properties for Partition Data Sets (PDS) used by zAppBuild build scripts.
# Please provide a fully qualified DSN for each build property below.
# Ex:
# MACLIB=SYS1.MACLIB

# z/OS macro library. Example: SYS1.MACLIB
MACLIB=SYS1.MACLIB

# Assembler macro library. Example: CEE.SCEEMAC
SCEEMAC=CEE.SCEEMAC

# LE (Language Environment) load library. Example: CEE.SCEELKED
SCEELKED=CEE.SCEELKED

# High Level Assembler (HLASM) load library. Example: ASM.SASMMOD1
SASMMOD1=HLA.SASMMOD1

# Cobol Compiler Data Sets. Example: COBOL.V4R1M0.SIGYCOMP
SIGYCOMP_V4=
SIGYCOMP_V6=IGY630.SIGYCOMP

# PL/I Compiler Data Sets.  Example: PLI.V5R2M0.SIBMZCMP
IBMZPLI_V52=IEL530.SIBMZCMP
IBMZPLI_V51=

# CICS Macro Library. Example: CICSTS.V3R2M0.CICS.SDFHMAC
SDFHMAC=DFH550.CICS.SDFHMAC

# CICS Load Library. Example: CICSTS.V3R2M0.CICS.SDFHLOAD
SDFHLOAD=DFH550.CICS.SDFHLOAD

# CICS COBOL Library. Example: CICSTS.V3R2M0.CICS.SDFHCOB
SDFHCOB=DFH550.CICS.SDFHCOB

# MQ COBOL Library. Example: CSQ.V9R1M0.SCSQCOBC
SCSQCOBC=CSQ911.SCSQCOBC

# MQ Load Library. Example: CSQ.V9R1M0.SCSQLOAD
SCSQLOAD=CSQ911.SCSQLOAD

# DB2 Load Library. Example: DB2.V9R1M0.SDSNLOAD
SDSNLOAD=DSNC10.SDSNLOAD

# IMS Macro Library. Example: DFS.V11R1M0.SDFSMAC
SDFSMAC=DFSF10.SDFSMAC

# IMS RESLIB. Example: DFS.V11R1M0.SDFSRESL
SDFSRESL=DFSF10.USER.SDFSRESL

# User generated library for DB/DC and DC installations. Example: DFS.V11R1M0.REFERAL
REFERAL=DFSF10.REFERAL

# IBM Debug Library containing Exits
SEQAMOD=EQAF00.SEQAMOD

# Optional IDz Load Library. Example: FEL.V14R0M0.SFELLOAD
SFELLOAD=FELE20.SFELLOAD

# Optional IDZ zUnit / WAZI VTP library containing necessary copybooks. Example : FEL.V14R2.SBZUSAMP
SBZUSAMP=
```

### USS上のディレクトリの作成

DBBとの連携では、ローカルのPCからファイルをUSS上に転送し、USS上で各種操作が行われます。そのためのディレクトリを作成しておく必要があります。ここでは以下のようにディレクトリを作成することにします。
このディレクトリは、ユーザー単位で設定しておくのがよさそうです。

**DBBワークスペース用ディレクトリ**: /u/TAGUCHI/projects
**ログ用ディレクトリ**: /u/TAGUCHI/projects/logs

基本的には、SSHで接続するユーザーのアクセス権があればよいです。ただ、DBBのShared Daemonという機能を使う場合は、ログ用のディレクトリについてはDBB Shared Daemonがの実行ユーザーからログの書き込みが行われるので、DBB Shared Daemon実行ユーザーのwrite権限も必要になります。
(今回試した環境では、SSHユーザーとDBB Shared Daemonユーザーのグループを同じにし、グループに対してwrite権限も付与しています)

```
TAGUCHI:/u/TAGUCHI/projects: >ls -la
total 1008
drwxr-xr-x   6 TAGUCHI  SYS1        8192 Feb 21 13:16 .
drwxr-xr-x   8 TAGUCHI  SYS1        8192 Feb 22 10:54 ..
drwxrwxr-x   2 TAGUCHI  SYS1        8192 Feb 21 13:39 logs
...
```

## PC側

### インストール
PC側では、使用するEclipseのツール上(IDz, Wazi Developer for Eclipseなど)に以下のフィーチャーをインストールしておく必要があります。

- EGit
- Dendency Based Build Integration

### 接続構成
リモート・システムとしてRSEに対する接続定義を作成しておく必要があります。(これまでの記事で利用していた接続そのままでOK)


# 使用例
以下、Wazi Developer for Eclipseでの操作例です。
Wazi Developer for Eclipseパースペクティブで操作します。

## サンプルのクローン
以下に提供されているサンプルを使います。
https://github.com/IBM/dbb-zappbuild

GitRepositoryビューでClone a Git Repositoryのアイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/313c6f72-d56c-3de1-6132-c1facca3f4b2.png)

GitHubのURIを指定して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/9cd81ae2-b7e9-2142-01ab-35198b2a3add.png)

ブランチを選択して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/4732e263-533c-e773-0a92-32b9d203672e.png)

Clone先の適当なディレクトリを指定し、さらに、"Import all Existing Eclipse projects after clone finishes"にチェックを入れる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/02d6019d-29f8-82a1-a874-1fee4c5f4b08.png)

dbb-zappbuildがクローンされ、Working Tree以下からRepositoryで管理されている各種ファイルが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1ab5b6c2-cd3e-8ea5-915d-502dfbb1b5db.png)

## z/OSプロジェクトとしての管理
さて、ここでCloneしたリポジトリ配下のsample/MortgageApplicationに着目します。
このディレクトリ下には.projectというファイルがあり、以下のような設定がされています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/a6a6ad60-fc14-1da5-a2a5-7c9ec9f2b7fa.png)

以下の<nature>タグに指定されている値の意味は、z/OSプロジェクト、かつ、DBB(依存関係ビルド)用のプロジェクトとして扱うということを意味しています。

```xml:.project
...
	<natures>
		<nature>com.ibm.ftt.ui.views.project.navigator.local</nature>
		<nature>com.ibm.ftt.dbbz.integration.dbbzprojectnature</nature>
	</natures>
...
```

このような属性を持つ.projectファイルが配置されているディレクトリは、z/OSプロジェクトとして認識されます。z/OSプロジェクト・ビューを見てみると、自動的にMortgageApplicationが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/9dd1e105-c145-1ae6-cc9c-f87f682d4f70.png)

※新規にz/OSプロジェクトを作成する場合、z/OSプロジェクト・ビューでローカルz/OSプロジェクトを作成し、右クリック-依存関係ベースのビルド-DBBプロジェクト・ネイチャーの追加 を選択すると、.projectにDBB用の属性が追加され、依存関係ベースビルドの機能が使えるようになります。
<details><summary><font color="blue">参考</font></summary><div>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/0c76482c-47c6-3692-b85b-89d313094637.png)
</div></details>

z/OSプロジェクト・ビューでMortgageApplicationを右クリック-依存関係ベースのビルド-プロパティー・グループの生成 を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/69556b5b-513f-0366-bea4-7d6187275178.png)

ローカルCOBOL設定を選択して終了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/b5d7cd70-8286-c45a-c0b5-0cf5f451570a.png)

すると、プロパティー・グループ・マネージャーのローカル以下に、プロジェクト名と同名のプロパティー・グループが作成され、関連付けされます。中身を見てみると、SYSLIB探索パスとしてプロジェクト以下の全ディレクトリが設定されていますので、必要に応じて編集します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/3bd91668-a176-9271-594f-893a5e7d6782.png)


## ソース編集
前の記事の例に示したような機能を利用し、ソースの修正などを行います。ここでは意図的に不具合を含んだコードを追加してみます(存在しない変数名を使ったステートメントを追記)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1d850b12-873d-1317-4f14-336a30be89c7.png)

リアルタイム構文検査で警告マークが出ていますが、無視してそのまま次のステップに進んでみます。

## ビルド
DBB,zAppBuildを利用してビルドしてみます。
このサンプルではzAppBuildのアプリケーション依存プロパティはapplication-confとして提供されているので、それをそのまま使います。
上で編集したCOBOLのソースをビルドしてみます。

z/OSプロジェクト・ビューからビルド対象のファイルを右クリック-依存関係ベースのビルド-ユーザー・ビルドの構成 を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/0e141f0c-cd7e-f2c1-ebdb-f221e76641c4.png)

DBB、zAppBuild関連の各種パラメーターを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/439232bd-b59b-f3ce-3949-9e154a115c8c.png)

- **使用するz/OSシステムを選択**: ビルドを実行するz/OSの接続定義
- **使用するビルド・スクリプトを選択**: USS上のzAppBuild提供のbuild.groovyを指定
- **ビルド・サンドボックスのフォルダーを入力**: ワーク用に使用するUSS上のディレクトリを指定(事前に作成しておく)
- **ビルド宛先HLQを入力**: ビルド対象のソースや作成されるロード・モジュール配置先データセットのHLQ(データセットは無ければ動的に作成される)

"この構成をプロジェクトのデフォルトとして使用する"にチェックすれば、別のソースでも同様の設定を利用可能です。

そのまま次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/859f7f75-6357-821a-b993-a66dab68c9b0.png)

ログ出力用のディレクトリ(USS上に事前作成しておく)を指定して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/b05cbc0a-49c8-a001-0a09-8782524b88e1.png)

build.groovy実行時のパラメーターを適宜設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c49d1f45-e195-73b9-2ce2-94aa48bd86e9.png)

- **--workspace**: ${SANDBOX}で先に指定したUSS上のワークディレクトリが参照されます
- **--outDir**: ${LOGS}で先に指定したログ出力用ディレクトリが参照されます
- **--hlq**: 先に指定したビルド宛先HLQが参照されます
- **--application**: 今回ビルドする対象のソースが含まれるアプリケーションのディレクトリ名を指定します
- **-DBB_DAEMON_HOST, -DBB_DAEMON_PORT**: DBB Shared Daemonを使用する場合のオプションを指定しています(具体的な値は管理者に要確認)。使用しない場合は追記不要。

ビルドする際にホストに転送するファイルを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/be6ebf17-82a3-1096-8022-1311108d649d.png)
対象ソースに関連性のあるファイル(COPYBOOKなど)は自動的に検出されて選択されていますが、それ以外に必要なものは適宜選択します。ここでは、zAppBuildを使用するのでapplication-confディレクトリを追加でチェックします。

最後に指定した内容について確認して終了をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/59e5278b-9619-4785-b92d-03ce06b19866.png)

コンソールにビルドの状況のログが出力され、完了すると以下のようなポップアップが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/fbd43c20-37ff-21df-b2e4-15016ced9d04.png)

詳細を見ると、コンパイルの実行結果が参照できます(この結果はログ用ディレクトリとして指定したUSS上のディレクトリ下にもEPSNBRVL.logとして生成されています)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d6514114-29bc-94e7-5f98-68c0f12904be.png)

敢えて意図的にエラーを含むステートメントを追加したので、想定通りコンパイルがエラーとなりました。
リモート・エラー・リスト・ビューを見ると、以下のようにコンパイル・エラーのリストが表示されており、ダブル・クリックするとソース中の該当箇所に飛んでくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/af3e91f1-ded8-f190-9a65-fb529d74ab89.png)

エラー箇所を削除して、再度ビルドしてみます。2回目以降は先と同じ構成を使えばよいのでビルドを実行するだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/05c2f3be-d446-f7d8-d827-ee08294308d5.png)

<details><summary><font color="blue">コンソール出力例</font></summary><div>

```
sh


cd /u/TAGUCHI/projects

$DBB_HOME/bin/groovyz /u/dbb_common/dbb-zappbuild/build.groovy --workspace /u/TAGUCHI/projects --outDir /u/TAGUCHI/projects/logs --hlq TAGUCHI.DBB --application MortgageApplication -DBB_DAEMON_HOST 127.0.0.1 -DBB_DAEMON_PORT 7380 --errPrefix U2478565 --userBuild  MortgageApplication/cobol/epsnbrvl.cbl
/u/TAGUCHI/projects>



** Build start at 20210403.104406.044
/u/TAGUCHI/projects>
** Build output located at /u/TAGUCHI/projects/logs


** Adding MortgageApplication/cobol/epsnbrvl.cbl to Building build list
** Writing build list file to /u/TAGUCHI/projects/logs/buildList.txt
** Invoking build scripts according to build order: BMS.groovy,Cobol.groovy,LinkEdit.groovy
** Building files mapped to Cobol.groovy script
*** Building file MortgageApplication/cobol/epsnbrvl.cbl
/u/TAGUCHI/projects>

** Writing build report data to /u/TAGUCHI/projects/logs/BuildReport.json
** Writing build report to /u/TAGUCHI/projects/logs/BuildReport.html

** Build ended at Sat Apr 03 10:44:18 GMT 2021
** Build State : CLEAN
** Total files processed : 1
** Total build time  : 11.603 seconds

__RC=0__
** Build finished
/u/TAGUCHI/projects>
```

</div></details>

RC=0で終わればOKです。
このような形で、ソースの編集、ビルドを繰り返すことができます。

# おわりに
今回は、ビルドに関してベースとなる手順の部分のみを実施してみました。
実際の開発プロセスを回す場合は、アプリケーション用のリポジトリを別途作成してそれを使用し、ソース編集/ビルド/UT を回して確定したら変更をcommitしてpushというような流れになると思います。
テスト部分については冒頭でも示したように、変更対象のソースの形態に依存するので、やり方はまちまちです。テスト支援ツールと組み合わせれば、UT部分もUser Buildのスクリプトに組み込んである程度自動化する、ということも可能にはなると思います。