Skip to content

Commit 7de784e

Browse files
[NFC] split up gen_struct_info.py's inspect_headers function (#22247)
This helps when trying to generate struct info via another build system (i.e. bazel). I'm now able to call into these functions individually. I think breaking up the large function into smaller and more focused functions also helps readability.
1 parent d99a75f commit 7de784e

File tree

1 file changed

+71
-57
lines changed

1 file changed

+71
-57
lines changed

tools/maint/gen_struct_info.py

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,31 @@
7777
QUIET = (__name__ != '__main__')
7878
DEBUG = False
7979

80+
CFLAGS = [
81+
# Avoid parsing problems due to gcc specific syntax.
82+
'-D_GNU_SOURCE',
83+
]
84+
85+
INTERNAL_CFLAGS = [
86+
'-I' + utils.path_from_root('system/lib/libc/musl/src/internal'),
87+
'-I' + utils.path_from_root('system/lib/libc/musl/src/include'),
88+
'-I' + utils.path_from_root('system/lib/pthread/'),
89+
]
90+
91+
CXXFLAGS = [
92+
'-I' + utils.path_from_root('system/lib/libcxxabi/src'),
93+
'-D__EMSCRIPTEN_EXCEPTIONS__',
94+
'-I' + utils.path_from_root('system/lib/wasmfs/'),
95+
'-std=c++17',
96+
]
97+
98+
DEFAULT_JSON_FILES = [
99+
utils.path_from_root('src/struct_info.json'),
100+
utils.path_from_root('src/struct_info_internal.json'),
101+
utils.path_from_root('src/struct_info_cxx.json'),
102+
utils.path_from_root('src/struct_info_webgpu.json'),
103+
]
104+
80105

81106
def show(msg):
82107
if shared.DEBUG or not QUIET:
@@ -179,7 +204,7 @@ def gen_inspect_code(path, struct, code):
179204
c_ascent(code)
180205

181206

182-
def inspect_headers(headers, cflags):
207+
def generate_c_code(headers):
183208
code = ['#include <stdio.h>', '#include <stddef.h>']
184209
for header in headers:
185210
code.append('#include "' + header['name'] + '"')
@@ -211,28 +236,10 @@ def inspect_headers(headers, cflags):
211236
code.append('return 0;')
212237
code.append('}')
213238

214-
# Write the source code to a temporary file.
215-
src_file = tempfile.mkstemp('.c', text=True)
216-
show('Generating C code... ' + src_file[1])
217-
os.write(src_file[0], '\n'.join(code).encode())
218-
219-
js_file = tempfile.mkstemp('.js')
220-
221-
# Check sanity early on before populating the cache with libcompiler_rt
222-
# If we don't do this the parallel build of compiler_rt will run while holding the cache
223-
# lock and with EM_EXCLUSIVE_CACHE_ACCESS set causing N processes to race to run sanity checks.
224-
# While this is not in itself serious problem it is wasteful and noise on stdout.
225-
# For the same reason we run this early in embuilder.py and emcc.py.
226-
# TODO(sbc): If we can remove EM_EXCLUSIVE_CACHE_ACCESS then this would not longer be needed.
227-
shared.check_sanity()
228-
229-
compiler_rt = system_libs.Library.get_usable_variations()['libcompiler_rt'].build()
239+
return code
230240

231-
# Close all unneeded FDs.
232-
os.close(src_file[0])
233-
os.close(js_file[0])
234241

235-
info = []
242+
def generate_cmd(js_file_path, src_file_path, cflags, compiler_rt):
236243
# Compile the program.
237244
show('Compiling generated code...')
238245

@@ -244,7 +251,7 @@ def inspect_headers(headers, cflags):
244251
node_flags = building.get_emcc_node_flags(shared.check_node_version())
245252

