This chapter is the complete reference for the rpgc command: every option, its argument, its default, and how it interacts with the others. It describes Triton RPG 2026.09.3.

For a task-oriented introduction, start with Getting Started; for include paths and ExtName, see Compiling RPG Programs; for display files, see Display Files and Screen I/O; for Java interop, see Java Interoperability.

Synopsis

rpgc [options] <source-file>

On Windows, invoke the compiler through its JAR - the options are identical:

java -jar rpgc.jar [options] <source-file>

Exactly one source file is compiled per invocation. Options may appear before or after the source file, and in any order.

Passing more than one source file is an error - the compiler names the files it was given and exits 1, rather than compiling one of them and discarding the rest:

$ rpgc -o out/ A.rpgle B.rpgle
[ERROR] Only one source file may be given per invocation (got 2: A.rpgle, B.rpgle).

This means rpgc *.rpgle will not quietly compile only the last member. To compile several, loop:

for f in *.rpgle; do rpgc -o out/ "$f" || exit 1; done

Invoking rpgc with no arguments prints the usage summary and exits with status 1.

Malformed command lines

Most options that take a value are checked. Omitting the value is reported and never crashes the compiler:

$ rpgc HELLO.rpgle --output
[ERROR] --output requires an output directory.

An option accidentally given where a value belongs is caught too, rather than being swallowed as the value:

$ rpgc --output --strict HELLO.rpgle
[ERROR] --output requires an output directory, but was followed by the option --strict.

An unrecognized option is rejected outright:

$ rpgc --optimise HELLO.rpgle
[ERROR] Unknown option: --optimise

All of these exit 1 and write nothing to the output directory.

Exit status

Status Meaning
0 Compilation succeeded. Every requested class was written to the output directory.
1 Compilation failed, or the command was rejected. This covers a compile error, an unusable option, a missing source file, and a license failure alike.

rpgc does not distinguish failure causes by exit code. A build script should treat any non-zero status as failure and read the diagnostic text (see below) to find out why.

Output streams

The two streams carry different things, and build scripts should treat them differently:

Stream Content
stdout The compiled artifact list - one Compiled: <path> line per emitted class - and the output of --version and --machine-key. This is the machine-readable channel: rpgc --version and rpgc --machine-key can be captured directly.
stderr Everything else: progress (Compiling <target>...), diagnostics, the usage summary, and license errors.

Diagnostics are streamed as they are produced rather than batched at the end, so a long compile reports its first error immediately. Each one is formatted:

[ERROR] INVCALC.rpgle:27:14 - TRN2135: Undefined variable 'UnitPric'
[WARN] INVCALC.rpgle:31:1 - TRN0014: Unrecognized control option 'CURSYMM'; it is ignored

The code (TRN2135 above) identifies the diagnostic; every code is catalogued in the Diagnostic Reference.

Option index

Option Argument Default
-o, --output directory ./out
--class-name class name derived from the source filename
--package Java package none (default package)
--target JVM version 17
--disable-annotations - annotations are emitted
--schema-map file none (no schema is verified)
--lib - off (a main() is generated)
--screen class name TerminalScreenHandler
--screen-title text none
--ebcdic - off (source is read as UTF-8)
--codepage codepage IBM037
--include-path directory none (repeatable)
--dds-path directory none
--bnddir NAME=PATH none (repeatable)
--classpath classpath none
--jdbc-url-env env var name JDBC_URL
--jdbc-user-env env var name JDBC_USER
--jdbc-password-env env var name JDBC_PASSWORD
--jdbc-driver-env env var name JDBC_DRIVER
--verify-jdbc-url JDBC URL none (verify mode off)
--verify-jdbc-user-env env var name JDBC_USER
--verify-jdbc-password-env env var name JDBC_PASSWORD
--verify-jdbc-driver driver class none
--jdbc-driver-path jar or directory none
--verify-library library name none (repeatable)
--license file path $RPGC_LICENSE, then ~/.rpgc/license.lic
--machine-key - -
--user-mode inject, os, or signon by output kind - see --user-mode
--strict - off
-v, --verbose - off
--version - -
-h, --help - -

Output and class naming

-o, --output <dir>

