The future of storing ILE source code is closer than you think.
In this long-awaited article, I'm going to talk about how to store your RPG and CL code on the IFS and what steps you need to take in order to create objects out of that source.
First, you should know that CRTRPGMOD, CRTBNDRPG, and CRTSQLRPGI all have a parameter to specify a stream file for source. Thanks to IBM, this makes compiling RPG programs much easier. But what about CL? There isn’t a stream file parameter on CRTBNDCL, so what options do we have? I’ll come to that in a little while. If you work with other ILE languages, you might be glad to hear that the C, C++, and COBOL “Create” commands also have stream file parameters.
Next, I’m going to talk about how to organize your source. Let's imagine there is a library called MYPROG that holds two source physical files, one called QRPGLESRC and another called QCLLESRC. Now you have to consider how you'd lay that out in an IFS-styled manner. You might have a directory named MYPROG, with two directories below that called QRPGLESRC and QCLLESRC. It would look something like this:
As you can see, this is how you'd normally lay out your source code, but instead of libraries and source physical files, we just have regular directories. For this example, I have created MYPROJ in the IFS root, but you may create it wherever you like, including your home directory.
Creating Your First Program!
Creating your first program is just as simple as it would be if you were compiling from a source member. First, you need to create a stream file. For the sake of example, I created HELLOWORLD.rpgle within the QRPGLESRC directory.
Now bear in mind, stream file names do not have a logical maximum length. In theory, you could have RPG stream files named HELLOWORLDHOWAREYOU.sqlrpgle, and it wouldn't make a difference. But when creating an object from this source, that object will still have its 10-character limit. Don't give stream file long names just because you can.
So now I have created HELLOWORLD.rpgle, I am going to place some source code in there so it can be compiled:
Dcl-S Text Char(11);
Text = 'Hello world';
*InLR = *On;
To compile this, I’m going to use CRTBNDRPG. Luckily, since the stream file name (without the extension) is 10 characters, I can give the object the same name. The only difference here is that you can’t pass in a source member, but instead you pass in the path to the stream file you want to compile—in this case, /MYPROJ/QRPGLESRC/HELLOWORLD.rpgle.
CRTBNDRPG PGM(*CURLIB/HELLOWORLD) SRCSTMF('/MYPROJ/QRPGLESRC/HELLOWORLD.rpgle') REPLACE(*YES) OPTION(*EVENTF) DBGVIEW(*SOURCE)
Compiling CL Source
Compiling CL source can be a touchy subject. In fact, what I’m about to tell you doesn't apply only to CL, but also display files, commands, and a few others.
I'm afraid to tell you that CRTBNDCL does not have a stream file parameter. There is an RFE to add support for CL in stream files, but we've heard nothing from IBM on the matter; it could be a while before we even see it, let alone are able to use it.
This means we need to create our own process to create our CL programs. What do I mean by “process,” you ask? You need to have a way to automate compiling CL from the IFS.
A common method and the one I will be using is having a program to automate the following steps:
1.Copy the stream file to a temporary member (replace this member if it already exists too).
2.Create the CL program from the temporary member.
Might seem easy, right? It's the best we have right now, but there is one small thing to remember: If you create a temporary member within a source file in QTEMP and still want the ability to debug the CL, you will need to use DBGVIEW(*LIST) in your CRTBNDCL command. You will find that, after you start debugging, *LIST is not the best thing to do. Another option is to not make it a temporary member. Instead, copy the stream file into a member that resides in the same library you are creating the object in and then use DBGVIEW(*SOURCE) to retain the source.
Seems like a lot just to create a CL from the IFS, doesn’t it? There is an easier way in the meantime, but that is until IBM gives us the stream file parameter. I mentioned this in my previous article , but Brian Garland's CRTFRMSTMF is a great way to do this and could easily be part of your process to create CLs, display files, etc. The good news is that Brian has made it open source for us all to use.
CRTFRMSTMF allows you to compile non-traditional things like CL from the IFS. It actually uses the process I described earlier; it creates a temporary memory and runs the compile command for us. The best way to try it is to obtain the source for this project and compile it on your machine so you have access to the CRTFRMSTMF command.
So let's say we have a CL program called MYCLPGM.clle that lives in the QCLLESRC directory I created earlier.
DCL VAR(&TEXT) TYPE(*CHAR) LEN(11)
CHGVAR VAR(&TEXT) VALUE('Hello world')
Now, I can make use of the process to create this CL, but for this article I will show both methods.
CRTSRCPF FILE(QTEMP/QCLLESRC) RCDLEN(112)
CPYFRMSTMF FROMSTMF('/MYPROJ/QCLLESRC/MYCLPGM.clle') TOMBR('/QSYS.lib/QTEMP.lib/QCLLESRC.file/MYCLPGM.mbr') MBROPT(*ADD)
CRTBNDCL PGM(MYCLPGM) SRCFILE(QTEMP/QCLLESRC) SRCMBR(*PGM)
Process 2 (Automated)
CRTFRMSTMF OBJ(*LIBL/MYCLPGM) CMD(CRTBNDCL) STMF('/MYPROG/QCLLESRC/MY
I hope this article has shown you how easy it can be to store source on the IFS. It really is the future and will allow development and dev ops processes to become much easier.
In the next article, I plan to show you how to start using Git on this MYPROJ directory to maintain your source code.