246253
# -O1+ produces calls to iprintf, which libcompiler_rt doesn't support
247-
cmd = [compiler] + cflags + ['-o', js_file[1], src_file[1],
254+
cmd = [compiler] + cflags + ['-o', js_file_path, src_file_path,
248255
'-O0',
249256
'-Werror',
250257
'-Wno-format',
@@ -272,27 +279,54 @@ def inspect_headers(headers, cflags):
272279
cmd += ['-sMEMORY64=2', '-Wno-experimental']
273280

274281
show(shared.shlex_join(cmd))
282+
return cmd
283+
284+
285+
def inspect_headers(headers, cflags):
286+
# Write the source code to a temporary file.
287+
src_file_fd, src_file_path = tempfile.mkstemp('.c', text=True)
288+
show('Generating C code... ' + src_file_path)
289+
code = generate_c_code(headers)
290+
os.write(src_file_fd, '\n'.join(code).encode())
291+
os.close(src_file_fd)
292+
293+
# Check sanity early on before populating the cache with libcompiler_rt
294+
# If we don't do this the parallel build of compiler_rt will run while holding the cache
295+
# lock and with EM_EXCLUSIVE_CACHE_ACCESS set causing N processes to race to run sanity checks.
296+
# While this is not in itself serious problem it is wasteful and noise on stdout.
297+
# For the same reason we run this early in embuilder.py and emcc.py.
298+
# TODO(sbc): If we can remove EM_EXCLUSIVE_CACHE_ACCESS then this would not longer be needed.
299+
shared.check_sanity()
300+
301+
compiler_rt = system_libs.Library.get_usable_variations()['libcompiler_rt'].build()
302+
303+
js_file_fd, js_file_path = tempfile.mkstemp('.js')
304+
# Close the unneeded FD.
305+
os.close(js_file_fd)
306+
307+
cmd = generate_cmd(js_file_path, src_file_path, cflags, compiler_rt)
308+
275309
try:
276310
subprocess.check_call(cmd, env=system_libs.clean_env())
277311
except subprocess.CalledProcessError as e:
278312
sys.stderr.write('FAIL: Compilation failed!: %s\n' % e.cmd)
279313
sys.exit(1)
280314

281315
# Run the compiled program.
282-
show('Calling generated program... ' + js_file[1])
316+
show('Calling generated program... ' + js_file_path)
283317
args = []
284318
if settings.MEMORY64:
285319
args += shared.node_bigint_flags(config.NODE_JS)
286-
info = shared.run_js_tool(js_file[1], node_args=args, stdout=shared.PIPE).splitlines()
320+
info = shared.run_js_tool(js_file_path, node_args=args, stdout=shared.PIPE).splitlines()
287321

288322
if not DEBUG:
289323
# Remove all temporary files.
290-
os.unlink(src_file[1])
324+
os.unlink(src_file_path)
291325

292-
if os.path.exists(js_file[1]):
293-
os.unlink(js_file[1])
294-
wasm_file = shared.replace_suffix(js_file[1], '.wasm')
295-
os.unlink(wasm_file)
326+
if os.path.exists(js_file_path):
327+
os.unlink(js_file_path)
328+
wasm_file_path = shared.replace_suffix(js_file_path, '.wasm')
329+
os.unlink(wasm_file_path)
296330

297331
# Parse the output of the program into a dict.
298332
return parse_c_output(info)
@@ -366,16 +400,10 @@ def output_json(obj, stream):
366400
def main(args):
367401
global QUIET
368402

369-
default_json_files = [
370-
utils.path_from_root('src/struct_info.json'),
371-
utils.path_from_root('src/struct_info_internal.json'),
372-
utils.path_from_root('src/struct_info_cxx.json'),
373-
utils.path_from_root('src/struct_info_webgpu.json'),
374-
]
375403
parser = argparse.ArgumentParser(description='Generate JSON infos for structs.')
376404
parser.add_argument('json', nargs='*',
377405
help='JSON file with a list of structs and their fields (defaults to src/struct_info.json)',
378-
default=default_json_files)
406+
default=DEFAULT_JSON_FILES)
379407
parser.add_argument('-q', dest='quiet', action='store_true', default=False,
380408
help='Don\'t output anything besides error messages.')
381409
parser.add_argument('-o', dest='output', metavar='path', default=None,
@@ -392,34 +420,20 @@ def main(args):
392420

393421
QUIET = args.quiet
394422

395-
# Avoid parsing problems due to gcc specifc syntax.
396-
cflags = ['-D_GNU_SOURCE']
423+
extra_cflags = []
397424

398425
if args.wasm64:
399426
settings.MEMORY64 = 2
400427

401428
# Add the user options to the list as well.
402429
for path in args.includes:
403-
cflags.append('-I' + path)
430+
extra_cflags.append('-I' + path)
404431

405432
for arg in args.defines:
406-
cflags.append('-D' + arg)
433+
extra_cflags.append('-D' + arg)
407434

408435
for arg in args.undefines:
409-
cflags.append('-U' + arg)
410-
411-
internal_cflags = [
412-
'-I' + utils.path_from_root('system/lib/libc/musl/src/internal'),
413-
'-I' + utils.path_from_root('system/lib/libc/musl/src/include'),
414-
'-I' + utils.path_from_root('system/lib/pthread/'),
415-
]
416-
417-
cxxflags = [
418-
'-I' + utils.path_from_root('system/lib/libcxxabi/src'),
419-
'-D__EMSCRIPTEN_EXCEPTIONS__',
420-
'-I' + utils.path_from_root('system/lib/wasmfs/'),
421-
'-std=c++17',
422-
]
436+
extra_cflags.append('-U' + arg)
423437

424438
# Look for structs in all passed headers.
425439
info = {'defines': {}, 'structs': {}}
@@ -429,11 +443,11 @@ def main(args):
429443
header_files = parse_json(f)
430444
# Inspect all collected structs.
431445
if 'internal' in f:
432-
use_cflags = cflags + internal_cflags
446+
use_cflags = CFLAGS + extra_cflags + INTERNAL_CFLAGS
433447
elif 'cxx' in f:
434-
use_cflags = cflags + cxxflags
448+
use_cflags = CFLAGS + extra_cflags + CXXFLAGS
435449
else:
436-
use_cflags = cflags
450+
use_cflags = CFLAGS + extra_cflags
437451
info_fragment = inspect_code(header_files, use_cflags)
438452
merge_info(info, info_fragment)
439453

0 commit comments

Comments
 (0)