Binding Directory

25 Views


A binding directory (*BNDDIR) on IBM i is a container that lists what to bind to (service programs, modules, or even other binding directories) when you create or update programs and service programs. It saves you from spelling out a long list of BNDSRVPGM / modules every time you compile.


What it’s for

  • Simplify builds: one place to list common dependencies.

  • Consistency: every program using the BNDDIR picks up the same set of service programs.

  • Layering: you can nest BNDDIRs (a BNDDIR can reference another BNDDIR).


What can a BNDDIR contain?

  • *SRVPGM (service programs)

  • *MODULE (modules)

  • *BNDDIR (other binding directories)

The binder searches entries in the order they appear in the directory, and searches BNDDIRs you pass on the compile command left to right.


Core commands

/* Create a binding directory */
CRTBNDDIR BNDDIR(MYLIB/APPBND)

/* Add entries */
ADDBNDDIRE BNDDIR(MYLIB/APPBND) OBJ((MYLIB/UTILSRV *SRVPGM)
                                    (MYLIB/LOGSRV  *SRVPGM)
                                    (MYLIB/BASEBND *BNDDIR))

/* Display / maintain */
WRKBNDDIRE BNDDIR(MYLIB/APPBND)
DSPBNDDIR  BNDDIR(MYLIB/APPBND)

/* Remove entry */
RMVBNDDIRE BNDDIR(MYLIB/APPBND) OBJ(MYLIB/LOGSRV) OBJTYPE(*SRVPGM)

Using a BNDDIR at compile time

1) With CRTBNDRPG (one-step create)

CRTBNDRPG PGM(MYLIB/MAINPGM)
          SRCFILE(MYLIB/QRPGLESRC)
          BNDDIR(MYLIB/APPBND)

2) With CRTRPGMOD + CRTPGM (two-step)

CRTRPGMOD MODULE(MYLIB/MAINMOD) SRCFILE(MYLIB/QRPGLESRC)
CRTPGM    PGM(MYLIB/MAINPGM) MODULE(MYLIB/MAINMOD) BNDDIR(MYLIB/APPBND)

3) Creating a service program that imports from others

CRTRPGMOD  MODULE(MYLIB/BILLING)
CRTSRVPGM  SRVPGM(MYLIB/BILLINGSRV)
           MODULE(MYLIB/BILLING)
           BNDDIR(MYLIB/APPBND)           /* resolve imports here */
           EXPORT(*SRCFILE) SRCFILE(MYLIB/QSRVSRC) SRCMBR(BILLINGSRV)

4) Rebinding an existing program to new entries

UPDPGM PGM(MYLIB/MAINPGM) BNDDIR(MYLIB/APPBND)

RPG shortcut: specify BNDDIR in the source

ctl-opt dftactgrp(*no) actgrp(*caller)
        bnddir('APPBND');   // library must be on compile-time LIBL

(You can qualify it like bnddir('MYLIB/APPBND') if you prefer.)


How this relates to binder source & signatures

  • BNDDIR just tells the binder where to find exports.

  • Binder source (QSRVSRC) in your service programs controls what you export and the signature (version).

  • If you change a service program’s signature, callers must be re-created/rebound (BNDDIR won’t avoid that).
    If you keep the signature the same (bug fix), you can rebuild the SRVPGM and avoid recompiling callers.


Typical setup pattern

  1. Create one BNDDIR per application layer:

    • APPBND → app-level SRVPGMs (e.g., UTILSRV, LOGSRV, SECURESrv)

    • BASEBND → low-level/common SRVPGMs

  2. Point programs and higher-level SRVPGMs to APPBND.

  3. Keep APPBND tidy and order entries so most commonly-used SRVPGMs are earlier.


Gotchas & tips

  • Order matters: the binder picks the first matching export it finds.

  • Reproducibility: pin exact service programs in BNDDIR; avoid relying on LIBL accidents.

  • Don’t use EXPORT(*ALL) in production SRVPGMs—use binder source to control exports and signatures.

  • Nesting BNDDIRs is fine, but avoid circular references.

  • If an import can’t be resolved, you’ll get a binding error at create time; check which symbol is missing and add the correct SRVPGM to your BNDDIR.


Minimal working example

Service program:

// UTILMOD.RPGLE
ctl-opt dftactgrp(*no) actgrp(*caller);
dcl-proc ToUpper export;
  dcl-pi *n varchar(256); s varchar(256); end-pi;
  return %upper(s);
end-proc;
CRTRPGMOD  MODULE(MYLIB/UTILMOD)
CRTSRVPGM  SRVPGM(MYLIB/UTILSRV) MODULE(MYLIB/UTILMOD)
           EXPORT(*SRCFILE) SRCFILE(MYLIB/QSRVSRC) SRCMBR(UTILSRV)

QSRVSRC/UTILSRV:

STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('UTIL 1.0')
  EXPORT SYMBOL('TOUPPER')
ENDPGMEXP

Binding directory:

CRTBNDDIR  BNDDIR(MYLIB/APPBND)
ADDBNDDIRE BNDDIR(MYLIB/APPBND) OBJ((MYLIB/UTILSRV *SRVPGM))

Program using it:

// MAINPGM.RPGLE
ctl-opt dftactgrp(*no) actgrp(*caller) bnddir('MYLIB/APPBND');

dcl-pr ToUpper varchar(256) extproc(*dclcase);
  s varchar(256);
end-pr;

dsply ToUpper('hello ibmi');
*inlr = *on; return;
CRTBNDRPG PGM(MYLIB/MAINPGM) SRCFILE(MYLIB/QRPGLESRC)

 

Post Comments