+###
+### Helpers for custom targets used across the tree
+###
+
+catalog_pm = files('src/backend/catalog/Catalog.pm')
+perfect_hash_pm = files('src/tools/PerfectHash.pm')
+gen_kwlist_deps = [perfect_hash_pm]
+gen_kwlist_cmd = [
+  perl, '-I', '@SOURCE_ROOT@/src/tools',
+  files('src/tools/gen_keywordlist.pl'),
+  '--output', '@OUTDIR@', '@INPUT@']
+
+
+
 ###
 ### windows resources related stuff
 ###
 
 common_kwlist = custom_target('kwlist',
   input: files('../include/parser/kwlist.h'),
   output: 'kwlist_d.h',
-  command: [perl, '-I', '@SOURCE_ROOT@/src/tools', files('../tools/gen_keywordlist.pl'),
-      '--extern', '--output', '@OUTDIR@', '@INPUT@'])
+  depend_files: gen_kwlist_deps,
+  command: [gen_kwlist_cmd, '--extern'])
 generated_sources += common_kwlist
 common_sources += common_kwlist
 
 
   custom_target('unicode_norm_table.h',
     input: [unicode_data['UnicodeData.txt'], unicode_data['CompositionExclusions.txt']],
     output: ['unicode_norm_table.h', 'unicode_norm_hashfunc.h'],
+    depend_files: perfect_hash_pm,
     command: [
       perl, files('generate-unicode_norm_table.pl'),
       '--outdir', '@OUTDIR@', '@INPUT@'],
   custom_target('unicode_nonspacing_table.h',
     input: [unicode_data['UnicodeData.txt']],
     output: ['unicode_nonspacing_table.h'],
+    depend_files: perfect_hash_pm,
     command: [perl, files('generate-unicode_nonspacing_table.pl'), '@INPUT@'],
     build_by_default: false,
     capture: true,
   custom_target('unicode_normprops_table.h',
     input: [unicode_data['DerivedNormalizationProps.txt']],
     output: ['unicode_normprops_table.h'],
+    depend_files: perfect_hash_pm,
     command: [perl, files('generate-unicode_normprops_table.pl'), '@INPUT@'],
     build_by_default: false,
     capture: true,
 
   output: output_files,
   install_dir: output_install,
   input: input,
-  depend_files: bki_data_f,
+  depend_files: bki_data_f + catalog_pm,
   build_by_default: true,
   install: true,
   command: [
 
 generated_nodes = custom_target('nodetags.h',
   input: node_support_input,
   output: node_support_output,
+  depend_files: catalog_pm,
   command: [
     perl, files('../../backend/nodes/gen_node_support.pl'),
     '-o', '@OUTDIR@',
 
 fmgrtab_target = custom_target('fmgrtab',
   input: '../catalog/pg_proc.dat',
   output : fmgrtab_output,
+  depend_files: catalog_pm,
   command: [perl, '-I', '@SOURCE_ROOT@/src/backend/catalog/', files('../../backend/utils/Gen_fmgrtab.pl'), '--include-path=@SOURCE_ROOT@/src/include', '--output=@OUTDIR@', '@INPUT@'],
   install: true,
   install_dir: [dir_include_server / 'utils', dir_include_server / 'utils', false],
 
   input: ['c_kwlist.h'],
   output: ['c_kwlist_d.h'],
   depends: check_rules,
-  command: [
-    perl,
-    '-I', '@SOURCE_ROOT@/src/tools',
-    '@SOURCE_ROOT@/src/tools/gen_keywordlist.pl',
-    '--output', '@OUTDIR@',
-    '--varname', 'ScanCKeywords',
-    '--no-case-fold', '@INPUT0@',
-  ],
+  depend_files: gen_kwlist_deps,
+  command: [gen_kwlist_cmd, '--varname', 'ScanCKeywords', '--no-case-fold'],
 )
 generated_sources += c_kwlist
 ecpg_sources += c_kwlist
 ecpg_kwlist = custom_target('ecpg_kwlist_d.h',
   input: ['ecpg_kwlist.h'],
   output: ['ecpg_kwlist_d.h'],
-  command: [
-    perl, '-I',
-    '@SOURCE_ROOT@/src/tools',
-    '@SOURCE_ROOT@/src/tools/gen_keywordlist.pl',
-    '--output', '@OUTDIR@',
-    '--varname', 'ScanECPGKeywords', '@INPUT0@',
-  ]
+  depend_files: gen_kwlist_deps,
+  command: [gen_kwlist_cmd, '--varname', 'ScanECPGKeywords'],
 )
 generated_sources += ecpg_kwlist
 ecpg_sources += ecpg_kwlist
 
 generated_sources += pl_errcodes
 plpgsql_sources += pl_errcodes
 
-gen_keywordlist = files('../../../../src/tools/gen_keywordlist.pl')
 pl_reserved = custom_target('pl_reserved_kwlist',
   input: ['pl_reserved_kwlist.h'],
   output: ['pl_reserved_kwlist_d.h'],
-  command: [perl, '-I', '@SOURCE_ROOT@/src/tools', gen_keywordlist, '--output', '@OUTDIR@', '--varname', 'ReservedPLKeywords', '@INPUT@']
+  depend_files: gen_kwlist_deps,
+  command: [gen_kwlist_cmd, '--varname', 'ReservedPLKeywords'],
 )
 generated_sources += pl_reserved
 plpgsql_sources += pl_reserved
 pl_unreserved = custom_target('pl_unreserved_kwlist',
   input: ['pl_unreserved_kwlist.h'],
   output: ['pl_unreserved_kwlist_d.h'],
-  command: [perl, '-I', '@SOURCE_ROOT@/src/tools', gen_keywordlist, '--output', '@OUTDIR@', '--varname', 'UnreservedPLKeywords', '@INPUT@']
+  depend_files: gen_kwlist_deps,
+  command: [gen_kwlist_cmd, '--varname', 'UnreservedPLKeywords'],
 )
 generated_sources += pl_unreserved
 plpgsql_sources += pl_unreserved