@profoundlogic/codermake 1.1.0 → 1.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.
@@ -1 +1 @@
1
- function _0x250f(_0x247c5e,_0x320131){_0x247c5e=_0x247c5e-0xe4;const _0x449fc6=_0x449f();let _0x250f9a=_0x449fc6[_0x247c5e];if(_0x250f['QDoYzL']===undefined){var _0x44fee5=function(_0x575a72){const _0x5cdbfd='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x16cdea='',_0x43f4c3='';for(let _0x5df22b=0x0,_0x448fbe,_0x44e523,_0x315d5b=0x0;_0x44e523=_0x575a72['charAt'](_0x315d5b++);~_0x44e523&&(_0x448fbe=_0x5df22b%0x4?_0x448fbe*0x40+_0x44e523:_0x44e523,_0x5df22b++%0x4)?_0x16cdea+=String['fromCharCode'](0xff&_0x448fbe>>(-0x2*_0x5df22b&0x6)):0x0){_0x44e523=_0x5cdbfd['indexOf'](_0x44e523);}for(let _0x8b200c=0x0,_0xd73275=_0x16cdea['length'];_0x8b200c<_0xd73275;_0x8b200c++){_0x43f4c3+='%'+('00'+_0x16cdea['charCodeAt'](_0x8b200c)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x43f4c3);};_0x250f['PHOvrr']=_0x44fee5,_0x250f['zPzjui']={},_0x250f['QDoYzL']=!![];}const _0x3d236c=_0x449fc6[0x0],_0x30db4f=_0x247c5e+_0x3d236c,_0x733f57=_0x250f['zPzjui'][_0x30db4f];return!_0x733f57?(_0x250f9a=_0x250f['PHOvrr'](_0x250f9a),_0x250f['zPzjui'][_0x30db4f]=_0x250f9a):_0x250f9a=_0x733f57,_0x250f9a;}(function(_0x3dd7e1,_0x18472d){const _0x5808b9=_0x250f,_0x585616=_0x3dd7e1();while(!![]){try{const _0x36bca5=parseInt(_0x5808b9(0xe5))/0x1+parseInt(_0x5808b9(0xfb))/0x2+parseInt(_0x5808b9(0xf0))/0x3*(parseInt(_0x5808b9(0xf4))/0x4)+-parseInt(_0x5808b9(0xeb))/0x5*(-parseInt(_0x5808b9(0xf6))/0x6)+-parseInt(_0x5808b9(0xf9))/0x7+-parseInt(_0x5808b9(0xea))/0x8+-parseInt(_0x5808b9(0xf8))/0x9;if(_0x36bca5===_0x18472d)break;else _0x585616['push'](_0x585616['shift']());}catch(_0x378307){_0x585616['push'](_0x585616['shift']());}}}(_0x449f,0xececf));import{writeFileSync,mkdirSync,existsSync}from'fs';import{join}from'path';import{randomUUID}from'crypto';import{tmpdir}from'os';function ensureDir(_0x164847){const _0x388468=_0x250f,_0x5a3e97={'LYVCO':function(_0x15b996,_0x5388ff){return _0x15b996(_0x5388ff);}};if(!_0x5a3e97[_0x388468(0xfa)](existsSync,_0x164847)){const _0x4533e4={};_0x4533e4[_0x388468(0xf7)]=!![],mkdirSync(_0x164847,_0x4533e4);}}function _0x449f(){const _0x4bc290=['nZi4mdq4ohf4rKjzqW','mtu4nZbkv3DfqMm','vNjyz0q','EwTfCgu','EgzVsui','vefsr0vuuYa6psa','nta1mtCZrgHbELDr','C3rYAw5NAwz5','sLD2DMS','AM9PBG','mJHxBNjVqwW','DgfYz2v0C0zPBgu','mJC0ofLhwKLdEq','CMvJDxjZAxzL','mJaWmZm4nZr3vNbMDxK','mti2odyWntHbyMjAwva','tfLwq08','mJK0mtu2nfr6u1n1wa','zvDYwvC','C1fJtw4','CMvWBgfJzq','mtGXntu3n3veyMPzsq','BwfWCgLUz0zPBgu','Dg1WrgLY','DxrMoa','DgfYz2v0CY5TAW'];_0x449f=function(){return _0x4bc290;};return _0x449f();}export function writeRules(_0x676a1,_0x4b0b86,_0x89c7e5={},_0xe3d51e=null){const _0x5071d4=_0x250f,_0x405a73={'ykEpe':function(_0x139c2f){return _0x139c2f();},'VrXgD':function(_0x113415){return _0x113415();},'JWvvk':function(_0x1a15b7,_0x5cafc6){return _0x1a15b7(_0x5cafc6);},'xfoIB':function(_0x28909f,_0x294084){return _0x28909f+_0x294084;},'sQcMn':function(_0x4d1676,_0x1bd0a2,_0x2d5db1,_0x4eaca1){return _0x4d1676(_0x1bd0a2,_0x2d5db1,_0x4eaca1);},'eWrYW':_0x5071d4(0xe8)};if(!_0xe3d51e){const _0x37d2e7=_0x405a73[_0x5071d4(0xed)](randomUUID)[_0x5071d4(0xe4)](/-/g,'');_0xe3d51e=join(_0x405a73[_0x5071d4(0xec)](tmpdir),'cm-'+_0x37d2e7);}_0x405a73[_0x5071d4(0xf2)](ensureDir,_0xe3d51e);const _0x3dcb51=join(_0xe3d51e,'rules.mk'),_0x22a124=join(_0xe3d51e,_0x5071d4(0xe9)),_0x338ab2=join(_0xe3d51e,'target-mapping.json'),_0x57abbf=_0x405a73[_0x5071d4(0xee)](_0x676a1[_0x5071d4(0xf3)]('\x0a'),'\x0a');_0x405a73[_0x5071d4(0xfd)](writeFileSync,_0x3dcb51,_0x57abbf,_0x405a73['eWrYW']);const _0x500fc6=_0x5071d4(0xef)+_0x4b0b86[_0x5071d4(0xf3)]('\x20')+'\x0a';_0x405a73[_0x5071d4(0xfd)](writeFileSync,_0x22a124,_0x500fc6,_0x405a73[_0x5071d4(0xfc)]);const _0x5d2612=JSON[_0x5071d4(0xf1)](_0x89c7e5,null,0x2);_0x405a73[_0x5071d4(0xfd)](writeFileSync,_0x338ab2,_0x5d2612,_0x405a73['eWrYW']);const _0x2a422f={};return _0x2a422f['rulesFile']=_0x3dcb51,_0x2a422f[_0x5071d4(0xf5)]=_0x22a124,_0x2a422f[_0x5071d4(0xe6)]=_0x338ab2,_0x2a422f[_0x5071d4(0xe7)]=_0xe3d51e,_0x2a422f;}
1
+ function _0x5bc5(){const _0x2ed8ca=['DxrMoa','CNvSzxmUBwS','mwrhtLbOqq','DgfYz2v0lw1HChbPBMCUANnVBG','CMvWBgfJzq','ota2r0LPDxvb','sNj3DNe','B05nBfG','B1ztvvu','Cg5bDvO','vefsr0vuuYa6psa','mtG1otu0mgPvzgLbva','ndq3nJG4mfLLu3rTsW','mtG4otn2AgrNswW','BwfWCgLUz0zPBgu','AM9PBG','nZy4nJuWB1nVEKPL','CNvSzxngAwXL','ntC0odGXuxnkAKrs','mZeXmZm0CM9ZzKjp','Dg1WrgLY','CMXzu2O','CLzbwNK','ENzivvq','DgfYz2v0CY5TAW','mtq1nZCWnJzRAM1Kyva','CMvJDxjZAxzL','C3rYAw5NAwz5','DgfYz2v0C0zPBgu'];_0x5bc5=function(){return _0x2ed8ca;};return _0x5bc5();}(function(_0x2f9a22,_0x4a9238){const _0xfc7212=_0x3ff9,_0x31f554=_0x2f9a22();while(!![]){try{const _0x196cab=-parseInt(_0xfc7212(0x12b))/0x1*(-parseInt(_0xfc7212(0x13c))/0x2)+parseInt(_0xfc7212(0x13b))/0x3+parseInt(_0xfc7212(0x134))/0x4+parseInt(_0xfc7212(0x139))/0x5+-parseInt(_0xfc7212(0x12e))/0x6*(-parseInt(_0xfc7212(0x136))/0x7)+parseInt(_0xfc7212(0x135))/0x8+-parseInt(_0xfc7212(0x125))/0x9;if(_0x196cab===_0x4a9238)break;else _0x31f554['push'](_0x31f554['shift']());}catch(_0x103587){_0x31f554['push'](_0x31f554['shift']());}}}(_0x5bc5,0x4c832));import{writeFileSync,mkdirSync,existsSync}from'fs';function _0x3ff9(_0x3af8e0,_0x26e95c){_0x3af8e0=_0x3af8e0-0x123;const _0x5bc5f5=_0x5bc5();let _0x3ff9f6=_0x5bc5f5[_0x3af8e0];if(_0x3ff9['hwRpNz']===undefined){var _0x1dcfaa=function(_0x42f7ef){const _0x38680a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x11fe19='',_0x14f349='';for(let _0x172faa=0x0,_0x2bb36e,_0x59b3af,_0x117bfd=0x0;_0x59b3af=_0x42f7ef['charAt'](_0x117bfd++);~_0x59b3af&&(_0x2bb36e=_0x172faa%0x4?_0x2bb36e*0x40+_0x59b3af:_0x59b3af,_0x172faa++%0x4)?_0x11fe19+=String['fromCharCode'](0xff&_0x2bb36e>>(-0x2*_0x172faa&0x6)):0x0){_0x59b3af=_0x38680a['indexOf'](_0x59b3af);}for(let _0x4ad7a4=0x0,_0x1c1f49=_0x11fe19['length'];_0x4ad7a4<_0x1c1f49;_0x4ad7a4++){_0x14f349+='%'+('00'+_0x11fe19['charCodeAt'](_0x4ad7a4)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x14f349);};_0x3ff9['bFryPL']=_0x1dcfaa,_0x3ff9['BCJVFQ']={},_0x3ff9['hwRpNz']=!![];}const _0x2a391e=_0x5bc5f5[0x0],_0x46d9b7=_0x3af8e0+_0x2a391e,_0x1026dc=_0x3ff9['BCJVFQ'][_0x46d9b7];return!_0x1026dc?(_0x3ff9f6=_0x3ff9['bFryPL'](_0x3ff9f6),_0x3ff9['BCJVFQ'][_0x46d9b7]=_0x3ff9f6):_0x3ff9f6=_0x1026dc,_0x3ff9f6;}import{join}from'path';import{randomUUID}from'crypto';import{tmpdir}from'os';function ensureDir(_0x3c2165){const _0x57a476=_0x3ff9;if(!existsSync(_0x3c2165)){const _0x4d121c={};_0x4d121c[_0x57a476(0x126)]=!![],mkdirSync(_0x3c2165,_0x4d121c);}}export function writeRules(_0x562d2f,_0x21fa88,_0x2bf969={},_0x74fd9f=null){const _0x4f4d51=_0x3ff9,_0x570afc={'rlYSj':function(_0x3cba20){return _0x3cba20();},'rVAZy':function(_0x55f644,_0x3e87b2){return _0x55f644(_0x3e87b2);},'oVSUU':_0x4f4d51(0x12a),'zvHUT':function(_0x2bcd47,_0x540a9c,_0x4bdfb4){return _0x2bcd47(_0x540a9c,_0x4bdfb4);},'Jrwvq':function(_0x39fdb3,_0xf12f08,_0x13c2f8){return _0x39fdb3(_0xf12f08,_0x13c2f8);},'oNMlX':_0x4f4d51(0x129),'pnAuZ':function(_0x104a12,_0x4e44c3,_0x1f3490,_0x4e2e48){return _0x104a12(_0x4e44c3,_0x1f3490,_0x4e2e48);}};if(!_0x74fd9f){const _0x311ad5=randomUUID()[_0x4f4d51(0x12d)](/-/g,'');_0x74fd9f=join(_0x570afc[_0x4f4d51(0x13e)](tmpdir),'cm-'+_0x311ad5);}_0x570afc[_0x4f4d51(0x13f)](ensureDir,_0x74fd9f);const _0x574a1d=join(_0x74fd9f,_0x570afc[_0x4f4d51(0x131)]),_0x147ec0=_0x570afc[_0x4f4d51(0x123)](join,_0x74fd9f,_0x4f4d51(0x124)),_0x55fca2=_0x570afc[_0x4f4d51(0x12f)](join,_0x74fd9f,_0x4f4d51(0x12c)),_0x160a9f=_0x562d2f[_0x4f4d51(0x138)]('\x0a')+'\x0a';writeFileSync(_0x574a1d,_0x160a9f,_0x570afc[_0x4f4d51(0x130)]);const _0x495c0b=_0x4f4d51(0x133)+_0x21fa88[_0x4f4d51(0x138)]('\x20')+'\x0a';writeFileSync(_0x147ec0,_0x495c0b,_0x4f4d51(0x129));const _0x522a3b=JSON[_0x4f4d51(0x127)](_0x2bf969,null,0x2);_0x570afc[_0x4f4d51(0x132)](writeFileSync,_0x55fca2,_0x522a3b,_0x570afc[_0x4f4d51(0x130)]);const _0x1e0d7a={};return _0x1e0d7a[_0x4f4d51(0x13a)]=_0x574a1d,_0x1e0d7a[_0x4f4d51(0x128)]=_0x147ec0,_0x1e0d7a[_0x4f4d51(0x137)]=_0x55fca2,_0x1e0d7a[_0x4f4d51(0x13d)]=_0x74fd9f,_0x1e0d7a;}
@@ -179,6 +179,35 @@ $(SET_LIBL)
179
179
  system "crtlf file($(LIBRARY)/$(basename $(@F))) srcfile($(LIBRARY)/qddssrc)"
180
180
  endef
181
181
 
182
+ # Build printer file
183
+ define BUILD_PRTF_TO_FILE
184
+ $(call SETUP_LOG,$(notdir $@))
185
+ $(call CREATE_SOURCE_MEMBER,$<,qddssrc)
186
+ $(SET_LIBL)
187
+ system "crtprtf file($(LIBRARY)/$(basename $(@F))) srcfile($(LIBRARY)/qddssrc)"
188
+ endef
189
+
190
+ # Build SQL table
191
+ define BUILD_SQLTABLE_TO_FILE
192
+ $(call SETUP_LOG,$(notdir $@))
193
+ $(SET_LIBL)
194
+ system "runsqlstm srcstmf('$<') commit(*none) dftrdbcol($(LIBRARY))"
195
+ endef
196
+
197
+ # Build SQL index
198
+ define BUILD_SQLINDEX_TO_FILE
199
+ $(call SETUP_LOG,$(notdir $@))
200
+ $(SET_LIBL)
201
+ system "runsqlstm srcstmf('$<') commit(*none) dftrdbcol($(LIBRARY))"
202
+ endef
203
+
204
+ # Build SQL procedure
205
+ define BUILD_SQLPROC_TO_PGM
206
+ $(call SETUP_LOG,$(notdir $@))
207
+ $(SET_LIBL)
208
+ system "runsqlstm srcstmf('$<') commit(*none) dftrdbcol($(LIBRARY))"
209
+ endef
210
+
182
211
  # Build message file from CL commands
183
212
  define BUILD_MSGF
184
213
  $(call SETUP_LOG,$(notdir $@))
@@ -204,7 +233,13 @@ endef
204
233
  .PHONY: platform-clean
205
234
  platform-clean:
206
235
  @if [ -n "$(TARGETS)" ] && [ -d $(LIBRARY_PATH) ]; then
207
- for target in $(TARGETS); do
208
- rm -rf "$$target"
236
+ for pass in 1 2; do
237
+ for target in $(TARGETS); do
238
+ if [ "$${target%.file}" != "$$target" ]; then
239
+ (system "dltf $(LIBRARY)/$$(basename $$target .file)" > /dev/null 2>&1) || true
240
+ else
241
+ rm -rf "$$target"
242
+ fi
243
+ done
209
244
  done
210
245
  fi
@@ -271,6 +271,38 @@ EOF
271
271
  touch '$@'
272
272
  endef
273
273
 
274
+ # Build printer file
275
+ define BUILD_PRTF_TO_FILE
276
+ $(call SETUP_LOG,$(notdir $@))
277
+ $(call CREATE_SOURCE_MEMBER,$<,qddssrc)
278
+ $(SSH) $(QSHELL) <<'EOF'
279
+ $(SET_LIBL)
280
+ system "crtprtf file($(LIBRARY)/$(basename $(@F))) srcfile($(LIBRARY)/qddssrc)"
281
+ EOF
282
+ touch '$@'
283
+ endef
284
+
285
+ # Build SQL table
286
+ define BUILD_SQLTABLE_TO_FILE
287
+ $(call SETUP_LOG,$(notdir $@))
288
+ $(call REMOTE_BUILD,$(filter-out build/%,$^),system "runsqlstm srcstmf('$<') commit(*none) dftrdbcol($(LIBRARY))")
289
+ touch '$@'
290
+ endef
291
+
292
+ # Build SQL index
293
+ define BUILD_SQLINDEX_TO_FILE
294
+ $(call SETUP_LOG,$(notdir $@))
295
+ $(call REMOTE_BUILD,$(filter-out build/%,$^),system "runsqlstm srcstmf('$<') commit(*none) dftrdbcol($(LIBRARY))")
296
+ touch '$@'
297
+ endef
298
+
299
+ # Build SQL procedure
300
+ define BUILD_SQLPROC_TO_PGM
301
+ $(call SETUP_LOG,$(notdir $@))
302
+ $(call REMOTE_BUILD,$(filter-out build/%,$^),system "runsqlstm srcstmf('$<') commit(*none) dftrdbcol($(LIBRARY))")
303
+ touch '$@'
304
+ endef
305
+
274
306
  # Build message file from CL commands
275
307
  define BUILD_MSGF
276
308
  $(call SETUP_LOG,$(notdir $@))
@@ -307,8 +339,14 @@ platform-clean:
307
339
  if [ -n "$$CLEAN_TARGETS" ]; then
308
340
  $(SSH) $(QSHELL) <<EOF
309
341
  if [ -d $(LIBRARY_PATH) ]; then
310
- for target in $$CLEAN_TARGETS; do
311
- rm -rf "$(LIBRARY_PATH)/\$$target"
342
+ for pass in 1 2; do
343
+ for target in $$CLEAN_TARGETS; do
344
+ if [ "\$${target%.file}" != "\$$target" ]; then
345
+ system "dltf $(LIBRARY)/\$${target%.file}" > /dev/null 2>&1 || true
346
+ else
347
+ rm -rf "$(LIBRARY_PATH)/\$$target"
348
+ fi
349
+ done
312
350
  done
313
351
  fi
314
352
  EOF
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profoundlogic/codermake",
3
- "version": "1.1.0",
3
+ "version": "1.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",
@@ -37,6 +37,7 @@
37
37
  "dist/bin/",
38
38
  "dist/lib/",
39
39
  "dist/makefiles/",
40
+ "skills/",
40
41
  "README.md",
41
42
  "LICENSE.txt"
42
43
  ]
@@ -0,0 +1,201 @@
1
+ ---
2
+ name: codermake
3
+ description: Build IBM i objects from source code.
4
+ ---
5
+
6
+ # codermake
7
+
8
+ codermake is a Make-based build tool for IBM i projects. It compiles RPG, CL, DDS, and SQL source into IBM i objects (programs, modules, service programs, files, menus, message files, binding directories) either locally on IBM i or remotely via SSH.
9
+
10
+ ## Key constraints
11
+
12
+ - **Never modify Makefiles.** codermake auto-generates Makefiles from `Rules.mk` files. Only edit `Rules.mk`.
13
+ - **Never modify environment variables or `.env` files** unless the user explicitly asks. Build configuration belongs to the user.
14
+ - **Source names and target names do not need to match.** The preprocessor infers the correct recipe from file extensions alone.
15
+
16
+ ## Building
17
+
18
+ Run codermake from the project root:
19
+
20
+ ```bash
21
+ # Build everything
22
+ codermake
23
+
24
+ # Build a single target
25
+ codermake <target> # e.g. codermake mypgm.pgm
26
+
27
+ # Dry run (show what would build, without building)
28
+ codermake -n
29
+
30
+ # Clean all build artifacts
31
+ codermake clean
32
+
33
+ # Show the generated Makefile rules (useful for debugging)
34
+ codermake --print-rules
35
+ ```
36
+
37
+ Build output for each target is logged to `tmp/logs/<target>.log`.
38
+
39
+ ## Rules.mk syntax
40
+
41
+ Each source directory contains a `Rules.mk` file that declares build targets and their prerequisites. codermake automatically adds path prefixes (`src/`, `build/`, etc.) based on file extensions -- you write only bare filenames.
42
+
43
+ ### Basic rules
44
+
45
+ ```makefile
46
+ # program from RPG source
47
+ mypgm.pgm: mypgm.rpgle
48
+
49
+ # program from RPG source, depends on a display file
50
+ mypgm.pgm: mypgm.rpgle myscreen.file
51
+
52
+ # display file from DDS
53
+ myscreen.file: myscreen.dspf
54
+
55
+ # physical file from DDS
56
+ custdata.file: custdata.pf
57
+
58
+ # ILE CL program
59
+ setup.pgm: setup.clle
60
+ ```
61
+
62
+ ### Order-only prerequisites
63
+
64
+ Use `|` for objects that must exist before building the target but should not trigger a rebuild when they change. This is typical for binding directories and database files.
65
+
66
+ ```makefile
67
+ mypgm.pgm: mypgm.rpgle mysrvpgm.srvpgm | mybnddir.bnddir mytable.file
68
+ ```
69
+
70
+ ### Cross-directory references
71
+
72
+ Files with a path separator are treated as relative to the project root (not the Rules.mk directory):
73
+
74
+ ```makefile
75
+ # In app/Rules.mk -- reference an exports file in the common/ directory
76
+ mysrvpgm.srvpgm: mymod.module common/api.exports
77
+ ```
78
+
79
+ ### Message files and binding directories (dual-purpose pattern)
80
+
81
+ The `.msgf` and `.bnddir` extensions serve double duty -- as source when they are the first prerequisite of a matching target type, and as built objects everywhere else:
82
+
83
+ ```makefile
84
+ # Build a message file (source file -> object)
85
+ appmsg.msgf: appmsg.msgf
86
+
87
+ # Build a binding directory (source file -> object)
88
+ mybnddir.bnddir: mybnddir.bnddir
89
+
90
+ # Use them as dependencies (treated as built objects)
91
+ mymenu.menu: mymenu.file appmsg.msgf
92
+ setup.pgm: setup.rpgle | mybnddir.bnddir
93
+ ```
94
+
95
+ The `.msgf` source file contains CL commands (`CRTMSGF`, `ADDMSGD`, etc.). The `.bnddir` source file contains CL commands (`CRTBNDDIR`, `ADDBNDDIRE`, etc.).
96
+
97
+ ### Modules and service programs
98
+
99
+ ```makefile
100
+ # Compile source to a module
101
+ mymod.module: mymod.rpgle
102
+
103
+ # Link modules into a program
104
+ mypgm.pgm: mod1.module mod2.module
105
+
106
+ # Create a service program from modules + export list
107
+ mysrvpgm.srvpgm: mymod.module mymod.exports
108
+ ```
109
+
110
+ The `.exports` file is a text file listing exported procedure symbols:
111
+
112
+ ```
113
+ STRPGMEXP PGMLVL(*CURRENT) SIGNATURE(*GEN)
114
+ EXPORT SYMBOL("myProcedure")
115
+ EXPORT SYMBOL("anotherProc")
116
+ ENDPGMEXP
117
+ ```
118
+
119
+ ## Quick reference: source-to-object mapping
120
+
121
+ | Source extension | Target extension | IBM i object | CL command |
122
+ |---|---|---|---|
123
+ | `.rpgle` | `.pgm` | Program (*PGM) | `CRTBNDRPG` |
124
+ | `.rpgle` | `.module` | Module (*MODULE) | `CRTRPGMOD` |
125
+ | `.sqlrpgle` | `.pgm` | Program (*PGM) | `CRTSQLRPGI OBJTYPE(*PGM)` |
126
+ | `.sqlrpgle` | `.module` | Module (*MODULE) | `CRTSQLRPGI OBJTYPE(*MODULE)` |
127
+ | `.clle` | `.pgm` | Program (*PGM) | `CRTBNDCL` |
128
+ | `.clle` | `.module` | Module (*MODULE) | `CRTCLMOD` |
129
+ | `.clp` / `.cl` | `.pgm` | Program (*PGM) | `CRTCLPGM` |
130
+ | `.proc.sql` | `.pgm` | SQL Procedure (*PGM) | `RUNSQLSTM` |
131
+ | `.module` (1+) | `.pgm` | Program (*PGM) | `CRTPGM` |
132
+ | `.module` + `.exports` | `.srvpgm` | Service Program (*SRVPGM) | `CRTSRVPGM` |
133
+ | `.dspf` | `.file` | Display File (*FILE) | `CRTDSPF` |
134
+ | `.json` (RDF) | `.file` | Display File (*FILE) | `CRTDSPF` |
135
+ | `.pf` | `.file` | Physical File (*FILE) | `CRTPF` |
136
+ | `.lf` | `.file` | Logical File (*FILE) | `CRTLF` |
137
+ | `.prtf` | `.file` | Printer File (*FILE) | `CRTPRTF` |
138
+ | `.table.sql` | `.file` | SQL Table (*FILE) | `RUNSQLSTM` |
139
+ | `.index.sql` | `.file` | SQL Index (*FILE) | `RUNSQLSTM` |
140
+ | `.file` + `.msgf` | `.menu` | Menu (*MENU) | `CRTMNU` |
141
+ | `.msgf` (CL src) | `.msgf` | Message File (*MSGF) | `CRTMSGF` / `ADDMSGD` |
142
+ | `.bnddir` (CL src) | `.bnddir` | Binding Dir (*BNDDIR) | `CRTBNDDIR` / `ADDBNDDIRE` |
143
+
144
+ For full details on every type, see [references/file-types.md](references/file-types.md).
145
+
146
+ ## Adding a new target
147
+
148
+ Follow this procedure when adding a new object to the build:
149
+
150
+ 1. **Create the source file** in the appropriate source directory (e.g., `src/newpgm.rpgle`).
151
+ 2. **Add a rule to `Rules.mk`** in that directory:
152
+ ```makefile
153
+ newpgm.pgm: newpgm.rpgle
154
+ ```
155
+ 3. **Declare dependencies** on any objects that must exist first:
156
+ ```makefile
157
+ newpgm.pgm: newpgm.rpgle myscreen.file mysrvpgm.srvpgm | mybnddir.bnddir
158
+ ```
159
+ 4. **Build and verify:**
160
+ ```bash
161
+ codermake newpgm.pgm
162
+ ```
163
+ 5. **Check logs on failure:** `tmp/logs/newpgm.pgm.log`
164
+
165
+ If the target is a module destined for a service program or multi-module program, also add the downstream rule:
166
+
167
+ ```makefile
168
+ newmod.module: newmod.rpgle
169
+ existing.srvpgm: existing_mod.module newmod.module existing.exports
170
+ ```
171
+
172
+ ## Troubleshooting
173
+
174
+ Build logs are in `tmp/logs/<target>.log`. When a build fails:
175
+
176
+ 1. Open the log file for the failing target.
177
+ 2. Search for error message IDs (e.g., `RNF`, `SQL`, `CPF`, `CPD`).
178
+ 3. For RPG/SQL RPG, look at the message summary near the end of the listing -- severity 30+ messages are errors.
179
+ 4. For DDS/CL, look for `CPF` or `CPD` message IDs in the output.
180
+ 5. Use `codermake --print-rules` to verify the generated Makefile if the target is not being built at all.
181
+
182
+ For detailed guidance on reading compile listings, see [references/compile-listings.md](references/compile-listings.md).
183
+
184
+ ## Environment variables
185
+
186
+ codermake reads its configuration from environment variables (typically set in a `.env` file at the project root).
187
+
188
+ ### Remote builds (from Linux/macOS to IBM i via SSH)
189
+
190
+ | Variable | Description |
191
+ |---|---|
192
+ | `IBMI_BUILD_LIBRARY` | Target IBM i library for compiled objects |
193
+ | `IBMI_HOST` | IBM i hostname or IP address |
194
+ | `IBMI_USER` | SSH username on the IBM i |
195
+ | `IBMI_KEY` | Path to SSH private key (optional) |
196
+
197
+ ### Local builds (on IBM i PASE)
198
+
199
+ | Variable | Description |
200
+ |---|---|
201
+ | `BUILD_LIBRARY` | Target IBM i library for compiled objects |
@@ -0,0 +1,141 @@
1
+ # Compile Listings Reference
2
+
3
+ Guide to finding and interpreting IBM i compile listings produced by codermake builds.
4
+
5
+ ## Where to find logs
6
+
7
+ Every build target produces a log file at:
8
+
9
+ ```
10
+ tmp/logs/<target>.log
11
+ ```
12
+
13
+ For example, building `mypgm.pgm` writes to `tmp/logs/mypgm.pgm.log`.
14
+
15
+ ## RPG listings (.rpgle)
16
+
17
+ RPG compile listings from `CRTBNDRPG` or `CRTRPGMOD` follow a standard structure:
18
+
19
+ 1. **Header** -- compiler version, source file path, compile options
20
+ 2. **Source listing** -- numbered source lines (may include copy members)
21
+ 3. **Additional diagnostics** -- cross-reference tables, data structure layouts
22
+ 4. **Message summary** -- all diagnostic messages grouped by severity
23
+
24
+ ### Reading the message summary
25
+
26
+ The message summary appears near the end of the listing. Each entry shows:
27
+
28
+ ```
29
+ MSG ID SEV LINE TEXT
30
+ RNF7031 00 12 The name or indicator is not referenced.
31
+ RNF7066 00 45 A semicolon is expected ...
32
+ RNF5377 30 78 The type of expression does not match ...
33
+ ```
34
+
35
+ **Severity levels:**
36
+
37
+ | Severity | Meaning | Action |
38
+ |---|---|---|
39
+ | 00 | Informational | Safe to ignore |
40
+ | 10 | Warning | Review but usually benign |
41
+ | 20 | Error (recoverable) | Compiler attempted to continue; fix recommended |
42
+ | 30 | Severe error | Compilation failed; must fix |
43
+ | 40+ | Unrecoverable | Compilation failed; must fix |
44
+
45
+ Search for severity 30+ messages to find the root cause of a build failure. The `LINE` column tells you which source line triggered the error.
46
+
47
+ ### Common RPG message IDs
48
+
49
+ | ID prefix | Area |
50
+ |---|---|
51
+ | `RNF` | RPG compiler messages |
52
+ | `RNS` | RPG compiler (structured) |
53
+ | `SQL` | Embedded SQL messages (in SQLRPGLE) |
54
+
55
+ ## SQL RPG listings (.sqlrpgle)
56
+
57
+ SQL RPG compilation is a two-phase process:
58
+
59
+ 1. **SQL precompile** (`CRTSQLRPGI`) -- translates embedded SQL into RPG call statements
60
+ 2. **RPG compile** -- compiles the resulting RPG source
61
+
62
+ The log contains output from both phases. When debugging:
63
+
64
+ - **SQL errors** appear in the first phase. Look for `SQL` message IDs.
65
+ - **RPG errors** appear in the second phase. Look for `RNF`/`RNS` message IDs.
66
+ - If the SQL precompile fails, the RPG compile does not run.
67
+
68
+ ### SQL precompile messages
69
+
70
+ ```
71
+ SQL0104 30 Position 45 Token "SELEC" was not valid. Valid tokens: ...
72
+ SQL0204 20 Table "MYLIB/NOTABLE" not found.
73
+ ```
74
+
75
+ The position or line number tells you where in the embedded SQL the error occurred.
76
+
77
+ ## CL listings (.clle, .clp, .cl)
78
+
79
+ CL compile errors appear as `CPD` or `CPF` messages:
80
+
81
+ ```
82
+ CPD0727 30 The character value specified is not a valid name.
83
+ CPF0001 40 Error found on CALL command.
84
+ ```
85
+
86
+ For ILE CL (`CRTBNDCL`, `CRTCLMOD`), the listing structure is similar to RPG -- source listing followed by a message summary.
87
+
88
+ For OPM CL (`CRTCLPGM`), the output is typically shorter and errors reference source sequence numbers.
89
+
90
+ ## DDS listings (.dspf, .pf, .lf, .prtf)
91
+
92
+ DDS compilation errors from `CRTDSPF`, `CRTPF`, `CRTLF`, or `CRTPRTF` produce `CPD` messages:
93
+
94
+ ```
95
+ CPD7302 30 Record format SCREEN1 not found in file referenced.
96
+ CPD7344 30 Keyword REF not valid for this type of file.
97
+ ```
98
+
99
+ DDS errors typically reference a specific record format and line within the source.
100
+
101
+ ## SQL DDL listings (.table.sql, .index.sql, .proc.sql)
102
+
103
+ SQL DDL statements executed via `RUNSQLSTM` produce SQL messages:
104
+
105
+ ```
106
+ SQL0104 30 Token "CREAT" was not valid.
107
+ SQL0601 20 Table EMPLOYEE in MYLIB already exists.
108
+ SQL7905 10 Module *N in *N not found.
109
+ ```
110
+
111
+ - Severity 30+ means the statement failed.
112
+ - Severity 20 warnings (like "already exists") may or may not be a problem depending on context.
113
+
114
+ ## Message files and binding directories (.msgf, .bnddir)
115
+
116
+ These execute CL commands from a source file. Errors appear as `CPF` or `CPD` messages from the individual CL commands:
117
+
118
+ ```
119
+ CPF2112 40 Object APPMSG type *MSGF already exists in library MYLIB.
120
+ CPF2105 30 Object MYSRVPGM in MYLIB type *SRVPGM not found.
121
+ ```
122
+
123
+ ## Practical example
124
+
125
+ A build of `mypgm.pgm` fails. Here is how to diagnose it:
126
+
127
+ ```bash
128
+ # 1. Check the log
129
+ cat tmp/logs/mypgm.pgm.log
130
+
131
+ # 2. Search for high-severity messages
132
+ grep -E 'RNF.{4}\s+[34]0|SQL.{4}\s+[34]0|CPD.{4}\s+[34]0|CPF.{4}\s+[34]0' tmp/logs/mypgm.pgm.log
133
+ ```
134
+
135
+ Example output:
136
+
137
+ ```
138
+ RNF5377 30 42 The type of expression does not match the type expected.
139
+ ```
140
+
141
+ This tells you line 42 of the RPG source has a type mismatch. Open the source file, go to line 42, and fix the expression type.