An RPGLE source member compiles into a module, and the module type decides whether it can start a program, whether it carries the RPG cycle, and what you may code outside a procedure. This page is the lookup for the three module types, the NOMAIN and MAIN keywords, the export and import rules, and the create command each module needs.
It is a lookup, not a build walkthrough. To build a service program step by step, read Build an ILE RPG Service Program. For the packaging model in plain terms, read IBM i Modules, Bound Programs, and Binding Directories Explained. For procedure basics, read Subprocedures and Service Programs in RPGLE.
Module types at a glance
IBM’s ILE RPG Reference describes three kinds of module. The keyword on the control specification decides which one you get.
| Module type | Keyword | RPG cycle | Main procedure | Can be the program-entry module |
|---|---|---|---|---|
| Cycle-main | none | Yes | Implicit: everything before the first procedure | Yes |
| Linear-main | MAIN(procedure-name) | No | A named subprocedure | Yes |
| No main | NOMAIN | No | None | No |
Two further rules come from the same chapter:
- A linear-main procedure can only be called through a program call. It cannot be called with a bound call.
- A
NOMAINmodule contains only subprocedures. IBM says it “cannot be the program-entry module of a program, since it has no main procedure”.
NOMAIN
NOMAIN marks a module with no main procedure and no cycle code. It is the normal home for procedures that other programs call.
**free
ctl-opt nomain;
dcl-proc refDouble export;
dcl-pi *n int(10);
inNumber int(10) const;
end-pi;
return inNumber * 2;
end-proc;
dcl-proc refLabel export;
dcl-pi *n varchar(30);
inNumber int(10) const;
end-pi;
return 'Number ' + %char(inNumber);
end-proc;
The export keyword on dcl-proc makes the procedure available to other modules. A module like this is created with CRTRPGMOD, which makes a *MODULE that cannot run by itself:
CRTRPGMOD MODULE(MYLIB/REFUTIL) SRCFILE(MYLIB/QRPGLESRC) SRCMBR(REFUTIL) DBGVIEW(*SOURCE)
The examples on this page were compiled from source file members. On the IBM i V7R5M0 system used to check them, the same commands with SRCSTMF stream-file source failed with RNS9339: Unable to open file, so the page does not rely on SRCSTMF. SRCSTMF is a documented parameter, and it may work on your system.
What NOMAIN changes:
| Rule | Detail |
|---|---|
| No program entry | A NOMAIN module has no program entry procedure, so CRTBNDRPG cannot create a program from it |
| How to use it | Bind it into a program with CRTPGM, next to a module that has a program entry procedure, or create a service program with CRTSRVPGM |
| No cycle | Language features that depend on the cycle must not be specified |
| Main source section | Allows full-procedural files, input specifications, definitions, declarative calculations and exception output. It does not allow primary or secondary files, heading, detail or total output, executable calculations (including *INZSR) or *ENTRY PLIST |
| Initialization | Happens when the first procedure in the module is called |
| Cleanup | A linear module has no implicit closing of global files and no implicit unlocking of data areas. They stay open or locked until the code closes or unlocks them |
IBM adds a tip: convert cycle modules to NOMAIN modules, except those that hold the program entry procedure, to remove unneeded cycle code.
MAIN (linear-main)
MAIN names one subprocedure as the program entry point and still leaves the cycle out.
**free
ctl-opt main(refMain) dftactgrp(*no) actgrp('REFDEMO');
dcl-proc refMain;
dcl-pi *n extpgm('REFMAIN');
end-pi;
dsply 'Linear-main program';
end-proc;
IBM’s rules for the linear-main procedure:
- A prototype for it must specify
EXTPGM. If there is no prototype but there is a procedure interface, the interface must specifyEXTPGM. - If the program has no parameters and is not called from an RPG program, neither a prototype nor a procedure interface is required.
- It cannot be exported:
EXPORTis not allowed on its procedure. - A recursive call to it is a dynamic program call.
Cycle-main modules that export procedures
A module with no MAIN or NOMAIN keyword is a cycle module. IBM warns against mixing the cycle with exported subprocedures:
- An exported subprocedure can be called first, before the cycle-main procedure. When the cycle-main procedure is called later, it initializes at that time, which can reopen files or reinitialize global data the subprocedures already use.
- Cycle-main initialization happens again if the cycle-main procedure ended abnormally or with
*inlron.
IBM’s recommendations are to move the cycle logic into a subprocedure and make the module NOMAIN, or to make it linear-main. If you must mix them, avoid *inlr, declare files USROPN and open and close them yourself.
Export and import
| Item | How | Notes |
|---|---|---|
| Export a procedure | export on dcl-proc | The name is exported in upper case unless extproc gives another name |
| Call an imported procedure | A prototype with no extpgm | Procedure names are imported implicitly into every module of the program when export is on the procedure |
| Export a data item | export on a dcl-s or dcl-ds | Only one module may define it as exported. Unnamed data structures and based items cannot be exported |
| Import a data item | import on the definition | It cannot have inz. The exporting module does the initialization |
| Choose the external name | extproc('NAME') or extproc(*dclcase) | *dclcase keeps the case you coded |
Details that catch people:
- A prototype with neither
extpgmnorextprocis a procedure, and the compiler gives it the upper-case form of its name. That is why an exportedrefDoubleis found asREFDOUBLE. extprocmakes the call a bound call.extpgmmakes it a dynamic program call.- A name that starts with
CEEor an underscore is treated as a system built-in. Do not name your proceduresCEE.... - The
exportkeyword on a definition exports data only. Procedure names are exported withexportondcl-proc.
Which create command for which module
| Source has | Create with | Result |
|---|---|---|
Cycle-main or MAIN, to run as a program | CRTBNDRPG | A *PGM made from one source member |
| Any module type, to bind later | CRTRPGMOD | A *MODULE |
NOMAIN | CRTRPGMOD, then CRTPGM or CRTSRVPGM | CRTBNDRPG is not allowed |
CRTBNDRPG has DFTACTGRP(*YES) as its default. IBM says static binding is not available with DFTACTGRP(*YES), so a program that uses binding directories or calls bound procedures needs DFTACTGRP(*NO). See the RPGLE Activation Groups Reference.
Common mistakes
- Compiling a
NOMAINsource withCRTBNDRPG. - Putting executable calculations or
*INZSRin the main source section of aNOMAINorMAINmodule. - Exporting the linear-main procedure.
- Mixing a cycle-main procedure with exported subprocedures and then ending with
*inlr. - Expecting
exporton a data definition to export a procedure. - Using the
calloperation, which makes a dynamic program call, where a bound procedure call through a prototype is needed. - Forgetting that global files in a linear module stay open until your code closes them.
FAQ
What does NOMAIN do in RPGLE?
It says the module has no main procedure and no cycle code, so it holds only subprocedures. It cannot be the entry module of a program.
Can I run a NOMAIN module on its own?
No. Bind it into a program with CRTPGM, or into a service program with CRTSRVPGM, and call the procedures from another module.
What is the difference between MAIN and NOMAIN?
MAIN names a procedure that starts the program and is called by a program call. NOMAIN has no entry procedure at all. Neither includes the RPG cycle.
Do I need NOMAIN for a service program?
No, but it is the normal choice. IBM says modules in a service program may have program entry procedures, that these are ignored, and that a service program has no entry point of its own. NOMAIN states the intent, removes cycle code, and is what IBM’s tip recommends.
Summary
- Three module types exist: cycle-main (no keyword), linear-main (
MAIN) and no-main (NOMAIN). NOMAINandMAINleave out the cycle, which limits what the main source section may hold.- A
NOMAINmodule cannot be created into a program withCRTBNDRPG. UseCRTRPGMODand thenCRTPGMorCRTSRVPGM. - Export procedures with
exportondcl-proc. Export and import data withexportandimporton the definition. - Next: the RPGLE Service Programs Reference for what a service program is, and the RPGLE Binder Language and Signatures Reference for controlling its exports.
Sources: IBM i 7.5 ILE RPG Reference (RPG module types, NOMAIN, MAIN, DFTACTGRP, EXPORT, IMPORT, EXTPROC) and IBM i 7.5 ILE Concepts (service programs). The examples have been reviewed against that text. They have not been compiled or run.