@profoundlogic/codermake 2.0.8 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -139,3 +139,52 @@ ifdef CODERMAKE_LIBRARY_MAP
139
139
  else
140
140
  MODULE_PARM = module($(foreach m,$(filter %.module,$^),$(call ibmi_name_sh,$(m))))
141
141
  endif
142
+
143
+ ######
144
+ # RPG III (.rpg / .rpg38) /COPY member support.
145
+ #
146
+ # RPG III cannot compile directly from IFS stream files, so /COPY directives
147
+ # always reference source members. codermake creates a source member for every
148
+ # RPG III /COPY prerequisite (in addition to the main program source) before
149
+ # running the compile. Each /COPY prerequisite is listed in the rule so its
150
+ # location in the source tree encodes where the member must be created:
151
+ #
152
+ # <libraryDir>/<sourceFile>/<member>.<ext> (multi-library output)
153
+ # <sourceFile>/<member>.<ext> (single-library output)
154
+ #
155
+ # The member name comes from the file's base name, the source physical file
156
+ # from the immediate parent directory, and the target library from the leading
157
+ # library-directory segment (multi-library) or the program's own library
158
+ # (single-library). This lets the same /COPY member name resolve to different
159
+ # members in different libraries.
160
+ ######
161
+
162
+ # A literal newline, so a $(foreach ...) can emit one recipe line per member.
163
+ define NL
164
+
165
+
166
+ endef
167
+
168
+ # The RPG III /COPY prerequisites of the current rule: every .rpg/.rpg38
169
+ # prerequisite except the main program source ($<).
170
+ RPG3_COPY_MEMBERS = $(filter-out $<,$(filter %.rpg %.rpg38,$^))
171
+
172
+ # Source physical file name for a /COPY prerequisite = its immediate parent dir.
173
+ copy_src_file = $(notdir $(patsubst %/,%,$(dir $(1))))
174
+
175
+ ifdef CODERMAKE_LIBRARY_MAP
176
+ # Parse CODERMAKE_RESOLVED_LIBRARY_MAP ("LIBA=APPLIBA LIBB=APPLIBB") into
177
+ # per-directory lookup variables CODERMAKE_LIBMAP_<dir> so a /COPY prereq's
178
+ # leading library-directory segment can be mapped to its IBM i library.
179
+ define _CODERMAKE_LIBMAP_ENTRY
180
+ CODERMAKE_LIBMAP_$(word 1,$(subst =, ,$(1))) := $(word 2,$(subst =, ,$(1)))
181
+ endef
182
+ $(foreach _p,$(CODERMAKE_RESOLVED_LIBRARY_MAP),$(eval $(call _CODERMAKE_LIBMAP_ENTRY,$(_p))))
183
+
184
+ # Target library for a /COPY prerequisite = its leading library-dir segment
185
+ # mapped through the resolved library map.
186
+ copy_src_lib = $(CODERMAKE_LIBMAP_$(firstword $(subst /, ,$(1))))
187
+ else
188
+ # Single-library output: every member goes to the program's own library.
189
+ copy_src_lib = $(TARGET_LIB)
190
+ endif
@@ -47,6 +47,20 @@ test -e '$(TARGET_LIB_PATH)/$(2).file/$(call ibmi_name,$(1)).mbr' || system "add
47
47
  cat '$(1)' | Rfile -Qw '$(TARGET_LIB)/$(2)($(call ibmi_name,$(1)))'
48
48
  endef
49
49
 
50
+ ######
51
+ # Utility to create a source member in an explicitly named library. Used for
52
+ # RPG III /COPY members, whose target library is derived from the prerequisite
53
+ # path (see base.mk) and may differ from the program's own library.
54
+ # $(1) = IFS file path (source type is derived from file extension)
55
+ # $(2) = source file name (e.g., qcpysrc)
56
+ # $(3) = target IBM i library
57
+ ######
58
+ define CREATE_COPY_MEMBER
59
+ test -e '/qsys.lib/$(3).lib/$(2).file' || system "crtsrcpf file($(3)/$(2))"
60
+ test -e '/qsys.lib/$(3).lib/$(2).file/$(call ibmi_name,$(1)).mbr' || system "addpfm file($(3)/$(2)) mbr($(call ibmi_name_sh,$(1))) srctype($(subst .,,$(suffix $(1))))"
61
+ cat '$(1)' | Rfile -Qw '$(3)/$(2)($(call ibmi_name,$(1)))'
62
+ endef
63
+
50
64
  ######