Directory to write .class files into. Defaults to ./out. The directory is created if it does not exist. When --package is also given, classes are written into the package's subdirectory tree beneath this directory, as the JVM requires.

rpgc -o build/classes INVCALC.rpgle

--class-name <name>

Overrides the generated class name. By default the class name is derived from the source filename. Use this when the source member name and the desired class name differ - most often when a legacy member name is not a legal Java identifier, or when two members in different libraries share a name.

rpgc --class-name InvoiceCalculator INVCALC.rpgle

--package <name>

Emits the generated class into a named Java package. The default is the unnamed (default) package. The value must be a dot-separated sequence of legal Java identifiers; anything else is rejected before compilation begins.

rpgc --package com.acme.payroll PAYCALC.rpgle

Placing compiled programs in a package is strongly recommended for anything embedded in a larger Java application, where default-package classes are awkward to import.

--target <version>

The JVM class-file version to emit. Defaults to 17. Accepted values are 8 (or 1.8), 9 (or 1.9), and 10 through 21. Any other value is rejected.

Lowering the target lets compiled programs run on an older JVM, but the runtime library (triton-rpg.jar) still requires the Java version it was built for - retargeting the class file does not retarget the runtime.

rpgc --target 11 INVCALC.rpgle

--disable-annotations

Suppresses the RPG metadata annotations that are otherwise emitted on generated classes. Annotations are on by default. They are what lets Java callers and tooling discover a program's parameters, record formats, and exported procedures by reflection; turn them off only when you need the smallest possible class files and nothing reflects over them.

--schema-map <file>

Names a YAML file describing how your migration represented RPG columns on your target database. Supplying one turns on schema conformance checking: the first time each file is opened, its columns are compared against the contract, and the program stops with a diagnostic if they disagree.

rpgc --schema-map schema-map.yaml INVCALC.rpgle

With no --schema-map, nothing is verified and the compiled program runs against any supported database. Supplying one is a deliberate narrowing: the file is written for one target, so the artifact becomes bound to it.

The file, its precedence rules, and the migration workflow are described in JDBC database connectivity.

Compilation mode

--lib

Library mode. Suppresses main() and produces a class intended to be embedded and driven by a caller, rather than launched from a shell. Use this for NOMAIN service modules and for any program you intend to call from Java.

--lib controls how the output is built; CTL-OPT NOMAIN is what makes the source a module. A NOMAIN source must be compiled with --lib - without it the compile fails with TRN3031, since a NOMAIN module has no main procedure to run. A source without NOMAIN may still be compiled with --lib when you want it callable from Java rather than launchable from a shell.

Cannot be combined with --screen: library mode generates no main(), so there is no entry point in which to wire a screen handler. The combination is rejected.

rpgc --lib CUSTSVC.rpgle

--user-mode <inject|os|signon>

Selects how the activation-group user profile is established at runtime. The user profile is the identity reported by INZ(*USER), PSDS POS 254/358, and (when reconciled) SQL USER.

When omitted, the mode is chosen by the output kind: --lib defaults to inject; a standalone executable defaults to os.

A standalone program therefore always runs under a user profile, and INZ(*USER) never initializes to blanks. The default establishes that identity without changing how the program reaches its database: it still connects from the JDBC environment variables, so an unattended batch or embedded run needs no operator. Ask for signon when you want the program to prompt instead.

Because a sign-on has to be validated against a database connection, asking for signon in a program that issues no SQL shows no sign-on screen; the profile comes from the host login, exactly as os does.

--screen <class>

The screen handler class that the generated main() instantiates. Defaults to TerminalScreenHandler, the JLine-backed green-screen front end. Supply your own implementation to change how a compiled program presents its display files when run standalone.

Requires JLine on the runtime classpath when the default handler is used. Cannot be combined with --lib.

--screen-title <text>

Sets the window/session title presented by the screen handler.

Source encoding

--ebcdic

Reads the source file as EBCDIC rather than UTF-8. Legacy members transferred from an IBM i in binary form need this; members transferred as text and translated in flight generally do not.

--codepage <cp>

The codepage used to decode the source, given as a JDK charset name. Defaults to IBM037 (US/Canada); any EBCDIC charset the JVM provides is accepted - IBM500, IBM1047, IBM273 - IBM297, IBM871 and IBM01140 - IBM01147 among them. Only meaningful together with --ebcdic.

