This chapter will cover what migration means, what tools can be used to migrate source members, handling changes to the copy books, compiling sources from the IFS (editors and command line) and why iProjects is not used.
Migration actually means copying the source member contents to the IFS. Only one person has to do this step. Once all the source is migrated into git, is when normal development. If you let someone edit the source members while migrating the source to the IFS, you will have to re-copy the changed members.
For example, your library, source physical files and members might look like this:
DEVLIB
- QRPGLESRC
- PROGRAMA.RPGLE
- PROGRAMB.RPGLE
- PROGRAMC.RPGLE
- QSQLSRC
- CUSTOMERS.SQL
- INVENTORY.SQL
- QCLLESRC
- STARTJOB.CLLE
- QCMDSRC
- STARTJOB.CMD
Where the resulting layout in the IFS could be very similar:
/home
/barry
/.git
/qrpglesrc
programa.rpgle
programb.rpgle
programc.rpgle
/qsqlsrc
customers.sql
inventory.sql
/qcllesrc
startjob.cmd
/qcmdsrc
startjob.cmd
Make sure that when you migrate code, you are migrating code into a directory which is a local repository (e.g. you cloned it) so you can commit & push changes as you make them. For example, make your first commit when you've migrated the code and then make another (or multiple) after you fix up the 'copybooks'.
Notes about migrating to the IFS:
- You will lose the TEXT column that source members have, which is usually used for describing what the source is. Although, you can still put that in the program as a comment.
- The type of the source member becomes the extension when in the IFS.
- Files and directories of sources are usually stored as all lowercase.
- It is recommended you retain the 10 character limit on programs, commands, modules, etc - any source related to Db2 for i doesn't matter as much as Db2 for i and most ILE languages support 'long names'
- Sources on the IFS should be stored as encoding 1208 (UTF-8).
Initially migrating the source code can be the hardest part of the entire process, but once it's done: it's done. There are many ways to do it, but this will only describe two.
All a migration consists of is moving source members to the IFS. To our benefit, the CPYTOSTMF
command exists, which can be used to copy a source member to a stream file. For example:
CPYTOSTMF FROMMBR('/QSYS.lib/DEVLIB.lib/QRPGLESRC.file/PROGRAMA.mbr') TOSTMF('/home/barry/myproject/qrpglesrc/programa.rpgle') STMFOPT(*REPLACE) STMFCCSID(1208)
On the basis of this command, you would have to run this command for each source member you want to migrate.
There is an open source migrate tool, simply named 'migrate', which automates the copying of source members into a directory. It also creates the streamfiles with the correct extensions.
To use the migrate tool, you will need to clone it and build it manually.
git clone https://github.com/worksofliam/migrate.git
cd migrate
gmake
Building this solution will create the MIGRATE
library and inside is the MIGSRCPF
command. MIGSRCPF
has three simple parameters.
If we had a library with source physical files and wanted to migrate them into a new project directory, we would have to run the command once to migrate the source physical file. It will copy the source member into the IFS as a 1208 (UTF-8) streamfile. If the file or folder it tries to create already exists, it will fail. In the last chapter, we created /home/BARRY/myproject
as a git repository.
MIGSRCPF LIBRARY(TESTPROJ) SOURCEPF(QRPGLESRC) OUTDIR('/home/BARRY/myproject')
MIGSRCPF LIBRARY(TESTPROJ) SOURCEPF(QRPGLEREF) OUTDIR('/home/BARRY/myproject')
MIGSRCPF LIBRARY(TESTPROJ) SOURCEPF(QCLLESRC) OUTDIR('/home/BARRY/myproject')
This would create three directories in /home/BARRY/myproject
like the following:
/home
/BARRY
/myproject
/qrpglesrc
/somesource.rpgle
/somesource.rpgle
/qrpgleref
/whatever.rpgle
/qcllesrc
/pgm1.clle
/pgm2.clle
/pgm3.clle
Note that it will create all directories and stream files with lowercase names.
You could potentially create an iProject in RDi based on a library and then have a local copy of all the source (which you can then put into a git repository later). You can also use the SPF Clone tool in ILEditor to clone a libraries source members on to your local machine (which can also be put into a git repository later).
Make sure, when you've finished migrating source code into your local developer repository. For example:
git add --all
git commit -m "Initial migration step"
git push
You will want to do this again (maybe multiple times) as you change the copybooks too.
Once the source has been migrated, another tedious task is changing all the copy books to point to your newly migrated stream files. We're lucky that the C, RPG and COBOL compilers for IBM i all support bringing includes in from the IFS. In this chapter, we will use RPG as it's the primary target audience for this book.
Let's say we have a program that has /COPY
(or /INCLUDE
) statements like the following at the top of the source:
/COPY QRPGLEREF,OBJECTS
/COPY QRPGLEREF,OBJECT
/COPY QRPGLEREF,FORMATS
/COPY QRPGLEREF,MEMBERS
** --------------------------
D testproj PI
D pLibrary 10A Const
** --------------------------
Even though this source might be in the IFS, /COPY
(or /INCLUDE
) can still bring in source from source members in the QSYS file system (and vice versa). What the developer should do is change the statements to use a relative path based on the root of the project to the respective streamfile on the IFS. For example /COPY QRPGLEREF,OBJECTS
might translate to /COPY './qrpgleref/objects.rpgle'
.
/COPY `./qrplgeref/objects.rpgle`
/COPY `./qrplgeref/object.rpgle`
/COPY `./qrplgeref/formats.rpgle`
/COPY `./qrplgeref/members.rpgle`
The reason you use a path relative to the root of the project is so we can build from the root of the project within our command line, IDE or our build system (which you will see later). It's not required that you do this to all your source at once, because you can still depend on the existing source members during a migration period - although it is recommended you change them as soon as possible. While it's not recommend, you can do it iteratively and change them when you work on the source. This is dangerous because the source members aren't under change control.
If you are using a 3rd party tool, like the HTTPAPI, which as it's headers in source members, then you can leave those /COPY
(or /INCLUDE
) statements along side your includes which point to the IFS:
/COPY `./qrplgeref/objects.rpgle`
/COPY `./qrplgeref/object.rpgle`
/COPY `./qrplgeref/formats.rpgle`
/COPY `./qrplgeref/members.rpgle`
/COPY QRPGLEREF,HTTPAPI_H
You are able to compile most sources out of the IFS using your IDE or by the command line. The following list of commands/compilers have support for compiling sources out of the IFS on IBM i with the SRCSTMF
parameter:
CRTBNDRPG
/CRTRPGMOD
CRTSQLRPGI
CRTSRVPGM
(for binder source) - 7.2+CRTBNDCL
/CRTCLMOD
- 7.3+RUNSQLSTM
CRTBNDC
/CRTCMOD
CRTBNDCBL
/CRTCBLMOD
When you invoke the compile commands, whether from a 5250 shell, pase shell or IDE, make sure you set the jobs current working directory to the root/directory of the project you're working with to make sure the sources /INCLUDE
and /COPY
statements work as intended (as shown in the chapter about copybooks).
You can change your working directory in a 5250 job using either CD
or CHGCURDIR
. You can also change your working directory in RDi and ILEditor when compiling sources. When working in pase, you can use cd
to change working directory.
For compilers like CRTBNDCL
or CRTCMD
(or any without the SRCSTMF
parameter), in the case that a business has not updated the 7.3 yet, to compile the source the developer would have to create a temporary source member in the same library they are building the object in (which should be their own developer library) and then compile that source member. For example:
CRTSRCPF FILE(BARRYDEV/QCMDSRC) RCDLEN(112)
CPYFRMSTMF FROMSTMF('./qcmdsrc/mycmd.cmd') TOMBR('/QSYS.lib/BARRYDEV.lib/QCMDSRC.file/mycmd.mbr') MBROPT(*REPLACE)
CRTCMD CMD(BARRYDEV/MYCMD) PGM(BARRYDEV/MYCMD) SRCFILE(BARRYDEV/QCMDSRC)
This process can also be automated tool called CRTFRMSTMF, which was created by Brian Garland. It adds the CRTFRMSTMF
command, which automated the previous three commands into one command: CRTFRMSTMF
. You can find that tool here: https://bitbucket.org/BrianGarland/crtfrmstmf
This book will cover building things like data areas, tables and message files in another chapter.
iProjects has the issue of adding more over head than it needs to. When you use an iProject, you are actually editing source locally and when the source is saved it is uploaded to a mapped source member on IBM i (where the compile happens). It makes more sense to have the currnet source code (and user repository) on the server, where the compiles happen, instead of working locally, mapping to a source member and then compiling.