51
65
  # Utility to build an object via CL commands in a separate file.
52
66
  # $(1) = Object path
@@ -101,11 +115,11 @@ $(info ===)
101
115
  ifndef CODERMAKE_LIBRARY_MAP
102
116
  $(LIBRARY_PATH):
103
117
  $(call SETUP_LOG,$(notdir $@))
104
- system "crtlib $(LIBRARY) *test aut(*use) crtaut(*use)"
118
+ test -e '$(LIBRARY_PATH)' || system "crtlib $(LIBRARY) *test aut(*use) crtaut(*use)"
105
119
  else
106
120
  /qsys.lib/%.lib:
107
121
  $(call SETUP_LOG,$(notdir $@))
108
- system "crtlib $* *test aut(*use) crtaut(*use)"
122
+ test -e '/qsys.lib/$*.lib' || system "crtlib $* *test aut(*use) crtaut(*use)"
109
123
  endif
110
124
 
111
125
  ######
@@ -181,6 +195,39 @@ $(SET_LIBL)
181
195
  system "crtclpgm pgm($(TARGET_LIB)/$(call ibmi_name_sh,$@)) srcfile($(TARGET_LIB)/qclsrc) output(*print)"
182
196
  endef
183
197
 
198
+ # Build System/38 compatible OPM CL program (QSYS38/CRTCLPGM).
199
+ # QSYS38/CRTCLPGM has no REPLACE parameter and fails if the program exists, so
200
+ # delete any existing program object first.
201
+ define BUILD_CLP38_PGM
202
+ $(call SETUP_LOG,$(notdir $@))
203
+ $(call CREATE_SOURCE_MEMBER,$<,qclsrc)
204
+ $(SET_LIBL)
205
+ if test -e '$(TARGET_LIB_PATH)/$(call ibmi_name,$@).pgm'; then system "dltpgm $(TARGET_LIB)/$(call ibmi_name_sh,$@)"; fi
206
+ system "qsys38/crtclpgm pgm($(TARGET_LIB)/$(call ibmi_name_sh,$@)) srcfile($(TARGET_LIB)/qclsrc) srcmbr($(call ibmi_name_sh,$<)) option(*source)"
207
+ endef
208
+
209
+ # Build RPG/400 (RPG III) program (CRTRPGPGM). Creates the program source
210
+ # member plus a source member for every /COPY prerequisite before compiling.
211
+ define BUILD_RPG_PGM
212
+ $(call SETUP_LOG,$(notdir $@))
213
+ $(call CREATE_SOURCE_MEMBER,$<,qrpgsrc)
214
+ $(foreach c,$(RPG3_COPY_MEMBERS),$(call CREATE_COPY_MEMBER,$(c),$(call copy_src_file,$(c)),$(call copy_src_lib,$(c)))$(NL))
215
+ $(SET_LIBL)
216
+ system "crtrpgpgm pgm($(TARGET_LIB)/$(call ibmi_name_sh,$@)) srcfile($(TARGET_LIB)/qrpgsrc) srcmbr($(call ibmi_name_sh,$<)) option(*source) replace(*yes)"
217
+ endef
218
+
219
+ # Build System/38 compatible RPG III program (QSYS38/CRTRPGPGM).
220
+ # QSYS38/CRTRPGPGM has no REPLACE parameter and fails if the program exists, so
221
+ # delete any existing program object first. Also creates /COPY source members.
222
+ define BUILD_RPG38_PGM
223
+ $(call SETUP_LOG,$(notdir $@))
224
+ $(call CREATE_SOURCE_MEMBER,$<,qrpgsrc)
225
+ $(foreach c,$(RPG3_COPY_MEMBERS),$(call CREATE_COPY_MEMBER,$(c),$(call copy_src_file,$(c)),$(call copy_src_lib,$(c)))$(NL))
226
+ $(SET_LIBL)
227
+ if test -e '$(TARGET_LIB_PATH)/$(call ibmi_name,$@).pgm'; then system "dltpgm $(TARGET_LIB)/$(call ibmi_name_sh,$@)"; fi
228
+ system "qsys38/crtrpgpgm pgm($(TARGET_LIB)/$(call ibmi_name_sh,$@)) srcfile($(TARGET_LIB)/qrpgsrc) srcmbr($(call ibmi_name_sh,$<)) option(*source)"
229
+ endef
230
+
184
231
  # Build ILE CL module
