File size: 4,083 Bytes
cf8614b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | #!/usr/bin/env python
'''Generate simConst.py from simConst.h distributed from CoppeliaSim
$ ./generate_simConst.py > ../pyrep/backend/simConst.py
'''
import contextlib
import importlib
import os
import os.path as osp
import re
import shlex
import shutil
import subprocess
import sys
import tempfile
try:
import CppHeaderParser
except ImportError:
print('Please run following:\n\tpip install CppHeaderParser',
file=sys.stderr)
sys.exit(1)
def get_coppeliasim_root():
if 'COPPELIASIM_ROOT' not in os.environ:
raise RuntimeError('Please set env COPPELIASIM_ROOT')
return os.environ['COPPELIASIM_ROOT']
def import_as(filename, module):
spec = importlib.util.spec_from_file_location(
module, filename
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def generate_simConst_py():
header_file = osp.join(
get_coppeliasim_root(), 'programming/include/simConst.h'
)
with contextlib.redirect_stdout(sys.stderr):
header = CppHeaderParser.CppHeader(header_file)
assert header.classes == {}
assert header.functions == []
assert header.global_enums == {}
names = []
for define in header.defines:
m = re.match('^(.*)/\*.*\*/', define)
if m:
define = m.groups()[0]
splits = define.split()
if len(splits) == 2:
name, _ = splits
if name in ['SIM_PROGRAM_VERSION']:
continue
names.append(name)
for enum in header.enums:
assert enum['namespace'] == ''
for value in enum['values']:
names.append(value['name'])
names.append('')
out_dir = tempfile.mkdtemp()
cpp_file = osp.join(out_dir, 'generate_simConst_py.cpp')
with open(cpp_file, 'w') as f:
f.write('#include <iostream>\n')
f.write('#include <simConst.h>\n')
f.write('int main() {\n')
for name in names:
if name:
f.write(
f'\tstd::cout << "{name} = " << {name} << std::endl;\n'
)
else:
f.write('\tstd::cout << std::endl;\n')
f.write('}\n')
out_file = osp.join(out_dir, 'generate_simConst_py')
cmd = f'g++ {cpp_file} -o {out_file} -I{osp.dirname(header_file)}'
subprocess.check_call(shlex.split(cmd))
cmd = osp.join(out_dir, 'generate_simConst_py')
code = subprocess.check_output(cmd).strip().decode()
shutil.rmtree(out_dir)
return code
def merge_simConst_py(code):
official_file = osp.join(
get_coppeliasim_root(),
'programming/remoteApiBindings/python/python/simConst.py')
official = import_as(official_file, 'official')
out_dir = tempfile.mkdtemp()
generated_file = osp.join(out_dir, 'simConst_generated.py')
with open(generated_file, 'w') as f:
f.write(code)
generated = import_as(generated_file, 'generated')
name_and_value = []
for name in dir(official):
if re.match('__.*__', name):
continue
if name in dir(generated):
value_official = getattr(official, name)
value_generated = getattr(generated, name)
if value_official != value_generated:
print(f"WARNING: The values of var '{name}' is not equal: "
f'official={value_official}, '
f'generated={value_generated}', file=sys.stderr)
else:
name_and_value.append((name, getattr(official, name)))
code = ('# This file is automatically generated by '
f'{osp.basename(__file__)} from simConst.h\n\n' + code)
code += ('\n\n# Followings are copied from official simConst.py '
'(so possibly deprecated in C++ API)')
for name, value in name_and_value:
code += f'\n{name} = {value}'
code += '\n'
return code
def main():
code = generate_simConst_py()
code = merge_simConst_py(code)
print(code, end='')
if __name__ == '__main__':
main()
|