Documentation
¶
Overview ¶
Package pipeline orchestrates the load and generate phases of the code-generation pipeline.
Loading ¶
LoadAll reads one or more .gometa.json files produced by the scanner and builds a Registry. The registry resolves cross-framework concerns that cannot be determined per-framework in isolation:
- Class ownership: the framework with the fewest non-zero methods for a class name wins ("fewest methods wins" heuristic), preventing re-exported declarations in umbrella headers from stealing ownership.
- Protocol and enum ownership: scored by member count; ties broken by name-prefix match against the framework name.
- Superclass cycle detection: a DFS validates that no class is its own ancestor before generation begins.
Generation ¶
[Generate] consumes a Registry and a [Config] and writes the frameworks/ tree. Before writing it:
- Topologically sorts frameworks by superclass dependency (Kahn's algorithm) so a class's embedding type is always emitted before the class that embeds it.
- Detects import cycles between frameworks and breaks them by substituting unsafe.Pointer for the minimum-weight set of cross-framework type references ([resolveBlockedImports]).
- Removes stale .go and bridge files from the output directory before writing new ones.
The [Config] struct controls output directory, module prefix, verbosity, and which frameworks to include or skip.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EmitObjCClassHierarchy ¶
EmitObjCClassHierarchy reads all .gometa.json files in metadataPaths, derives the canonical superclass and owning framework for every ObjC class, and writes the result to outputPath as a committed Go source file containing ObjCClassSuperclassIndex and ObjCClassFrameworkIndex.
Canonical ownership is determined by "fewest non-zero methods wins" — the same heuristic used by LoadAll. The output carries no darwin build constraint and is the authoritative ObjC class hierarchy for the code generator's inherited-method filter and foreign-extension resolution.
func GenerateBindings ¶
func GenerateBindings(cfg BindingsConfig) error
GenerateBindings writes frameworks/ output plus block and callback trampoline files. Frameworks are emitted in topological dependency order. The frameworks and libraries output directories are wiped before generation so renamed or removed frameworks do not leave stale packages behind.
func GenerateCustom ¶
func GenerateCustom(cfg CustomConfig) error
GenerateCustom writes *_generated.go files for the opinionated/custom layer. Hand-crafted files in the output directories are never deleted.
Types ¶
type BindingsConfig ¶
type BindingsConfig struct {
// Registry is the combined metadata for all frameworks.
Registry *Registry
// FrameworksOutDir is the root output directory for ObjC framework packages.
// Canonical value: <repo-root>/frameworks
FrameworksOutDir string
// LibrariesOutDir is the root output directory for C library packages.
// When non-empty, frameworks with LinkLib set are written here instead of FrameworksOutDir.
// Canonical value: <repo-root>/libraries
LibrariesOutDir string
// SDKPath is the macOS SDK root (e.g. from xcrun --show-sdk-path).
// Used to locate .swiftinterface files for Swift-only frameworks.
SDKPath string
// BlocksDir overrides the output path for bindings/runtime/blocks generated files.
// Defaults to defaultBlocksDir when empty. Tests use this to redirect output
// to a temp directory without altering the canonical repo path.
BlocksDir string
// CallbacksDir overrides the output path for bindings/runtime/callbacks generated files.
// Defaults to defaultCallbacksDir when empty. Tests use this to redirect output
// to a temp directory without altering the canonical repo path.
CallbacksDir string
// Verbose enables diagnostic output for unsafe.Pointer type degradations.
Verbose bool
// Strict returns an error when any type degrades to unsafe.Pointer.
Strict bool
// IsNSStringOverloads enables Go-string convenience overloads for NSString * params.
IsNSStringOverloads bool
// DiagnosticsSink, when non-nil, receives every type-degradation diagnostic
// recorded by the type mapper. The CLI uses this to enforce a committed
// diagnostics baseline.
DiagnosticsSink *[]string
}
BindingsConfig controls raw Go binding generation: frameworks/ output plus the shared block and callback trampoline files in bindings/runtime/blocks and bindings/runtime/callbacks.
type CustomConfig ¶
type CustomConfig struct {
// Registry is the combined metadata for all frameworks.
Registry *Registry
// OutDir is the root output directory for the opinionated/custom layer.
// Canonical value: <repo-root>/opinionated/custom
OutDir string
// Frameworks is an optional filter: when non-empty, only the named frameworks
// are regenerated. Empty means regenerate all frameworks.
Frameworks []string
// Verbose enables diagnostic output.
Verbose bool
}
CustomConfig controls generation of the opinionated/custom layer. Only *_generated.go files are written; hand-crafted files are never touched.
type Registry ¶
type Registry struct {
Frameworks []*macosplatformmetadata.FrameworkMeta
ClassNameIndex map[string]bool // all class names across all loaded frameworks
GenericClasses map[string]bool // classes with ObjC generic params
// GenericParamIndex maps a generic class name to its ordered list of
// ObjC generic type parameter names (e.g. "NSArray" → ["ObjectType"],
// "NSDictionary" → ["KeyType", "ObjectType"]). Used by the bridge emitter
// to substitute placeholders in block-type casts on foreign-extension
// methods (categories defined on classes owned by another framework).
GenericParamIndex map[string][]string
OwnerIndex map[string]string // className → framework name (e.g. "NSString" → "Foundation")
// ProtocolIndex maps protocol name → owning framework (e.g. "NSCopying" → "Foundation").
// Used by the protocol emitter to resolve cross-framework parent protocol embeds.
ProtocolIndex map[string]string
// ProtocolProxyIndex maps protocol name → owning framework for protocols that
// have generated proxy types. Currently mirrors ProtocolIndex (every protocol
// gets a proxy). Used by the type mapper to resolve return-position id<Protocol>
// to *<GoProtoName>Proxy instead of unsafe.Pointer.
ProtocolProxyIndex map[string]string
// EnumIndex maps enum type name → owning framework (e.g. "VZVirtualMachineState" → "Virtualization").
// Used to resolve enum-typed return values that would otherwise fall through to unsafe.Pointer.
EnumIndex map[string]string
// EnumGoTypeIndex maps enum type name → underlying Go integer type (e.g. "int64", "uint64").
// Used by the bridge emitter to produce correct C integer casts for enum-typed arguments.
EnumGoTypeIndex map[string]string
// TypedefIndex maps typedef name → target ObjC qualType, merged across all frameworks.
// e.g. "VZMemorySize" → "NSInteger", "AVMIDINoteDuration" → "double"
// Used by the typemap as a last-resort fallback before degrading to unsafe.Pointer.
TypedefIndex map[string]string
// TypedefOwnerIndex maps typedef name → the framework that defined it
// (e.g. "CFRunLoopRef" → "CoreFoundation"). Used by cycle detection so that
// typedef-based cross-framework references (CF opaque pointers like CFArrayRef)
// contribute import edges, not just class/enum references.
TypedefOwnerIndex map[string]string
// StructIndex maps a struct name (CGSize, CGRect, NSOperatingSystemVersion,
// ether_addr_t, …) to the framework that owns the complete definition.
// Used by the type mapper to resolve value-type struct references as
// `<pkg>.<Name>` (or bare `<Name>` when same-framework) instead of falling
// through to unsafe.Pointer. Population prefers the first metadata entry
// with non-empty fields — forward-declared/placeholder entries from
// transitively-included headers do not claim ownership.
StructIndex map[string]string
// CFTypeIndex maps framework-specific CF opaque typedef names to
// their owning framework. These are CF-style reference types (e.g. CFHostRef,
// CFHTTPMessageRef from CFNetwork) that are defined outside CoreFoundation
// and therefore not in cfTypedefSet. The mapper routes them to
// *<pkgAlias>.TypedefName rather than the corefoundation package.
CFTypeIndex map[string]string
// ClassIndex maps every class name to its full definition across all loaded frameworks.
// Used by the class emitter to walk cross-framework superclass chains when building
// struct embedding hierarchies and value-chain constructors.
ClassIndex map[string]macosplatformmetadata.Class
// ModulePrefix is the Go module path prefix for framework packages,
// e.g. "github.com/deploymenttheory/go-bindings-macosplatform/frameworks".
// Cross-framework import paths are built as ModulePrefix + "/" + pkgName.
ModulePrefix string
}
Registry holds combined metadata from multiple frameworks. It is the single source of truth for cross-framework type resolution: OwnerIndex tells every emitter which Go package owns each ObjC class name, enabling precise import statements rather than unsafe.Pointer fallbacks.
func LoadAll ¶
LoadAll reads one or more .gometa.json files and builds a Registry. paths may be individual .gometa.json files or directories; directories are scanned one level deep for all *.gometa.json files. When a directory contains multiple arch variants, arm64 is preferred.
func (*Registry) SuperclassIndex ¶
SuperclassIndex returns the set of class names that appear as the Super field of at least one other class across all loaded frameworks. This identifies classes that Apple itself subclasses — the population that SubclassSpec targets.