185
232
  # tgtccsid(*job) is only supported on IBM i 7.5 and later.
186
233
  define BUILD_CLLE_MODULE
@@ -315,6 +362,35 @@ $(SET_LIBL)
315
362
  system "runsqlstm srcstmf('$(call shell_escape_dollars,$<)') commit(*none) dftrdbcol($(TARGET_LIB))"
316
363
  endef
317
364
 
365
+ # Build SQL trigger program.
366
+ # CREATE TRIGGER creates the *PGM; use PROGRAM NAME in the source when the
367
+ # trigger name should map exactly to the build target object.
368
+ define BUILD_SQLTRIGGER_TO_PGM
369
+ $(call SETUP_LOG,$(notdir $@))
370
+ $(SET_LIBL)
371
+ system "runsqlstm srcstmf('$(call shell_escape_dollars,$<)') commit(*none) dftrdbcol($(TARGET_LIB))"
372
+ endef
373
+
374
+ # Build SQL procedure as a service program.
375
+ # An SQL procedure whose source uses PROGRAM TYPE SUB is backed by a *SRVPGM.
376
+ # codermake only runs the SQL statement; IBM i creates the *SRVPGM and derives
377
+ # its object name from the routine (name it to match the target where practical).
378
+ define BUILD_SQLPROC_TO_SRVPGM
379
+ $(call SETUP_LOG,$(notdir $@))
380
+ $(SET_LIBL)
381
+ system "runsqlstm srcstmf('$(call shell_escape_dollars,$<)') commit(*none) dftrdbcol($(TARGET_LIB))"
382
+ endef
383
+
384
+ # Build SQL UDF (CREATE FUNCTION ... LANGUAGE SQL) as a service program.
385
+ # SQL UDFs are backed by *SRVPGM objects. codermake only runs the SQL statement;
386
+ # IBM i creates the *SRVPGM and derives its object name from the routine (name it
387
+ # to match the target where practical).
388
+ define BUILD_SQLUDF_TO_SRVPGM
389
+ $(call SETUP_LOG,$(notdir $@))
390
+ $(SET_LIBL)
391
+ system "runsqlstm srcstmf('$(call shell_escape_dollars,$<)') commit(*none) dftrdbcol($(TARGET_LIB))"
392
+ endef
393
+
318
394
  # Build message file from CL commands
319
395
  define BUILD_MSGF
320
396
  $(call SETUP_LOG,$(notdir $@))
@@ -79,6 +79,26 @@ EOF
79
79
  cat '$(1)' | $(SSH) "$(QSHELL) -c 'Rfile -Qw \"$(TARGET_LIB)/$(2)($(call remote_shell_escape_dollars,$(call ibmi_name,$(1))))\"'"
80
80
  endef
81
81
 
82
+ ######
83
+ # Utility to upload a source member to an explicitly named library. Used for
84
+ # RPG III /COPY members, whose target library is derived from the prerequisite
85
+ # path (see base.mk) and may differ from the program's own library.
86
+ # $(1) = local file path (source type is derived from file extension)
87
+ # $(2) = source file name (e.g., qcpysrc)
88
+ # $(3) = target IBM i library
89
+ ######
90
+ define CREATE_COPY_MEMBER
91
+ $(SSH) $(QSHELL) <<'EOF'
92
+ if [ ! -e '/qsys.lib/$(3).lib/$(2).file' ]; then
93
+ system "crtsrcpf file($(3)/$(2))"
94
+ fi
95
+ if [ ! -e '/qsys.lib/$(3).lib/$(2).file/$(call ibmi_name,$(1)).mbr' ]; then
96
+ system "addpfm file($(3)/$(2)) mbr($(call ibmi_name_sh,$(1))) srctype($(subst .,,$(suffix $(1))))"
97
+ fi
98
+ EOF
99
+ cat '$(1)' | $(SSH) "$(QSHELL) -c 'Rfile -Qw \"$(3)/$(2)($(call remote_shell_escape_dollars,$(call ibmi_name,$(1))))\"'"
100
+ endef
101
+
82
102
  ######
