package registry import ( "fmt" "os" "path/filepath" "strings" ) // emitModuleVersionHeader writes /version_generated.h for a module. // The header exposes constants the C++ side can read: // // FN_MODULE__VERSION (const char*) // FN_MODULE__NAME (const char*) // FN_MODULE__DESCRIPTION (const char*) // // For C++ modules only (lang == "cpp"). For other langs, returns nil silently. // Idempotent: only rewrites when content differs. func emitModuleVersionHeader(m *Module, root string) error { if m.Lang != "cpp" { return nil } if m.DirPath == "" { return nil } upper := strings.ToUpper(m.Name) macroPrefix := "FN_MODULE_" + upper guard := macroPrefix + "_VERSION_GENERATED_H" body := fmt.Sprintf(`// Auto-generated by `+"`fn index`"+` — do not edit. // Module: %s // Source of truth: modules/%s/module.md #ifndef %s #define %s #define %s_NAME %q #define %s_VERSION %q #define %s_DESCRIPTION %q #endif // %s `, m.Name, m.Name, guard, guard, macroPrefix, m.Name, macroPrefix, m.Version, macroPrefix, m.Description, guard) headerPath := filepath.Join(root, m.DirPath, "version_generated.h") // Idempotent: skip write when content already matches. if existing, err := os.ReadFile(headerPath); err == nil && string(existing) == body { return nil } if err := os.MkdirAll(filepath.Dir(headerPath), 0o755); err != nil { return fmt.Errorf("mkdir %s: %w", filepath.Dir(headerPath), err) } return os.WriteFile(headerPath, []byte(body), 0o644) }