# TraxProbe as an ESP-IDF component (ESP32-S3, Xtensa port).
#
# This is the vendored library only — it contains NO application-specific
# files. The user application (the `main` component) provides:
#   - trax_config.h    (TraxProbe configuration)
#   - trax_transport.c (the custom USB-Serial/JTAG transport)
#
# Layout in this component: inc/, src/, config/, debug/, hw_port/, os/, ...
#
# Source selection: every OS port file is wrapped in a TRAX_CFG_RTOS_TYPE
# guard, so it is safe to compile all of os/ — the inactive ports (here
# FreeRTOS kernel tracing) collapse to nothing, and the active one
# (BareMetal, since TRAX_CFG_RTOS_TYPE defaults to NONE) provides the needed
# symbols such as trax_memory_monitor_process(). The transports/ directory is
# intentionally NOT compiled: TRAX_CFG_TRANSPORT is CUSTOM, so main provides
# the transport.

file(GLOB TRAX_SRCS
    "${CMAKE_CURRENT_LIST_DIR}/src/*.c"
    "${CMAKE_CURRENT_LIST_DIR}/debug/*.c"
    "${CMAKE_CURRENT_LIST_DIR}/os/common/*.c"
    "${CMAKE_CURRENT_LIST_DIR}/os/BareMetal/*.c"
    "${CMAKE_CURRENT_LIST_DIR}/os/FreeRTOS/*.c"
)

idf_component_register(
    SRCS
        ${TRAX_SRCS}
        "hw_port/Xtensa/src/trax_hw_port.c"   # required: shared SMP spinlock
        "sdk/esp/trax_esp_trace_adapter.c"    # inert esp_trace "ext"/"none" stubs
    INCLUDE_DIRS
        "inc"   # library headers; config/ and hw_port/ resolve via relative includes
        "sdk/esp"   # esp_trace_freertos_impl.h: FreeRTOS kernel trace-hook entry point
    REQUIRES
        freertos esp_timer   # Xtensa port uses esp_timer + FreeRTOS portMUX
    LDFRAGMENTS
        # Metadata-in-flash placement (TRAX_CFG_META_STORAGE == TRAX_META_IN_FLASH):
        # collects the `.trax_<kind>` records into the MMU-mapped DROM window and
        # provides the __trax_<kind>_start/_end symbols trax_meta_tx.c walks to
        # stream the schema at session start. Inert in ELF-only mode.
        "linker/esp/trax_meta.lf"
    # sdk/esp/trax_esp_trace_adapter.c registers the inert "ext" encoder + "none"
    # transport via ESP_TRACE_REGISTER_{ENCODER,TRANSPORT}(). Those descriptors
    # are referenced only by the linker (esp_trace's linker.lf, archive: *), not
    # by any code, so the object file must be force-linked or it is dropped from
    # the static archive and the esp_trace core aborts at boot. WHOLE_ARCHIVE
    # guarantees it is pulled in (matches esp_trace's own component, which is
    # WHOLE_ARCHIVE for exactly this reason). The inactive os/ ports stay empty
    # under TRAX_CFG_RTOS_TYPE guards, so force-linking adds no live symbols.
    WHOLE_ARCHIVE
)

# The library's headers do #include "trax_config.h", which the application
# owns in main/. We cannot express that with REQUIRES (main already requires
# TraxProbe -> that would be circular), so add main/ to this component's
# include path directly. It is PUBLIC (not PRIVATE) because the FreeRTOS
# trace-hook shim (sdk/esp/esp_trace_freertos_impl.h) is compiled into the kernel
# build, where it pulls in trax.h -> trax_config.h: that search path must reach
# the freertos component too (it rides the esp_trace interface link below).
target_include_directories(${COMPONENT_LIB} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/../../main")

# TraxProbe's generic FreeRTOS port sources (os/FreeRTOS/*.c) use the vanilla
# FreeRTOS include convention (#include "FreeRTOS.h", "task.h") so they stay
# portable across non-ESP FreeRTOS targets. ESP-IDF instead exposes those
# headers under a freertos/ prefix, so the unprefixed form does not resolve out
# of the box. Add the active kernel's include/freertos directory to THIS
# component's private include path so the vendored port files compile unchanged.
# (The Xtensa hw_port already uses the freertos/ prefix and is unaffected.)
idf_component_get_property(freertos_dir freertos COMPONENT_DIR)
if(CONFIG_FREERTOS_SMP)
    set(_trax_freertos_kernel "FreeRTOS-Kernel-SMP")
else()
    set(_trax_freertos_kernel "FreeRTOS-Kernel")
endif()
target_include_directories(${COMPONENT_LIB} PRIVATE
    "${freertos_dir}/${_trax_freertos_kernel}/include/freertos")

# sdk/esp/trax_esp_trace_adapter.c needs esp_trace's public headers
# (esp_trace_registry.h + the port vtable headers) to register the inert
# adapters. Pull the include dir in directly rather than via REQUIRES: the
# top-level CMakeLists already does target_link_libraries(esp_trace INTERFACE
# TraxProbe), so a REQUIRES esp_trace here would form a dependency cycle. We only
# need the headers (the descriptors are consumed by esp_trace at link time, not
# by a link-time symbol dependency), so an include path is sufficient.
idf_component_get_property(esp_trace_dir esp_trace COMPONENT_DIR)
target_include_directories(${COMPONENT_LIB} PRIVATE "${esp_trace_dir}/include")

# NOTE on FreeRTOS kernel tracing (TRAX_CFG_RTOS_TYPE == TRAX_RTOS_FREERTOS):
# ESP-IDF's FreeRTOSConfig.h includes esp_trace_freertos.h (when
# CONFIG_ESP_TRACE_ENABLE), which includes our esp_trace_freertos_impl.h (when
# CONFIG_ESP_TRACE_LIB_EXTERNAL). For the kernel build to find that header -- and
# the trax.h / trax_config.h it pulls in -- this component's PUBLIC include dirs
# (inc/, esp/, main/) must hang off esp_trace's INTERFACE so they reach freertos
# and every TU that includes FreeRTOSConfig.h. That link CANNOT live here:
# component CMakeLists run in name order, and "TraxProbe" is processed before
# "esp_trace", so __idf_esp_trace does not exist yet at this point. It is wired
# instead from the top-level project CMakeLists.txt (after project(), once every
# component target exists). See components/esp_trace/README.md.