83
103
  # Utility to build an object via CL commands in a separate file.
84
104
  # $(1) = Target path
@@ -270,6 +290,52 @@ EOF
270
290
  touch '$@'
271
291
  endef
272
292
 
293
+ # Build System/38 compatible OPM CL program (QSYS38/CRTCLPGM).
294
+ # QSYS38/CRTCLPGM has no REPLACE parameter and fails if the program exists, so
295
+ # delete any existing program object first.
296
+ define BUILD_CLP38_PGM
297
+ $(call SETUP_LOG,$(notdir $@))
298
+ $(call CREATE_SOURCE_MEMBER,$<,qclsrc)
299
+ $(SSH) $(QSHELL) <<'EOF'
300
+ $(SET_LIBL)
301
+ if [ -e '$(TARGET_LIB_PATH)/$(call ibmi_name,$@).pgm' ]; then
302
+ system "dltpgm $(TARGET_LIB)/$(call ibmi_name_sh,$@)"
303
+ fi
304
+ system "qsys38/crtclpgm pgm($(TARGET_LIB)/$(call ibmi_name_sh,$@)) srcfile($(TARGET_LIB)/qclsrc) srcmbr($(call ibmi_name_sh,$<)) option(*source)"
305
+ EOF
306
+ touch '$@'
307
+ endef
308
+
309
+ # Build RPG/400 (RPG III) program (CRTRPGPGM). Creates the program source
310
+ # member plus a source member for every /COPY prerequisite before compiling.
311
+ define BUILD_RPG_PGM
312
+ $(call SETUP_LOG,$(notdir $@))
313
+ $(call CREATE_SOURCE_MEMBER,$<,qrpgsrc)
314
+ $(foreach c,$(RPG3_COPY_MEMBERS),$(call CREATE_COPY_MEMBER,$(c),$(call copy_src_file,$(c)),$(call copy_src_lib,$(c)))$(NL))
315
+ $(SSH) $(QSHELL) <<'EOF'
316
+ $(SET_LIBL)
317
+ system "crtrpgpgm pgm($(TARGET_LIB)/$(call ibmi_name_sh,$@)) srcfile($(TARGET_LIB)/qrpgsrc) srcmbr($(call ibmi_name_sh,$<)) option(*source) replace(*yes)"
318
+ EOF
319
+ touch '$@'
320
+ endef
321
+
322
+ # Build System/38 compatible RPG III program (QSYS38/CRTRPGPGM).
323
+ # QSYS38/CRTRPGPGM has no REPLACE parameter and fails if the program exists, so
324
+ # delete any existing program object first. Also creates /COPY source members.
325
+ define BUILD_RPG38_PGM
326
+ $(call SETUP_LOG,$(notdir $@))
327
+ $(call CREATE_SOURCE_MEMBER,$<,qrpgsrc)
328
+ $(foreach c,$(RPG3_COPY_MEMBERS),$(call CREATE_COPY_MEMBER,$(c),$(call copy_src_file,$(c)),$(call copy_src_lib,$(c)))$(NL))
329
+ $(SSH) $(QSHELL) <<'EOF'
330
+ $(SET_LIBL)
331
+ if [ -e '$(TARGET_LIB_PATH)/$(call ibmi_name,$@).pgm' ]; then
332
+ system "dltpgm $(TARGET_LIB)/$(call ibmi_name_sh,$@)"
333
+ fi
334
+ system "qsys38/crtrpgpgm pgm($(TARGET_LIB)/$(call ibmi_name_sh,$@)) srcfile($(TARGET_LIB)/qrpgsrc) srcmbr($(call ibmi_name_sh,$<)) option(*source)"
335
+ EOF
336
+ touch '$@'
337
+ endef
338
+
273
339
  # Build ILE CL module
