82def build_cpp_test(sources_dir: Path,
85 build_subdir: Optional[str] =
None) -> Path:
86 """Configure + build a C++ integration test target, returning the binary.
88 * ``sources_dir``: root provided by ``cosim_test`` (contains ``generated/``).
89 * ``target``: CMake target name (e.g. ``loopback_test``).
90 * ``header_subdir``: subdirectory under the include root where the generated
91 headers are copied (e.g. ``"loopback"`` or ``"test_codegen"``).
92 * ``build_subdir``: name for the build directory under ``sources_dir``.
93 Defaults to ``target``.
95 The configure step is skipped when the Ninja build file already exists;
96 ``cmake --build`` always runs so that CMake's own dependency tracking
97 picks up any source or generated-header changes.
100 require_tool(
"ninja")
102 if build_subdir
is None:
103 build_subdir = target
104 build_dir = sources_dir / build_subdir
105 exe_suffix =
".exe" if os.name ==
"nt" else ""
106 binary = build_dir / (target + exe_suffix)
108 runtime_root = get_runtime_root()
109 include_dir = sources_dir /
"cpp_include"
110 generated_dir = include_dir / header_subdir
112 if not (build_dir /
"build.ninja").exists():
113 if build_dir.exists():
114 shutil.rmtree(build_dir)
116 generated_dir.mkdir(parents=
True, exist_ok=
True)
118 codegen_src = sources_dir /
"generated"
119 if codegen_src.exists():
120 for item
in codegen_src.iterdir():
122 shutil.copy(item, generated_dir)
124 result = subprocess.run(
133 "-DCMAKE_BUILD_TYPE=Release",
134 f
"-DLOOPBACK_GENERATED_DIR={include_dir}",
135 f
"-DESI_RUNTIME_ROOT={runtime_root}",
140 assert result.returncode == 0, (
141 f
"cmake configure failed (rc={result.returncode}):\n"
142 f
"--- stdout ---\n{result.stdout}\n"
143 f
"--- stderr ---\n{result.stderr}")
145 result = subprocess.run(
148 str(build_dir),
"--target", target,
"--config",
"Release"
153 assert result.returncode == 0, (
154 f
"cmake build failed (rc={result.returncode}):\n"
155 f
"--- stdout ---\n{result.stdout}\n"
156 f
"--- stderr ---\n{result.stderr}")