diff --git a/.github/workflows/upload_components.yml b/.github/workflows/upload_components.yml index 8da596d36..721b3c85b 100755 --- a/.github/workflows/upload_components.yml +++ b/.github/workflows/upload_components.yml @@ -126,6 +126,7 @@ jobs: components/qmi8658 components/qtpy components/qwiicnes + components/reflect_cpp components/remote_debug components/rmt components/rtps diff --git a/.gitmodules b/.gitmodules index 7817faf37..d562b34f0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,6 @@ [submodule "components/gfps_service/detail/nearby"] path = components/gfps_service/detail/nearby url = https://github.com/esp-cpp/nearby +[submodule "components/reflect_cpp/detail/reflect-cpp"] + path = components/reflect_cpp/detail/reflect-cpp + url = https://github.com/getml/reflect-cpp.git diff --git a/components/reflect_cpp/CMakeLists.txt b/components/reflect_cpp/CMakeLists.txt new file mode 100644 index 000000000..2dffac6d3 --- /dev/null +++ b/components/reflect_cpp/CMakeLists.txt @@ -0,0 +1,5 @@ +# reflect-cpp's core reflection (rfl/to_view.hpp and friends) is header-only; +# the compiled library / bundled yyjson exist only for its JSON backend, which +# nothing here uses — so this component is include-dirs only. +idf_component_register( + INCLUDE_DIRS "detail/reflect-cpp/include") diff --git a/components/reflect_cpp/README.md b/components/reflect_cpp/README.md new file mode 100644 index 000000000..51aba8410 --- /dev/null +++ b/components/reflect_cpp/README.md @@ -0,0 +1,30 @@ +# reflect_cpp + +Vendors [getml/reflect-cpp](https://github.com/getml/reflect-cpp) (pinned to +`v0.25.0` as a git submodule under `detail/`) so espp components can use +compile-time reflection over plain aggregate structs — field iteration in +declaration order plus field names, with no macros and no code generation: + +```cpp +#include + +struct Point { int x; int y; }; + +Point p{1, 2}; +auto view = rfl::to_view(p); +view.apply([](const auto &f) { + // f.name() -> "x" / "y", f.value() -> pointer to the field +}); +``` + +Only the header-only reflection core is exposed (`rfl/to_view.hpp`, +`rfl/fields.hpp`, ...). reflect-cpp's serialization formats (JSON via +yyjson, etc.) are not built and their headers should not be included on +ESP-IDF targets. + +Requires C++20 or newer (ESP-IDF 5.2+ toolchains). The reflection-driven +`cdr` component (stacked follow-up PR) uses this component as its backend. + +When updating the submodule pin, keep it on the same reflect-cpp tag that +[finger563/cdr](https://github.com/finger563/cdr) fetches in its standalone +build (see that repo's `CMakeLists.txt`). diff --git a/components/reflect_cpp/detail/reflect-cpp b/components/reflect_cpp/detail/reflect-cpp new file mode 160000 index 000000000..1327ef1d0 --- /dev/null +++ b/components/reflect_cpp/detail/reflect-cpp @@ -0,0 +1 @@ +Subproject commit 1327ef1d0b403f1424776da4c47bf0c7a6b0feaa diff --git a/components/reflect_cpp/idf_component.yml b/components/reflect_cpp/idf_component.yml new file mode 100644 index 000000000..309510ab1 --- /dev/null +++ b/components/reflect_cpp/idf_component.yml @@ -0,0 +1,16 @@ +## IDF Component Manager Manifest File +license: "MIT" +description: "reflect-cpp compile-time reflection headers (rfl::to_view, field names) vendored for ESP-IDF; reflection core only, no serialization formats." +url: "https://github.com/esp-cpp/espp/tree/main/components/reflect_cpp" +repository: "git://github.com/esp-cpp/espp.git" +maintainers: + - William Emfinger +documentation: "https://esp-cpp.github.io/espp/data/reflect_cpp.html" +tags: + - cpp + - Component + - Reflection + - Serialization +dependencies: + idf: + version: '>=5.2' diff --git a/doc/en/data/index.rst b/doc/en/data/index.rst index 718e94229..7496f3bdc 100644 --- a/doc/en/data/index.rst +++ b/doc/en/data/index.rst @@ -11,4 +11,5 @@ byte-stuffing, CSV, and table formatting. cdr cobs csv + reflect_cpp tabulate diff --git a/doc/en/data/reflect_cpp.rst b/doc/en/data/reflect_cpp.rst new file mode 100644 index 000000000..317168398 --- /dev/null +++ b/doc/en/data/reflect_cpp.rst @@ -0,0 +1,34 @@ +Reflect-C++ (compile-time reflection) +************************************* + +The ``reflect_cpp`` component vendors the reflection core of the third-party +`reflect-cpp `_ library (as a git +submodule under ``detail/``), giving espp components compile-time reflection +over plain aggregate structs — field iteration in declaration order plus field +names, with no macros and no code generation: + +.. code-block:: cpp + + #include + + struct Point { + int x; + int y; + }; + + Point p{1, 2}; + auto view = rfl::to_view(p); + view.apply([](const auto &f) { + // f.name() -> "x" / "y", *f.value() -> the field + }); + +Only the header-only reflection core is exposed (``rfl/to_view.hpp``, +``rfl/fields.hpp``, ...). reflect-cpp's serialization formats (JSON via +yyjson, etc.) are not built and their headers should not be included on +ESP-IDF targets. + +This component is the reflection backend for the reflection-driven ``cdr`` +component (introduced in a follow-up PR), which uses it to have the compiler +generate CDR serialization code directly from struct definitions. + +Requires C++20 or newer (the default on ESP-IDF 5.2+ toolchains). diff --git a/suppressions.txt b/suppressions.txt index 563d866cf..aa6acf791 100644 --- a/suppressions.txt +++ b/suppressions.txt @@ -9,3 +9,4 @@ cstyleCast // Specific suppressions of the form: // [error id]:[filename]:[line] *:lib/* +*:components/reflect_cpp/detail/*