Skip to content

Commit 16ef221

Browse files
committed
Update
[ghstack-poisoned]
2 parents f5819c2 + c16d525 commit 16ef221

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

.ci/scripts/wheel/test_cpp_sdk.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,34 @@
7070
_OWNING_KINDS = frozenset("TtBbDdGgSsRrWV")
7171

7272
_CONSUMER_SOURCE = """\
73+
#include <executorch/extension/module/module.h>
74+
#include <executorch/extension/tensor/tensor.h>
7375
#include <executorch/runtime/backend/interface.h>
7476
#include <executorch/runtime/platform/runtime.h>
7577
7678
#include <cstdio>
79+
#include <vector>
80+
81+
using namespace executorch::extension;
7782
7883
int main() {
7984
executorch::runtime::runtime_init();
8085
std::printf(
8186
"registered backends: %zu\\n",
8287
(size_t)executorch::runtime::get_num_registered_backends());
88+
89+
// The documented entry points, not just the lower-level runtime. Constructing these
90+
// needs real definitions at link time, so it checks that the shipped headers and the
91+
// shipped library agree rather than only that the headers parse.
92+
module::Module module("nonexistent.pte");
93+
std::vector<float> data(4, 1.0f);
94+
auto input = make_tensor_ptr({2, 2}, data.data());
95+
std::printf("tensor holds %zu values\\n", (size_t)input->numel());
96+
97+
// A missing file is the expected outcome here. What matters is that the call resolves
98+
// and returns an error rather than failing to link.
99+
const auto error = module.load();
100+
std::printf("module load returned 0x%x as expected\\n", (unsigned)error);
83101
return 0;
84102
}
85103
"""
@@ -793,6 +811,62 @@ def test_component_targets_link(work_dir: Path) -> None:
793811
print(f"✓ every offered component links and is retained: {sorted(linked)}")
794812

795813

814+
def test_documented_example_compiles(work_dir: Path) -> None:
815+
"""The C++ example in the documentation must compile against the installed wheel.
816+
817+
Extracted from the documentation rather than copied here, so the two cannot drift. A
818+
reader who follows the documentation gets code that builds, and a dangling include or a
819+
renamed entry point fails this check instead of shipping.
820+
"""
821+
# Guarded the same way the wheel lookup is: a copy of this file can live outside the
822+
# repository layout, where indexing past the available parents raises.
823+
here = Path(__file__).resolve()
824+
root = here.parents[3] if len(here.parents) > 3 else here.parent
825+
documentation = root / "docs" / "source" / "using-executorch-cpp.md"
826+
if not documentation.is_file():
827+
print("- the documentation file is not present, skipping the example check")
828+
return
829+
830+
match = re.search(
831+
r"```cpp\n// main\.cpp\n(.*?)```", documentation.read_text(), re.S
832+
)
833+
assert match, (
834+
f"could not find the C++ example in {documentation.name}; the check needs it to "
835+
"verify what the documentation tells a reader to write"
836+
)
837+
838+
source_dir = work_dir / "documented"
839+
source_dir.mkdir(parents=True, exist_ok=True)
840+
(source_dir / "main.cpp").write_text("// main.cpp\n" + match.group(1))
841+
(source_dir / "CMakeLists.txt").write_text(
842+
"cmake_minimum_required(VERSION 3.28)\n"
843+
"project(documented_example CXX)\n"
844+
"find_package(executorch REQUIRED)\n"
845+
"add_executable(documented_example main.cpp)\n"
846+
"target_link_libraries(documented_example PRIVATE executorch::runtime)\n"
847+
)
848+
849+
build_dir = work_dir / "documented-build"
850+
configure = subprocess.run(
851+
["cmake", "-S", str(source_dir), "-B", str(build_dir),
852+
f"-DCMAKE_PREFIX_PATH={_installed_package_dir()}"],
853+
capture_output=True, text=True, check=False,
854+
)
855+
assert configure.returncode == 0, (
856+
"the documented example does not configure against the installed wheel: "
857+
f"{(configure.stderr or configure.stdout).strip()[-500:]}"
858+
)
859+
build = subprocess.run(
860+
["cmake", "--build", str(build_dir)],
861+
capture_output=True, text=True, check=False,
862+
)
863+
assert build.returncode == 0, (
864+
"the documented example does not compile against the installed wheel: "
865+
f"{(build.stderr or build.stdout).strip()[-500:]}"
866+
)
867+
print("\u2713 the C++ example in the documentation compiles and links")
868+
869+
796870
def run_tests(work_dir: Path) -> None:
797871
test_single_backend_registry()
798872
test_python_extensions_import()
@@ -805,4 +879,5 @@ def run_tests(work_dir: Path) -> None:
805879
test_single_kernel_registration()
806880
test_single_xnnpack_delegate()
807881
test_cpp_consumer(work_dir)
882+
test_documented_example_compiles(work_dir)
808883
test_component_targets_link(work_dir)

docs/source/using-executorch-cpp.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ build:
7979
#include <executorch/extension/module/module.h>
8080
#include <executorch/extension/tensor/tensor.h>
8181
82+
#include <cstdio>
83+
#include <vector>
84+
8285
using namespace executorch::extension;
8386
8487
int main() {

0 commit comments

Comments
 (0)