On any other platform, code is a file in a directory. Not here — or at least not
traditionally: code lives inside a source file, which is an object of type *FILE in a
library, and each program is a member of that file.
A source file is to a project what a directory is, except that it is a database object. That is why source can be queried in SQL, and also why you cannot give it a long name or put a subdirectory inside it.
The names you meet
By convention, one source file per language type:
| File | Holds |
|---|---|
QRPGLESRC |
ILE RPG sources, and RPG with embedded SQL |
QRPGSRC |
old-model RPG sources, where any remain |
QCLSRC |
CL sources |
QDDSSRC |
file descriptions: physical, logical, display, printer |
QCMDSRC |
command definitions |
QSQLSRC |
SQL scripts |
The member type — RPGLE, SQLRPGLE, CLLE, PF, LF, DSPF, PRTF, CMD — is
an attribute of the member, not of the file holding it, and decides how the editor colours
it and which compiler is expected.
WRKMBRPDM FILE(PRODLIB/QRPGLESRC)
DSPFD FILE(PRODLIB/QRPGLESRC) TYPE(*MBRLIST)
And in SQL, the convenient way to search across all sources at once:
SELECT TABLE_NAME, SYSTEM_TABLE_SCHEMA, SOURCE_TYPE, LAST_SOURCE_UPDATE_TIMESTAMP
FROM QSYS2.SYSPARTITIONSTAT
WHERE SYSTEM_TABLE_NAME = 'QRPGLESRC'
Note
a source file has fixed-length lines. Historic ones were 92 characters —
twelve of sequence number and date, eighty of code — and QRPGLESRC started at 112, that
is a hundred usable characters. A line longer than the record is not cut at the right
place with a warning: it is simply truncated, and what comes out is syntactically valid
and wrong. It is why some sources are formatted so tightly they look written out of
spite.
Code on the IFS
For several releases now the compilers have also accepted sources as IFS files — ordinary files in ordinary directories, with long names and no line-length limit.
CRTBNDRPG PGM(PRODLIB/INVOICES) SRCSTMF('/home/dev/invoices/invoices.rpgle')
Why this matters is not aesthetics: it is that a file in a directory can go under git. Version control over source file members has always been done with dedicated change management products, which work and cost money; with sources on the IFS you use the same tools as the rest of the world, and newcomers already know them.
Tip
this is not a decision to take for all the code at once. What works is leaving historic code where it is and putting on the IFS what gets written from now on, or the single application being rebuilt. The two coexist without trouble: the compiler produces the same object.
From source to object
Compiling does not produce an executable file: it produces an object in the library you named, with everything that follows — it has an owner, authorities, a description, and it is saved and restored like anything else.
CRTBNDRPG PGM(PRODLIB/INVOICES) SRCFILE(PRODLIB/QRPGLESRC) SRCMBR(INVOICES)
CRTBNDCL PGM(PRODLIB/LAUNCH) SRCFILE(PRODLIB/QCLSRC) SRCMBR(LAUNCH)
CRTPF FILE(PRODLIB/ORDERS) SRCFILE(PRODLIB/QDDSSRC) SRCMBR(ORDERS)
The object remembers where it came from, and this is one of the most useful things about the system:
DSPOBJD OBJ(PRODLIB/INVOICES) OBJTYPE(*PGM) DETAIL(*SERVICE)
Among the service data are the source file, the member, and the source's last-changed timestamp as of compile time. Comparing it with the member's date tells you whether the object in production matches the source in front of you.
Warning
this is the check to run before touching anything in an environment you do not know. Source newer than the object means somebody changed the code and did not compile it, or compiled it somewhere else: recompiling at that point ships changes nobody asked for and nobody tested.
SELECT OBJNAME, OBJTEXT, SOURCE_FILE, SOURCE_LIBRARY, SOURCE_MEMBER,
SOURCE_TIMESTAMP, OBJCREATED
FROM TABLE(QSYS2.OBJECT_STATISTICS('PRODLIB', '*PGM'))
ORDER BY SOURCE_TIMESTAMP DESC
The compile listing
Every compile produces a spooled file: the compile listing. It holds the numbered source, the errors, and — on request — the expanded code after copies and after SQL precompilation.
It is where you look when an error makes no sense, because it shows the code as the
compiler saw it, which is not always what you wrote: /COPY members have been expanded,
and in a source with embedded SQL the EXEC SQL statements have been rewritten as calls.
Tip
compiling with OPTION(*EVENTF) also produces an events file that modern editors
read to show errors on the right line, instead of making you hunt through the listing. It
is how RDi and the VS Code extensions work.
What is missing, compared with other platforms
Three things, worth knowing straight away instead of looking for them.
There is no project file. No Makefile or pom.xml as standard: the build order —
files first, then modules, then programs — is knowledge held by whoever works there, or
lives inside a change management product, or inside a hand-written CL that compiles
everything in sequence. Modern tools fill this gap, and the tools chapter covers them.
There is no virtual environment. Separation between test and production is done with libraries and the library list: same program, different libraries. That is why the library list is worth understanding properly, and why a mistake there costs more than elsewhere.
There is no package to ship. You move an object from one library to another, or save and restore. A production release is a copy of objects, and whoever does it by hand eventually forgets one.
Comments
No comments yet. Be the first to comment!
You need an account to comment. Log in · Sign up