rpgc --ebcdic --codepage IBM500 INVCALC.rpg

Resolution paths

--include-path <dir>

A directory to search for /COPY and /INCLUDE members. Repeatable; directories are searched in the order given, and the first match wins. The flag order is significant - list overrides before the base copybook directory.

rpgc --include-path ./local-copybooks --include-path ./vendor-copybooks INVCALC.rpgle

--dds-path <dir>

The directory searched for external description source. A program with a WORKSTN file needs its display file at compile time; this is how the compiler finds it.

Each kind of description is looked up by the object's name plus an extension, first beside the RPG source and then in this directory:

Extension Description
.dspf display file (WORKSTN)
.prtf printer file (PRINTER), for an externally-described printer
.pf physical file
.lf logical file
.table SQL DDL (CREATE TABLE)
.msgf message file (ADDMSGD source), for DDS ERRMSGID

--bnddir <NAME=PATH>

Maps a binding-directory name to a filesystem path. Repeatable. The argument must contain an =; a bare name is rejected.

Binding directories are named and searched in order, exactly as on IBM i.

rpgc --bnddir APPBND=./lib/app --bnddir SYSBND=./lib/system MAINPGM.rpgle

--classpath <cp>

Additional classpath entries for compile-time resolution - needed when a program calls Java classes directly, or binds to procedures in an already-compiled module.

Multiple entries are separated by the platform path separator (: on Unix, ; on Windows); a Windows drive letter such as C:\build\out is kept intact, not read as a separator, so resolution is identical on every host.

Directory entries (and the directories named by --bnddir) are searched recursively, so a module compiled into a Java package with --package is found in its package subdirectory just like a package-less one at the top level. The bound call resolves to the module's fully qualified class name; when the same procedure is exported by more than one module, the first one found wins, matching binding-directory search order on IBM i.

Runtime JDBC environment variable names

These four options do not connect to a database. They name the environment variables that the compiled program will read at runtime to find its connection. The name is baked into the class file as a constant; the value is read when the program runs. Use them when one binary must talk to a different database than the environment's default variables point at.

Option Names the variable holding Default
--jdbc-url-env <name> the JDBC URL JDBC_URL
--jdbc-user-env <name> the database user JDBC_USER
--jdbc-password-env <name> the database password JDBC_PASSWORD
--jdbc-driver-env <name> the JDBC driver class JDBC_DRIVER
# This program will read PAYROLL_DB_URL / PAYROLL_DB_USER at runtime.
rpgc --jdbc-url-env PAYROLL_DB_URL --jdbc-user-env PAYROLL_DB_USER PAYCALC.rpgle

These names are honored on every run path - a program's own main() and the headless bridge alike. See JDBC Database Connectivity.

Verify mode (compile-time catalog resolution)

Verify mode lets the compiler query a live Db2 catalog at compile time to resolve externally-described files - the ExtName data structures and DDS-described record formats whose layouts live in the database rather than in your source. Without it, those layouts must be resolvable from local DDS.

Verify mode is the only part of the compiler that opens a database connection, and it is off unless --verify-jdbc-url is given.

--verify-jdbc-url <url>

The JDBC URL for catalog queries. Supplying it enables verify mode.

--verify-jdbc-user-env <name>

Names the environment variable holding the catalog user. Defaults to JDBC_USER. The compiler reads the credential from that variable at compile time.

--verify-jdbc-password-env <name>

Names the environment variable holding the catalog password. Defaults to JDBC_PASSWORD.

--verify-jdbc-driver <class>

The JDBC driver class for the catalog connection - for Db2 for i, com.ibm.as400.access.AS400JDBCDriver. Optional: if omitted, the driver is discovered from --jdbc-driver-path through the standard JDBC service declaration.

--jdbc-driver-path <path>

Where to load the JDBC driver from: a jar, a directory of classes, or several of either separated by the platform path separator (: on Unix, ; on Windows).

Verify mode needs this. rpgc is a self-executing jar, and a Java program launched from a jar ignores -cp and $CLASSPATH - so a driver jar you place on the classpath cannot be seen by the compiler, no matter how you set it. --jdbc-driver-path is how the driver reaches verify mode. Point it at your jt400.jar:

