1#!/usr/bin/env python3 2 3# External command, intended to be called with run_command(), custom_target(), 4# meson.add_install_script() and meson.add_dist_script(). 5 6# argv[1] argv[2:] 7# generate-binding.py <subcommand> <xxx>... 8 9import os 10import sys 11import subprocess 12from pathlib import Path 13import shutil 14 15subcommand = sys.argv[1] 16 17# Invoked from custom_target() in meson.build. 18def generate_wrap_init(): 19 # argv[2] argv[3] argv[4] argv[5:] 20 # <gmmproc_dir> <output_file> <namespace> <hg_files>... 21 22 # <gmmproc_dir> is an absolute path in glibmm's installation directory. 23 # <output_file> is a relative or absolute path in the build directory. 24 # <hg_files> are relative or absolute paths in the source directory. 25 gmmproc_dir = sys.argv[2] 26 output_file = sys.argv[3] 27 parent_dir = os.path.basename(os.path.dirname(output_file)) 28 namespace = sys.argv[4] 29 cmd = [ 30 'perl', 31 '--', 32 os.path.join(gmmproc_dir, 'generate_wrap_init.pl'), 33 '--namespace=' + namespace, 34 '--parent_dir=' + parent_dir, 35 ] + sys.argv[5:] 36 with open(output_file, mode='w') as output_file_obj: 37 return subprocess.run(cmd, stdout=output_file_obj).returncode 38 39# Invoked from custom_target() in meson.build. 40def gmmproc(): 41 # argv[2] argv[3] argv[4] argv[5] argv[6:] 42 # <gmmproc_dir> <output_file> <basefilename> <src_dir> <m4_dirs>... 43 44 # <gmmproc_dir> is an absolute path in glibmm's installation directory. 45 # <output_file> is a relative or absolute path in the build directory. 46 # <src_dir> is an absolute path in the source directory. 47 # <m4_dirs> are absolute paths in the source directory. 48 gmmproc_dir = sys.argv[2] 49 output_file = sys.argv[3] 50 output_dir = os.path.dirname(output_file) 51 basefilename = sys.argv[4] # name without filetype 52 src_dir = sys.argv[5] 53 54 include_m4_dirs = [] 55 for dir in sys.argv[6:]: 56 include_m4_dirs += ['-I', dir] 57 58 # Create the private/ directory, if it does not exist. 59 os.makedirs(os.path.join(output_dir, 'private'), exist_ok=True) 60 61 # gmmproc generates output_dir/basefilename.cc, output_dir/basefilename.h 62 # and output_dir/private/{basefilename}_p.h 63 cmd = [ 64 'perl', 65 '-I' + os.path.join(gmmproc_dir, 'pm'), 66 '--', 67 os.path.join(gmmproc_dir, 'gmmproc'), 68 ] + include_m4_dirs + [ 69 '--defs', 70 src_dir, 71 basefilename, 72 src_dir, 73 output_dir, 74 ] 75 result = subprocess.run(cmd) 76 if result.returncode: 77 return result.returncode 78 79 # gmmproc does not update the timestamps of output files that have not changed. 80 # That's by design, to avoid unnecessary recompilations. 81 # The updated timestamp of output_file shows meson that this custom_target() 82 # has been updated. 83 Path(output_file).touch(exist_ok=True) 84 return 0 85 86# Invoked from meson.add_install_script(). 87def install_built_h_files(): 88 # argv[2] argv[3] argv[4:] 89 # <built_h_dir> <install_subdir> <basefilenames>... 90 91 # <built_h_dir> is an absolute path in the build directory or source directory. 92 # <install_subdir> is an installation directory, relative to {prefix}. 93 built_h_dir = sys.argv[2] 94 install_dir = os.path.join(os.getenv('MESON_INSTALL_DESTDIR_PREFIX'), sys.argv[3]) 95 96 # Create the installation directory, if it does not exist. 97 os.makedirs(os.path.join(install_dir, 'private'), exist_ok=True) 98 99 quiet = bool(os.getenv('MESON_INSTALL_QUIET')) 100 for file in sys.argv[4:]: 101 path_h = os.path.join(built_h_dir, file+'.h') 102 if not quiet: 103 print('Installing ', path_h, ' to ', install_dir) 104 # shutil.copy2() copies timestamps and some other file metadata. 105 shutil.copy2(path_h, install_dir) 106 107 path_h = os.path.join(built_h_dir, 'private', file+'_p.h') 108 install_priv_dir = os.path.join(install_dir, 'private') 109 if not quiet: 110 print('Installing ', path_h, ' to ', install_priv_dir) 111 shutil.copy2(path_h, install_priv_dir) 112 return 0 113 114# Invoked from meson.add_dist_script(). 115def dist_built_files(): 116 # argv[2] argv[3] argv[4:] 117 # <built_h_cc_dir> <dist_dir> <basefilenames>... 118 119 # <built_h_cc_dir> is an absolute path in the build directory or source directory. 120 # <dist_dir> is a distribution directory, relative to MESON_PROJECT_DIST_ROOT. 121 122 # MESON_PROJECT_DIST_ROOT is set only if meson.version() >= 0.58.0. 123 project_dist_root = os.getenv('MESON_PROJECT_DIST_ROOT', os.getenv('MESON_DIST_ROOT')) 124 built_h_cc_dir = sys.argv[2] 125 dist_dir = os.path.join(project_dist_root, sys.argv[3]) 126 127 # Create the distribution directory, if it does not exist. 128 os.makedirs(os.path.join(dist_dir, 'private'), exist_ok=True) 129 130 # Distribute wrap_init.cc. 131 # shutil.copy() does not copy timestamps. 132 shutil.copy(os.path.join(built_h_cc_dir, 'wrap_init.cc'), dist_dir) 133 134 # Distribute .h/.cc/_p.h files built from .hg/.ccg files. 135 for file in sys.argv[4:]: 136 shutil.copy(os.path.join(built_h_cc_dir, file+'.h'), dist_dir) 137 shutil.copy(os.path.join(built_h_cc_dir, file+'.cc'), dist_dir) 138 shutil.copy(os.path.join(built_h_cc_dir, 'private', file+'_p.h'), 139 os.path.join(dist_dir, 'private')) 140 return 0 141 142# Invoked from run_command() in meson.build. 143def copy_built_files(): 144 # argv[2] argv[3] argv[4:] 145 # <from_dir> <to_dir> <basefilenames>... 146 147 # <from_dir> is an absolute or relative path of the directory to copy from. 148 # <to_dir> is an absolute or relative path of the directory to copy to. 149 from_dir = sys.argv[2] 150 to_dir = sys.argv[3] 151 152 # Create the destination directory, if it does not exist. 153 os.makedirs(os.path.join(to_dir, 'private'), exist_ok=True) 154 155 # Copy some built files if they exist in from_dir, but not in the destination 156 # directory, or if they are not up to date in the destination directory. 157 # (The term "source directory" is avoided here, because from_dir might not 158 # be what Meson calls a source directory as opposed to a build directory.) 159 160 # Copy wrap_init.cc. 161 from_file = os.path.join(from_dir, 'wrap_init.cc') 162 to_file = os.path.join(to_dir, 'wrap_init.cc') 163 if os.path.isfile(from_file) and ((not os.path.isfile(to_file)) 164 or (os.stat(from_file).st_mtime > os.stat(to_file).st_mtime)): 165 shutil.copy(from_file, to_file) 166 167 # Copy .h/.cc/_p.h files built from .hg/.ccg files. 168 for basefile in sys.argv[4:]: 169 for file in [basefile+'.h', basefile+'.cc', os.path.join('private', basefile+'_p.h')]: 170 from_file = os.path.join(from_dir, file) 171 to_file = os.path.join(to_dir, file) 172 if os.path.isfile(from_file) and ((not os.path.isfile(to_file)) 173 or (os.stat(from_file).st_mtime > os.stat(to_file).st_mtime)): 174 shutil.copy(from_file, to_file) 175 return 0 176 177# ----- Main ----- 178if subcommand == 'generate_wrap_init': 179 sys.exit(generate_wrap_init()) 180if subcommand == 'gmmproc': 181 sys.exit(gmmproc()) 182if subcommand == 'install_built_h_files': 183 sys.exit(install_built_h_files()) 184if subcommand == 'dist_built_files': 185 sys.exit(dist_built_files()) 186if subcommand == 'copy_built_files': 187 sys.exit(copy_built_files()) 188print(sys.argv[0], ': illegal subcommand,', subcommand) 189sys.exit(1) 190