Compile – Make Objects From Source

*************************************************************************************************************
Special Note for folks in countries other than USA. 

In some case, Compile may have trouble with machines that have country codes other than USA and use a QCCSID of 65535. CCSID 65535 does not translate characters from CCSID 037 and you may have compiles fail because everything was compiled using 037. 

The solution would seem to be to recompile the programs, as described below, into your CCSID and that should solve the problem.

Please let me know if it does not.
*************************************************************************************************************

One of the single biggest problems in creating objects on the AS/400 (Iseries, I5, whatever it is this week) is remembering all the options used to create the object and, if you are using PDM, which option to use to create the object (14, 15, etc).

My Compile utility solves this problem by storing the commands to create an object in the header and allowing you to use a single PDM or WDSC command to create them. 

With the coming of ILE and multiple modules, binderies, service programs, etc, having some sort of Make tool is absolutely essential although it is just as handy for older environments.

I wrote it twenty years ago and continue to use it on a daily basis. 

It is especially handy with WDSC. In fact, I don’t see using WDSC as practical without it. 

The utility is still written in RPG III and CL and I will at some point rewrite to RPG/ILE but being in RPG III and CL has the advantage of being available to recompile if you need it for earlier release than V5R1M0.

Even though it is written in RPG III and CL, it runs almost instantaneous.  

The command CNLLSTSPLF is a utility that I have included. It is written using ILE modules and free-format RPG so cannot be recompiled lower than V5R1M0. It just deletes the last spool files for a compile each new compile. It, also, deletes the spool files when you are using WDSC in the QPRTJOB. Use or not, up to you. 

I have, also, included a new command called CHKOBJECT. CHKOBJECT is included for the ILE world although it can be used for OPM, also. 
CHKOBJECT commands are put into the header of the top level of a multiple module ILE program to check if the lower levels exist. If not, it uses COMPILE to create them. 