rpgc --jdbc-driver-path /opt/jt400/jt400.jar \
     --verify-jdbc-url 'jdbc:as400://ibmi.example.com/APPLIB' \
     ...

The driver is used only for catalog queries and is never registered process-wide. --classpath is unrelated: it resolves service-module exports at compile time, not JDBC drivers.

--verify-library <lib>

A library to search for catalog objects. Repeatable; libraries are searched in the order given, mirroring the IBM i library list.

export JDBC_USER=BUILDUSR
export JDBC_PASSWORD=...            # from your CI secret store, never inline

rpgc --jdbc-driver-path /opt/jt400/jt400.jar \
     --verify-jdbc-url 'jdbc:as400://ibmi.example.com' \
     --verify-jdbc-driver com.ibm.as400.access.AS400JDBCDriver \
     --verify-library APPLIB --verify-library SYSLIB \
     INVCALC.rpgle

If no driver can be found for the URL, the compile stops with an error naming the URL and this option - not a compiler crash.

Credentials are never accepted on the command line

--verify-jdbc-user and --verify-jdbc-password exist and are deliberately rejected. Passing either one fails the command with an explanatory error rather than compiling.

This is not an oversight. A credential in an argument is visible in the operating system's process table to every other user on the machine, and it is written to shell history and CI logs. The -env forms exist so the value reaches the compiler through the environment instead. If a script of yours passes these flags, it was never working - fix it to export the variable and use --verify-jdbc-user-env / --verify-jdbc-password-env.

Licensing

--license <path>

Path to the license file. When omitted, the compiler looks in this order:

  1. the --license path, if given
  2. the RPGC_LICENSE environment variable
  3. ~/.rpgc/license.lic

Validation is offline - no network connection is made or required. See Licensing.

--machine-key

Prints this machine's key to stdout and exits 0. The key identifies the machine a license is issued for; you need it to obtain a license.

$ rpgc --machine-key
Machine Key: TRP-XXXX-XXXX-XXXX

Provide this Machine Key to your account representative, or visit
https://portal.whitehorn.ltd to obtain a license.

It works with no license installed - or with an expired or corrupt one. It takes no source file. If the compiler does not recognize the platform it is running on, it cannot derive a key: it reports the platform it saw and exits non-zero rather than printing a partial one.

See Licensing for the full workflow.

Diagnostics and information

--strict

Treats warnings as errors. A compile that would otherwise succeed with warnings instead fails with a non-zero exit status. Recommended for CI, where a warning nobody reads is a warning nobody fixes.

-v, --verbose

Prints additional progress detail to stderr. Useful when a compile fails in a way the diagnostic alone doesn't explain, and when reporting a problem to support - see Getting Support.

--version

Prints the compiler version to stdout and exits 0, e.g. rpgc 2026.09.3. Written to stdout rather than stderr precisely so it can be captured:

rpgc --version              # -> rpgc 2026.09.3

-h, --help

Prints the usage summary to stderr and exits.

Environment variables

Read by the compiler, at compile time:

Variable Purpose
RPGC_LICENSE Path to the license file, when --license is not given.
RPGC_SQL_DIALECT Also read at compile time: in verify mode it selects whether the native Db2-for-i catalog or standard JDBC metadata is used.
(named by --verify-jdbc-user-env, default JDBC_USER) Catalog user for verify mode.
(named by --verify-jdbc-password-env, default JDBC_PASSWORD) Catalog password for verify mode.

Read by a compiled program, at run time:

Variable Purpose
(named by --jdbc-url-env, default JDBC_URL) JDBC URL.
(named by --jdbc-user-env, default JDBC_USER) Database user.
(named by --jdbc-password-env, default JDBC_PASSWORD) Database password.
(named by --jdbc-driver-env, default JDBC_DRIVER) JDBC driver class.
RPGC_SQL_DIALECT Forces the SQL backend when a driver misreports its product - see SQL backends.

A program that uses neither embedded SQL nor a disk file reads none of these and needs no database configuration at all.

Getting support

Support is available by email at support@whitehorn.ltd, through the client portal at portal.whitehorn.ltd, or from your account representative. Response commitments are governed by your contract - your account representative is the right contact for questions about them.

When reporting a compiler problem, include: