myxce/src/lib/meson.build
Rongsong Shen f09fbdb342
fix(build): close the same codegen race for the four PEG parsers (bug-1798)
Follow-up audit (requested: check other generated sources, specifically
packcc/PEG output) found the identical bug shape in the four PEG-parser
custom_targets: section_parser, rusage_parser, xce_resreq_parser, and
xce_select_parser each produce a .c + a paired .h (section.h, rusage.h,
xce_resreq.h, xce_select_peg.h), but libxce_src only referenced each
parser's [0] (.c) index. lib/resreq.c -- confirmed via a project-wide
grep to be the only consumer of any of these four headers -- had no
declared build-order dependency on any of the four codegen steps.

Fix: pass each of the four custom_targets unindexed into libxce_src,
same pattern as the capnp fix. No libxce_dep change needed here since
nothing outside src/lib/ consumes these headers.

A project-wide search confirms these, plus the capnp custom_target, are
the only multi-output C/H codegen steps in the whole build -- every other
custom_target() (xceadmin, apiserver, xcecli, autoscaler/providers)
produces a single Go-binary/stamp output with no equivalent hazard.

Verified: a third consecutive full from-scratch `./tools/xce-build.sh all
debug` build (1173/1173 targets) succeeded clean; a fresh `lib debug`
build plus the full lib test suite (313/313) passed; a fresh incremental
controller/ASAN rebuild passed 1331/1331 on a quiet re-run (its first,
concurrent-with-the-full-build run hit an unrelated, confirmed-flaky PTY
harness timing failure in test_smoke_launch_send_echo_capture_stdout_and_exit_code,
reproduced as system-load-induced, not caused by this change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 07:53:51 +00:00

241 lines
8.8 KiB
Meson

capnp = find_program('capnp')
packcc = find_program('packcc')
schema_dir = meson.current_source_dir() / '..' / 'schema'
gen_srcs = custom_target(
'controllercapnp.[ch]',
output:['controller.capnp.c', 'controller.capnp.h'],
input: '../schema/controller.capnp',
command: [capnp, 'compile','-o' ,'c:lib', '-I', schema_dir, '--src-prefix', schema_dir, '@INPUT@']
)
section_parser = custom_target(
'xce resreq section parser',
output: ['section.c', 'section.h'],
input: ['section.peg'],
command: [
packcc,
'-l',
'-o',
'lib/section',
'@INPUT@'
],
build_by_default: true)
rusage_parser = custom_target(
'xce resreq rusage parser',
output: ['rusage.c', 'rusage.h'],
input: ['rusage.peg'],
command: [
packcc,
'-l',
'-o',
'lib/rusage',
'@INPUT@'
],
build_by_default: true)
xce_resreq_parser = custom_target(
'xce resreq xce_resreq parser',
output: ['xce_resreq.c', 'xce_resreq.h'],
input: ['xce_resreq.peg'],
command: [
packcc,
'-l',
'-o',
'lib/xce_resreq',
'@INPUT@'
],
build_by_default: true)
xce_select_parser = custom_target(
'xce select expression parser',
output: ['xce_select_peg.c', 'xce_select_peg.h'],
input: ['xce_select.peg'],
command: [
packcc,
'-l',
'-o',
'lib/xce_select_peg',
'@INPUT@'
],
build_by_default: true)
libxce_src = [ # bug-1798: pass the whole gen_srcs custom_target (both
# controller.capnp.c AND controller.capnp.h), not just
# gen_srcs[0] -- several files below (utils.c and others)
# reach controller.capnp.h only via #include, which ninja
# cannot see. Indexing to gen_srcs[0] dropped that header
# from this target's declared outputs entirely, so a
# from-scratch build had no dependency edge forcing capnp
# codegen to finish before those files compiled,
# intermittently failing with "controller.capnp.h: No such
# file or directory" (recurring since 2026-07-16). Passing
# the full custom_target compiles only its .c output (as
# before) while ordering the ENTIRE target's build after
# BOTH outputs are generated.
gen_srcs,
# bug-1798 (same class): each packcc parser custom_target
# below also produces a paired .h output (section.h,
# rusage.h, xce_resreq.h, xce_select_peg.h) that only
# resreq.c #includes -- a separate file from each parser's
# own generated .c. Indexing to [0] dropped every one of
# these headers from libxce_src, leaving resreq.c's compile
# with no declared dependency on any of the four codegen
# steps. Passing each custom_target unindexed compiles only
# its .c output (as before) while ordering this whole
# target's build after both of its outputs.
section_parser,
rusage_parser,
xce_resreq_parser,
xce_select_parser,
'client.c',
'client_failover.c',
'dataq.c',
'hook.c',
'htab.c',
'kvmgr.c',
'mylock.c',
'netio.c',
'request.c',
'threshold.c',
'utils.c',
'vtaskmgr.c',
'window.c',
'xceapi.c',
'xcectx.c',
'xcelist.c',
'xlist.c',
'xstring.c',
'zarray.c',
'wrap.c',
'idgen.c',
'delay.c',
'ordq.c',
'preason.c',
'xcealloc.c',
'misc.c',
'group.c',
'xcelimit.c',
'xvec.c',
'helper.c',
'resreq.c',
'xce_select.c',
'bitset.c',
'kv.c',
'jobj.c',
'qobj.c',
'resobj.c',
'wobj.c',
'configobj.c',
'cluster.c',
'raft/raft.c',
]
incdir = include_directories('../include')
build_inc = include_directories('.')
capnpc_c_prog = find_program('capnpc-c')
# debug('capnpc_c_prog %s\n', capnpc_c_prog)
thread_dep = dependency('threads')
c_capnproto_dep = dependency('c-capnproto')
tinylog_dep = dependency('tinylog')
unity_dep = dependency('unity')
ssl_dep = dependency('openssl')
libxce_deps = [c_capnproto_dep, ssl_dep, tinylog_dep, thread_dep]
#libxce_shared = shared_library('xce',
# libxce_src,
# include_directories: [incdir, build_inc],
# dependencies: libxce_deps,
# install: true)
libxce = static_library('xce',
libxce_src,
include_directories: [incdir, build_inc],
dependencies: libxce_deps,
install: true)
# bug-1798: `sources: [gen_srcs]` forces every consumer of libxce_dep
# (controller/worker/scheduler, none of which otherwise declare any
# dependency on this codegen step even though several of their own .c
# files #include "controller.capnp.h" directly via a raw -Ilib path) to
# build gen_srcs' outputs before compiling their own sources -- closing
# the same missing-dependency-edge race as the libxce_src fix above, but
# for consumers OUTSIDE the libxce target itself. link_with alone does not
# propagate this: it only orders the LINK step after libxce is built, not
# a consumer's own COMPILE steps against a header libxce never installs.
libxce_dep = declare_dependency(link_with: libxce, sources: [gen_srcs])
# libxce_shared_dep = declare_dependency(link_with: libxce_shared)
libxce_test_src = ['testsuite/test.c',
'testsuite/test_error.c',
'testsuite/test_htab.c',
'testsuite/test_htab_int.c',
'testsuite/test_utils.c',
'testsuite/test_xstring.c',
'testsuite/test_zarray.c',
'testsuite/test_config.c',
'testsuite/test_idgen.c',
'testsuite/test_delay.c',
'testsuite/test_ordq.c',
'testsuite/test_preason.c',
'testsuite/test_kvmgr.c',
'testsuite/test_group.c',
'testsuite/test_xlist.c',
'testsuite/test_limit.c',
'testsuite/test_xvec.c',
'testsuite/test_resreq.c',
'testsuite/test_resreq_fingerprint.c',
'testsuite/test_resreq_task_count.c',
'testsuite/test_resmgr_fixture.c',
'testsuite/test_select.c',
'testsuite/test_bitset.c',
'testsuite/test_kv.c',
'testsuite/test_jobj.c',
'testsuite/test_jobj_hardening.c',
'testsuite/test_wobj.c',
'testsuite/test_qobj.c',
'testsuite/test_request.c',
'testsuite/test_job_state_wire.c',
'testsuite/test_cbuf.c',
'testsuite/test_zarray_cow.c',
'testsuite/test_kvmgr_capture.c',
'testsuite/test_zarray_reserve.c',
'testsuite/test_kvmgr_reserve.c',
'testsuite/test_hooks.c',
'testsuite/test_cluster.c',
'testsuite/test_cluster_parse.c',
'testsuite/test_libxce_retry.c',
'testsuite/test_netio_on_connected.c',
'testsuite/test_netio_on_fini.c',
'testsuite/test_netio_reconnect_gen.c',
'testsuite/test_netio_arm_failure.c',
'testsuite/test_netio_close_propagation.c',
'testsuite/test_netio_bounded_connect.c',
'testsuite/test_netio_batch_dispatch_uaf.c',
'testsuite/test_request_send_propagation.c',
'testsuite/test_raft.c',
'testsuite/test_wal_wire.c',
'testsuite/test_ctrlstatus.c',
'testsuite/test_vtask_admission.c',
'testsuite/test_vtask_enq_race.c',
'testsuite/test_xcealloc.c',
'raft/raft_sim.c',
]
libxce_test_deps = [libxce_deps, librtti_dep, unity_dep, libxce_dep]
libxce_test = executable('xcelib_test',
libxce_test_src,
include_directories: [incdir, build_inc],
dependencies: libxce_test_deps,
c_args: ['-DXCE_TESTING'],
install: true)
test('libxce test', libxce_test, timeout: 120)