For example:

      *_> DLTPGM PGM(@5/@4)                                            
      *_> CHKOBJECT OBJNAME(@5/XV0006_P01)  OBJTYPE(*FILE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(XV0006_P01)                          
      *_> CHKOBJECT OBJNAME(@5/XV0006_M01)  OBJTYPE(*MODULE) +         
      *_>   SRCFILE(@2/@1) SRCMBR(XV0006_M01)                          
      *_> CHKOBJECT OBJNAME(@5/XV0006_M02)  OBJTYPE(*MODULE) +         
      *_>   SRCFILE(@2/@1) SRCMBR(XV0006_M02)                          
      *_> CHKOBJECT OBJNAME(@5/XV0006_M03)  OBJTYPE(*MODULE) +         
      *_>   SRCFILE(@2/@1) SRCMBR(XV0006_M03)                          
      *_> CRTPGM PGM(@5/@4) MODULE(XV0006_M01 XV0006_M02 XV0006_M03) + 
      *_>   TEXT('Standard Utilities-CPP for INDENT') +                
      *_>   ACTGRP(QILE)        

In this example, we have a program that has three modules and a print file so we put in four check objects to make sure, first that the print file exists and then that each module exists.

If the source change date is newer than the source change date in the object, the object will, also, be recompiled.  

So if we just compile XV0012, it will create all the lower levels. We no longer have to compile the lower levels unless we want to. Just using COMPILE on XV0012 will create any lower levels needed. 

This utility is just command and CLLE object and should compile at any level that has ILE.                                         

Zip file COMPILE.ZIP contains the following:

This README.DOC.

COMPILE@V5R1M0.SAVF - V5R1M0 save file contains all the source and compiled objects. As indicated, original library COMPILE.

For those at a earlier release than V5R1M0, I have included the following sources.
  
AA_CREATE.CLP – Create all objects. Uses single source file QSRCF.
EXTSRCCMD.CMD – Extract Source Command.
XV0003C.CLP   – Driver.
XV0003AR.RPG  – Extract commands. 
EXCSRCCMD.CMD – Execute source commands.
XV0004C.CLP   – CL Driver.
COMPILE.CMD   – PDM/WDSC interface.
XV0005C.CLP   – CL Driver.
CHKOBJECT.CMD – Check if object exists. 
XV0018        - CPP for CHKOBJECT-Top Level.
XV0018_M01    - CPP for CHKOBJECT-Implementation.

To use the utility, you will need to create two PDM options described below and, if you are using WDSC, a compile options for each source type. Again described below. 

To recreate objects at an earlier release, create a library on AS/400 and a source physical file named QSRCF, length 112. 

Copy all the source members to the source file and compile AA_CREATE by hand. Then call 

CALL PGM(<Your_Library>/AA_CREATE)           
     PARM('<Your_Program_Library>' ‘Your_Source_Library” '<Your_Version>' 'N')

The fourth parameter is whether to create CNLLSTSPLF which should be “N” if you are creating for earlier than V5R1M0. 

That should do it. If you don’t like single source files, it is up to you to convert it to multiples.

To restore to V5R1M0 or later, copy the save file to the AS/400 using FTP and BIN option or whatever way you want and then do a RSTLIB. Original library name was COMPILE.

I have included a document Instructions on Transferring Save Files to AS/400 with instructions on how to transfer save files to AS/400.  

Now as to how the utility works. 

COMPILE executes instructions stored in the header of a source member. Any CL command that can be executed interactively can be executed. Here are example headers. I keep standard headers and just copy into any new source based on what I need. If I am recompiling existing source, I just copy the headers in when I edit. 

Display File

      *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                             
      *_> DLTF FILE(@5/@4)                                                 
      *_> CRTDSPF FILE(@5/@4) SRCFILE(@2/@1) SRCMBR(@3) +                  
      *_>    RSTDSP(*YES) DFRWRT(*YES) SHARE(*YES)                         

Print File. Extremely handy. Never have to remember how to recreate a print file.

      *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                          
      *_> DLTF FILE(@5/@4)                                              
      *_> CRTPRTF FILE(@5/@4) SRCFILE(@2/@1) SRCMBR(@3) +               
      *_>           PAGESIZE(71 132) LPI(6) CPI(10) +                   
      *_>           OVRFLW(70) SPOOL(*YES) OUTQ(*JOB) +                 
      *_>           FORMTYPE(*STD    ) MAXRCDS(*NOMAX) +                
      *_>           HOLD(*NO) SAVE(*YES) USRDTA('RUNS_Err')    

Physical File

      *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                          
      *_> DLTF FILE(@5/@4)                                    
      *_> CRTPF FILE(@5/@4) SRCFILE(@2/@1) SRCMBR(@3) +       
      *_>         MBR(*FILE) SIZE(10000 1000 999)             

Format only table

/*    *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                               */    
/*    *_> DLTF FILE(@5/@4)                                                   */    
/*    *_> CRTPF FILE(@5/@4) SRCFILE(@2/@1) SRCMBR(@3) +                      */    
/*    *_>         MBR(*NONE)                                                 */    

RPG/ILE Module

      *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                   
      *_> DLTPGM PGM(@5/@4)                                      
      *_> DLTMOD MODULE(@5/@4)                                   
      *_> CRTRPGMOD MODULE(@5/@4) SRCFILE(@2/@1) SRCMBR(@3) +    
      *_>   OPTION(*EVENTF) DBGVIEW(@9) OPTIMIZE(@8)             

SQL RPG Module. With all the options on SQL compiles, this one is important. 

      *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)
      *_> DLTMOD MODULE(@5/@4)
      *_> CRTSQLRPGI OBJ(@5/@4) +
      *_>   SRCFILE(@2/@1) SRCMBR(@3) +
      *_>   OBJTYPE(*MODULE) OPTION(*EVENTF) COMMIT(*NONE) +
      *_>   DBGVIEW(*SOURCE) DATFMT(*ISO) OUTPUT(*PRINT)      
                  
CL/ILE Module

/*    *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                               */      
/*    *_> DLTMOD MODULE(@5/@4)                                               */     
/*    *_> CRTCLMOD MODULE(@5/@4) SRCFILE(@2/@1) SRCMBR(@3) +                 */     
/*    *_>   DBGVIEW(@9) OPTIMIZE(@8)                                         */     