274
340
  # tgtccsid(*job) is only supported on IBM i 7.5 and later, so detect the
275
341
  # target's release inside the remote shell and gate the parameter on it.
@@ -439,6 +505,35 @@ $(call REMOTE_BUILD,$(filter-out build/%,$^),system "runsqlstm srcstmf('$(call s
439
505
  touch '$@'
440
506
  endef
441
507
 
508
+ # Build SQL trigger program.
509
+ # CREATE TRIGGER creates the *PGM; use PROGRAM NAME in the source when the
510
+ # trigger name should map exactly to the build target object.
511
+ define BUILD_SQLTRIGGER_TO_PGM
512
+ $(call SETUP_LOG,$(notdir $@))
513
+ $(call REMOTE_BUILD,$(filter-out build/%,$^),system "runsqlstm srcstmf('$(call shell_escape_dollars,$<)') commit(*none) dftrdbcol($(TARGET_LIB))")
514
+ touch '$@'
515
+ endef
516
+
517
+ # Build SQL procedure as a service program.
518
+ # An SQL procedure whose source uses PROGRAM TYPE SUB is backed by a *SRVPGM.
519
+ # codermake only runs the SQL statement; IBM i creates the *SRVPGM and derives
520
+ # its object name from the routine (name it to match the target where practical).
521
+ define BUILD_SQLPROC_TO_SRVPGM
522
+ $(call SETUP_LOG,$(notdir $@))
523
+ $(call REMOTE_BUILD,$(filter-out build/%,$^),system "runsqlstm srcstmf('$(call shell_escape_dollars,$<)') commit(*none) dftrdbcol($(TARGET_LIB))")
524
+ touch '$@'
525
+ endef
526
+
527
+ # Build SQL UDF (CREATE FUNCTION ... LANGUAGE SQL) as a service program.
528
+ # SQL UDFs are backed by *SRVPGM objects. codermake only runs the SQL statement;
529
+ # IBM i creates the *SRVPGM and derives its object name from the routine (name it
530
+ # to match the target where practical).
531
+ define BUILD_SQLUDF_TO_SRVPGM
532
+ $(call SETUP_LOG,$(notdir $@))
533
+ $(call REMOTE_BUILD,$(filter-out build/%,$^),system "runsqlstm srcstmf('$(call shell_escape_dollars,$<)') commit(*none) dftrdbcol($(TARGET_LIB))")
534
+ touch '$@'
535
+ endef
536
+
442
537
  # Build message file from CL commands
443
538
  define BUILD_MSGF
444
539
  $(call SETUP_LOG,$(notdir $@))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profoundlogic/codermake",
3
- "version": "2.0.8",
3
+ "version": "2.2.0",
4
4
  "description": "Make wrapper framework for IBM i development that simplifies build rules",
5
5
  "main": "dist/bin/index.js",
6
6
  "type": "module",
@@ -154,7 +154,13 @@ ENDPGMEXP
154
154
  | `.clle` | `.pgm` | Program (*PGM) | `CRTBNDCL` |
155
155
  | `.clle` | `.module` | Module (*MODULE) | `CRTCLMOD` |
156
156
  | `.clp` / `.cl` | `.pgm` | Program (*PGM) | `CRTCLPGM` |
157
+ | `.clp38` | `.pgm` | Program (*PGM) | `QSYS38/CRTCLPGM` (System/38, delete-then-create) |
158
+ | `.rpg` | `.pgm` | Program (*PGM) | `CRTRPGPGM ... REPLACE(*YES)` (RPG/400) |
159
+ | `.rpg38` | `.pgm` | Program (*PGM) | `QSYS38/CRTRPGPGM` (System/38 RPG III, delete-then-create) |
157
160
  | `.proc.sql` | `.pgm` | SQL Procedure (*PGM) | `RUNSQLSTM` |
161
+ | `.proc.sql` | `.srvpgm` | SQL Procedure (*SRVPGM, `PROGRAM TYPE SUB`) | `RUNSQLSTM` |
162
+ | `.udf.sql` | `.srvpgm` | SQL Function (*SRVPGM, `LANGUAGE SQL`) | `RUNSQLSTM` |
163
+ | `.trg.sql` | `.pgm` | SQL Trigger Program (*PGM) | `RUNSQLSTM` |
158
164
  | `.module` (1+) | `.pgm` | Program (*PGM) | `CRTPGM` |
159
165
  | `.module` + `.exports` or `.bnd` | `.srvpgm` | Service Program (*SRVPGM) | `CRTSRVPGM EXPORT(*SRCFILE)` |
160
166
  | `.module` (no exports) | `.srvpgm` | Service Program (*SRVPGM) | `CRTSRVPGM EXPORT(*ALL)` |
@@ -98,7 +98,7 @@ CPD7344 30 Keyword REF not valid for this type of file.
98
98
 
99
99
  DDS errors typically reference a specific record format and line within the source.
100
100
 
101
- ## SQL DDL listings (.table.sql, .index.sql, .view.sql, .proc.sql)
101
+ ## SQL DDL listings (.table.sql, .index.sql, .view.sql, .proc.sql, .udf.sql, .trg.sql)
102
102
 
103
103
  SQL DDL statements executed via `RUNSQLSTM` produce SQL messages:
104
104
 
@@ -110,6 +110,7 @@ SQL7905 10 Module *N in *N not found.
110
110
 
111
111
  - Severity 30+ means the statement failed.
112
112
  - Severity 20 warnings (like "already exists") may or may not be a problem depending on context.
113
+ - `.proc.sql` builds a `*PGM` (or a `*SRVPGM` with `PROGRAM TYPE SUB`), `.udf.sql` builds a `*SRVPGM`, and `.trg.sql` builds a trigger `*PGM`; IBM i creates these objects from the SQL statement, so align the SQL routine/trigger name or trigger `PROGRAM NAME` with the build target.
113
114
 
114
115
  ## Message files and binding directories (.msgf, .bnddir)
115
116
 
@@ -54,9 +54,50 @@ mypgm.pgm: mypgm.clp
54
54
 
55
55
  **CL command:** `CRTCLPGM PGM(LIB/MYPGM) SRCFILE(LIB/QCLSRC)`
56
56
 
57
+ ### System/38 OPM CL program from .clp38
58
+
59
+ System/38 compatible OPM CL. Like `.clp`, it compiles from a source member (`QCLSRC`).
60
+ `QSYS38/CRTCLPGM` has no `REPLACE` parameter, so the recipe deletes any existing
61
+ program object first.
62
+
63
+ ```makefile
64
+ mycl38.pgm: mycl38.clp38
65
+ ```
66
+
67
+ **CL command:** `QSYS38/CRTCLPGM PGM(LIB/MYCL38) SRCFILE(LIB/QCLSRC) SRCMBR(MYCL38) OPTION(*SOURCE)`
68
+
69
+ ### RPG/400 (RPG III) program from .rpg
70
+
71
+ RPG III cannot compile from stream files, so the source is staged as a member in
72
+ `QRPGSRC` first, then compiled with `CRTRPGPGM`. `/COPY` directives always
73
+ reference source members; list each `/COPY` target as a prerequisite so codermake
74
+ creates it as a source member too (in the source file named by the prereq's parent
75
+ directory, in the program's library — or, in multi-library output mode, the library
76
+ mapped from the prereq's leading library-directory segment). RPG III has no
77
+ `/INCLUDE` directive and defaults the source file to `QRPGSRC` when unqualified.
78
+
79
+ ```makefile
80
+ myrpg.pgm: myrpg.rpg
81
+ mycpy.pgm: mycpy.rpg qcpysrc/shared.rpg # /COPY QCPYSRC,SHARED staged as QCPYSRC/SHARED
82
+ ```
83
+
84
+ **CL command:** `CRTRPGPGM PGM(LIB/MYRPG) SRCFILE(LIB/QRPGSRC) SRCMBR(MYRPG) OPTION(*SOURCE) REPLACE(*YES)`
85
+
86
+ ### System/38 RPG III program from .rpg38
87
+
88
+ Like `.rpg`, but compiled with `QSYS38/CRTRPGPGM` and the staged member is tagged
89
+ `RPG38`. `QSYS38/CRTRPGPGM` has no `REPLACE` parameter, so the recipe deletes any
90
+ existing program object first. `/COPY` members are handled the same way as `.rpg`.
91
+
92
+ ```makefile
93
+ myrpg38.pgm: myrpg38.rpg38
94
+ ```
95
+
96
+ **CL command:** `QSYS38/CRTRPGPGM PGM(LIB/MYRPG38) SRCFILE(LIB/QRPGSRC) SRCMBR(MYRPG38) OPTION(*SOURCE)`
97
+
57
98
  ### SQL procedure from .proc.sql
58
99
 
59
- Runs a SQL DDL script that creates a stored procedure. The resulting object appears as a program.
100
+ Runs a SQL DDL script that creates a stored procedure. With the default `PROGRAM TYPE MAIN`, the resulting object is a program (`*PGM`).
60
101
 
61
102
  ```makefile
62
103
  getcount.pgm: getcount.proc.sql
@@ -64,6 +105,20 @@ getcount.pgm: getcount.proc.sql
64
105
 
65
106
  **CL command:** `RUNSQLSTM SRCSTMF('src/getcount.proc.sql') COMMIT(*NONE) DFTRDBCOL(LIB)`
66
107
 
108
+ A `.proc.sql` whose routine uses `PROGRAM TYPE SUB`, and a `.udf.sql` SQL function, are backed by `*SRVPGM` objects instead — see [SQL service programs](#sql-service-programs-from-procsql--udfsql) under Service programs.
109
+
110
+ ### SQL trigger program from .trg.sql
111
+
112
+ Runs a SQL DDL script that creates a trigger. IBM i creates the generated trigger program object (`*PGM`) when `CREATE TRIGGER` runs.
113
+
114
+ ```makefile
115
+ emptrg.pgm: emptrg.trg.sql employee.file empaudit.file
116
+ ```
117
+
118
+ **CL command:** `RUNSQLSTM SRCSTMF('src/emptrg.trg.sql') COMMIT(*NONE) DFTRDBCOL(LIB)`
119
+
120
+ Use the trigger name or `PROGRAM NAME` in the source so the generated program object matches the `.pgm` build target.
121
+
67
122
  ### Program from modules
68
123
 
69
124
  Links one or more compiled modules into a program. Prerequisites include `.module` targets, and optionally `.srvpgm` and `.bnddir` (normal or order-only) for automatic binding.
@@ -148,6 +203,22 @@ mysrvpgm.srvpgm: mymod.module mysrvpgm.exports dep.srvpgm
148
203
 
149
204
  This appends `BNDSRVPGM(DEP)` to the CRTSRVPGM command. `.bnddir` prerequisites (normal or order-only) append `BNDDIR(name)`.
150
205
 
206
+ ### SQL service programs from .proc.sql / .udf.sql
207
+
208
+ A service program can also be created from SQL source via `RUNSQLSTM`, with no modules or export list:
209
+
210
+ - **`.proc.sql` → `.srvpgm`** — `CREATE PROCEDURE ... LANGUAGE SQL PROGRAM TYPE SUB` is backed by a `*SRVPGM`.
211
+ - **`.udf.sql` → `.srvpgm`** — `CREATE FUNCTION ... LANGUAGE SQL` (SQL UDF) is backed by a `*SRVPGM`.
212
+
213
+ ```makefile
214
+ getcounts.srvpgm: getcounts.proc.sql employee.file # PROGRAM TYPE SUB
215
+ getname.srvpgm: getname.udf.sql employee.file # SQL UDF
216
+ ```
217
+
218
+ **CL command:** `RUNSQLSTM SRCSTMF('src/getcounts.proc.sql') COMMIT(*NONE) DFTRDBCOL(LIB)`
219
+
220
+ codermake only runs the SQL statement; IBM i creates the `*SRVPGM` and derives its object name from the SQL routine. Name the routine (and its `SPECIFIC` name where applicable) to match the build target so the generated object name lines up with the rule.
221
+
151
222
  ### .exports / .bnd file format
152
223
 
153
224
  The exports file (using either `.exports` or `.bnd` extension) is a plain text file with the following structure: