---
name: codegen_app_modules
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: impure
signature: "generate(app_md: Path, modules_root: Path, app_name: str, out_path: Path) -> int"
description: "Reads app.md uses_modules + modules/<name>/module.md frontmatters, emits <app>_modules_generated.cpp with fn::app_modules_array[] + fn::app_modules_count. CMake hook for add_imgui_app. Pure YAML parsing, no registry.db dep."
tags: [codegen, modules, cmake, cpp, build]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports:
  - yaml
example: |
  python python/functions/infra/codegen_app_modules.py \
    --app-md apps/data_factory/app.md \
    --modules-root modules \
    --app-name data_factory \
    --out cpp/build/apps/data_factory/data_factory_modules_generated.cpp
file_path: "python/functions/infra/codegen_app_modules.py"
params:
  - name: app_md
    desc: "Path absoluto al app.md de la app consumidora. Lee uses_modules del frontmatter YAML."
  - name: modules_root
    desc: "Raiz del directorio modules/. Cada modulo es modules/<name>/module.md."
  - name: app_name
    desc: "Nombre de la app (solo para el comment-header del .cpp generado)."
  - name: out_path
    desc: "Path donde escribir el .cpp generado. Idempotente: skip si contenido coincide."
output: "Exit code: 0 si OK, 2 si OK pero algun modulo declarado no existe (warning), >0 si error."
---

## Ejemplo

Generar el .cpp para `data_factory`:

```bash
python python/functions/infra/codegen_app_modules.py \
  --app-md apps/data_factory/app.md \
  --modules-root modules \
  --app-name data_factory \
  --out /tmp/data_factory_modules_generated.cpp
```

Si `data_factory/app.md` declara `uses_modules: [data_table_cpp]`, el .cpp generado es:

```cpp
// Auto-generated by codegen_app_modules.py — do not edit.
// App: data_factory
// Source of truth: apps/data_factory/app.md (uses_modules)

#include "app_modules.h"

namespace fn {
const ModuleInfo app_modules_array[] = {
    { "data_table", "1.4.0", "Reusable C++ ImGui module..." },
};
const unsigned long app_modules_count = 1;
} // namespace fn
```

## Cuando usarla

CMake hook automatico — la macro `add_imgui_app` la invoca al configurar el build. Apps no la llaman manualmente. Manual override: solo si quieres regenerar fuera del flujo cmake (debugging).

## Gotchas

- Resuelve `<name>_cpp` strippeando el sufijo `_cpp/_py/_ts/_bash/_go`. Mismo patron que `GenerateModuleID`.
- Si un modulo declarado en `uses_modules` no existe, emite warning a stderr y EXIT=2 (no falla el build).
- Idempotente: solo reescribe si el contenido cambia. Evita rebuilds innecesarios cuando los modulos no cambiaron.
- Requiere `pyyaml`. Disponible en `python/.venv` del registry.