Again important one. Create an ILE program from modules. Check to make sure the display file exists and the five modules. 

      *_> DLTPGM PGM(@5/@4)                                             
      *_> CHKOBJECT OBJNAME(@5/TG0001_D01) OBJTYPE(*FILE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(TG0001_D01)                          
      *_> CHKOBJECT OBJNAME(@5/TG0001_M01) OBJTYPE(*MODULE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(TG0001_M01)                          
      *_> CHKOBJECT OBJNAME(@5/TG0001_M02) OBJTYPE(*MODULE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(TG0001_M02)                          
      *_> CHKOBJECT OBJNAME(@5/TG0001_M03) OBJTYPE(*MODULE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(TG0001_M03)                          
      *_> CHKOBJECT OBJNAME(@5/TG0001_M04) OBJTYPE(*MODULE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(TG0001_M04)                          
      *_> CHKOBJECT OBJNAME(@5/TG0001_M05) OBJTYPE(*MODULE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(TG0001_M05)                          

      *_> CRTPGM PGM(@5/@4) MODULE(TG0001_M01 TG0002_M01 TG0002_M02 +       
      *_>   TG0002_M03 TG0002_M04 TG0002_M05) +                        
      *_>   ENTMOD(@5/@4) +                                            
      *_>   BNDSRVPGM(XVMSGF XVUSPC) ACTGRP(QILE)                  

Create a service program. Check to make sure module exists before binding

      *_> DLTSRVPGM SRVPGM(@5/@4)                               
      *_> CHKOBJECT OBJNAME(@5/XVIFSX_M01) OBJTYPE(*MODULE) +           
      *_>   SRCFILE(@2/@1) SRCMBR(XVIFSX_M01)                          
      *_> CRTSRVPGM  SRVPGM(@5/@4) MODULE(XVIFSX_M01) +         
      *_>   SRCFILE(@2/@1) SRCMBR(XVIFSX_B) BNDSRVPGM(XVERRH) + 
      *_>   TEXT('Integrated File System-Common Functions.') +  
      *_>   ACTGRP(QILE) BNDDIR(QC2LE)                          

Regular RPG.

      *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                         
      *_> DLTPGM PGM(@5/@4)                                            
      *_> OVRDBF FILE(FILEXYZ)              
      *_>   TOFILE(LIBABC/FILEABC)     
      *_>   OVRSCOPE(*JOB)             
      *_>   SHARE(*YES)                
      *_>  OPNSCOPE(*JOB)             
      *_> CRTRPGPGM  PGM(@5/@4) +                         
      *_>   SRCFILE(@2/@1) SRCMBR(@3)      

Note in this last one, I included an OVRDBF to demonstrate that you can create virtual files and override them at compile time.

Here is a very handy one. I have started using to create tables in SQL. Note that the table is named using the short name and then renamed to the long name. I am including the entire script. Note, also, that this will fail at an operating system level below V5R3M0 if the table doesn’t exist. 

The solution, in that case, is to put the DLTF command in the instructions below the CNLLSTSPLF command, delete using the short name and remove the drop table. If the file doesn’t exist, you will get a warning message but the compile will proceed as normal.

As you can see, you can use Compile to run any kind of SQL script. I just create the object with Ops Nav and then use the Generate SQL option and clean up and paste into a member.   

/*   *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)                               */
/*   *_> RUNSQLSTM SRCFILE(@2/@1) SRCMBR(@3) +                              */
/*   *_>   DFTRDBCOL(@5) CLOSQLCSR(*ENDMOD) ERRLVL(20)                      */
/*   *----------------------------------------------------------------------*/
/*   * SQL File: OIMACROPGM         Project.....:                           */
/*   * Author..: A. Campin          Date written: 06/07/2006                */
/*   * Purpose.: Create SQL Table OI_MACRO_PROGRAMS.                        */
/*   * -------------------------------------------------------------------- */
/*   * Revision history:                                                    */
/*   *  Proj#  Pgmr         Date    Desc                                    */
/*   *                                                                      */
/*   *  End Revision History                                                */
/*   *--------------------------------------------------------------------- */

DROP TABLE OI_MACRO_PROGRAMS;

CREATE TABLE OIMACROPGM (
	MACPGM_MACRO_NUMBER FOR COLUMN MPMACRONUM DECIMAL(3, 0) NOT NULL ,
	MACPGM_TYPE FOR COLUMN MPMACROTYP CHAR(1) CCSID 37 NOT NULL ,
	MACPGM_RUN_SEQ FOR COLUMN MPRUNSEQ   SMALLINT NOT NULL ,
	MACPGM_PROGRAM_NAME FOR COLUMN MPPGMNAM   VARCHAR(10) CCSID 37 NOT NULL ,
	MACPGM_PROGRAM_LIBRARY FOR COLUMN MPPGMLIB   VARCHAR(10) ALLOCATE(5)
	  CCSID 37 NOT NULL DEFAULT  '*LIBL' ,
      MACPGM_ACTIVE FOR COLUMN MPACTIVE CHAR(1) CCSID 37 NOT NULL
        DEFAULT 'Y',
	CONSTRAINT OIMACROPGM_MPMACRONUM_00001 PRIMARY KEY( MACPGM_MACRO_NUMBER ,
	  MACPGM_TYPE , MACPGM_RUN_SEQ ) ) ;

RENAME OIMACROPGM TO OI_MACRO_PROGRAMS;

RENAME OI_MACRO_PROGRAMS TO SYSTEM NAME OIMACROPGM;

ALTER TABLE OI_MACRO_PROGRAMS
	ADD CONSTRAINT OIMACROPGM_MPMACRONUM_00002
	CHECK( MACPGM_MACRO_NUMBER <> 0 ) ;

ALTER TABLE OI_MACRO_PROGRAMS
	ADD CONSTRAINT OIMACROPGM_MPPGMLIB_00001
	CHECK( MACPGM_PROGRAM_LIBRARY
           NOT IN('*CURLIB','*USRLIBL','*ALL','*ALLUSR'));

ALTER TABLE OI_MACRO_PROGRAMS
	ADD CONSTRAINT OIMACROPGM_MPRUNSEQ_00001
	CHECK(MACPGM_RUN_SEQ <> 0);

ALTER TABLE OI_MACRO_PROGRAMS
	ADD CONSTRAINT OIMACROPGM_MPMACROTYP_00001
	CHECK(MACPGM_TYPE IN ('F','R'));

ALTER TABLE OI_MACRO_PROGRAMS
	ADD CONSTRAINT OIMACROPGM_MPPGMNAM_00001
	CHECK( MACPGM_PROGRAM_NAME <> ' ' ) ;

ALTER TABLE OI_MACRO_PROGRAMS
	ADD CONSTRAINT OIMACROPGM_MPACTIVE_00001
	CHECK(MACPGM_ACTIVE IN ('Y','N'));

LABEL ON TABLE OI_MACRO_PROGRAMS
	IS 'Qualcomm Macro Processing Programs.' ;

LABEL ON COLUMN OI_MACRO_PROGRAMS
( MACPGM_MACRO_NUMBER IS 'Macro               Number' ,
	MACPGM_TYPE IS 'Macro               Type' ,
	MACPGM_RUN_SEQ IS 'Run                 Seq' ,
	MACPGM_PROGRAM_NAME IS 'Program              ' ,
	MACPGM_PROGRAM_LIBRARY IS 'Program              ',
      MACPGM_ACTIVE IS 'Active               ');

LABEL ON COLUMN OI_MACRO_PROGRAMS
( MACPGM_MACRO_NUMBER TEXT IS 'Macro Number' ,
	MACPGM_TYPE TEXT IS 'Macro Type Forward or Return' ,
	MACPGM_RUN_SEQ TEXT IS 'Program Run Sequence' ,
	MACPGM_PROGRAM_NAME TEXT IS 'Program to Run.' ,
	MACPGM_PROGRAM_LIBRARY TEXT IS 'Program to Run.',
      MACPGM_ACTIVE TEXT IS 'Record Active Y/N.');                                                             

To build new headers, just type commands into command line, fill in and type F14 and copy and paste to header and add tags. If you make a mistake, tool will give you a detailed message saying exactly where the error is located.  

Basically, it should be obvious that the flag *_> is what tells my utility that this instruction is what it is interested in. 

The @ variables are the substitution variables and can be assigned any meaning and are simply passed as a semi-colon delimited string. Currently my front end command COMPILE assigns the following meanings. 

/* Prepare substitution data. Current parameters are:                         */  
/*                                                                            */  
/*   @1 = Source file.                                                        */  
/*   @2 = Source file library.                                                */  
/*   @3 = Source member.                                                      */  
/*   @4 = Object name.                                                        */  
/*   @5 = Object library.                                                     */  
/*   @6 = Optimize *YES or *NO (Original Program Model.                       */  
/*   @7 = Object owner.                                                       */  
/*   @8 = Optimize ILE.                                                       */  
/*   @9 = ILE Module Debug View.                                              */  

If you feel you need others, you are free to add them up to 15 parameters. 

The utility consists of the following pieces:

EXTSRCCMD  – Extract commands from a source member. Must be run in a program.
  XV0003C  – CPP. Sets up and calls XV0003AR to extract strings. 
  XV0003AR – Extract strings and write to data queue.

EXCSRCCMD  - Execute source commands. Calls EXTSRCCMD to extract commands from header and than executes them one by one. 
  XV0004C  - CPP. 

COMPILE    - Compile is the PDM/WDSC interface. It accepts the parameters, validates input, builds parameter list and runs interactively or in batch the EXCSRCCMD.
  XV0005C  - CPP

Here is prompt of command. 

                    Create object using EXCSRCCMD. (COMPILE)                   
                                                                               
 Type choices, press Enter.                                                    
                                                                               
 Object . . . . . . . . . . . . .                 Name                         
   Library  . . . . . . . . . . .     *LIBL       Name, *LIBL                  
 Source file  . . . . . . . . . .                 Name, *RPGLE, *SQLLE, *RPG...
   Library  . . . . . . . . . . .     *LIBL       Name, *LIBL                  
 Source member  . . . . . . . . .                 Name                         
 Job description  . . . . . . . .                 Name                         
   Library  . . . . . . . . . . .     *LIBL       Name, *LIBL                  
 Optimize program(OPM)  . . . . .   *NO           *YES, *NO                    
 Optimize program(ILE)  . . . . .   *NONE         *NONE, *BASIC, *FULL         
 ILE Debug Level  . . . . . . . .   *ALL          *ALL, *STMT, *SOURCE...      
 Environment  . . . . . . . . . .   *WORKSTATION  *WORKSTATION, *GUI           
 Run Batch  . . . . . . . . . . .   *YES          *YES, *NO                    
 Send messages to . . . . . . . .   *USER         Name, *USER                  
   Library  . . . . . . . . . . .                 Name, *LIBL                  

--------------------------------------------------------------------------------
Here are the PDM options that you need.

PDM option:
                                                                             Option  . . . . . . . . : CO                                  
                                                                                
Command . . . . . . . . : COMPILE OBJ(&L/&N) SRCFILE(&L/&F) SRCMBR(&N) JOBD(&J)                                                               
 
If I compiling to production, I have this PDM option set up. 
                                                                                
Option  . . . . . . . . .   IN  

Command . . . . . . . . .   COMPILE OBJ(&L/&N) SRCFILE(&L/&F) SRCMBR(&N) JOBD(&J) OPTIMOPM(*YES) OPTIMILE(*BASIC) DEBUGVIEW(*LIST)                           
                                                                                
It just changes the compile options for production.

------------------------------------------------------------------------------------
WDSC setup. 

Note the *GUI and Batch(*NO). Setup under Work with Compile commands. You must set up for each source type.  

Note that you can edit all source types from the Work with Compile Commands and that you want to paste the following command into each source type (I use TXT for SQL commands) 

COMPILE OBJ(&L/&N) SRCFILE(&L/&F) SRCMBR(&N) ENV(*GUI) BATCH(*NO) /* *EVENTF SRCMBR(&N) */

Note the comment on the end. Very important to include this. This tells WDSC to return error messages. 

Once you create the command, you can right mouse button and move the Compile command to the top of the list.

Once Compile is setup, take the Compile option from the top menu or right mouse button on the source member in RSE and select Compile and the object will be compiled using the instructions in header. If you have OPTION(*EVENTF) included in the CRT* commands and the comment as documented above, you will get a listing of errors back, if any. 

You will not receive back error listings for commands that don’t have the OPTION command parameter unless you write your own commands to create your own event files as documented here under “Create your own Event Files”. 

http://www.itjungle.com/fhg/fhg080404-story01.html?

If you have your messages set to break using the SOFTLANDING Message Plug-in, you will get one message at a time. If you do have your messages set to break using the Softlanding Message Plug-in, you will need to switch to green to see the messages. 

Note that you will get some messages as errors even if they are not errors.

For example, if you say DLTPGM and the program as never been compiled before, you will get a message saying DLTPGM failed even though it is not a real error. 

A final message is always sent giving results. 

Well, hopefully this is as clear as mud. 

If you try this utility, please send me an e-mail and let me know how it working for you and any suggestions for improvement. 

I can be reached at:

Alan Campin
Alan0307d@bigfoot.com
(253) 266-7676 (Cell)