171 lines
4.9 KiB
Markdown
171 lines
4.9 KiB
Markdown
# SDL3 Header Parser: Dependency Resolution Plan
|
|
|
|
## Problem Statement
|
|
|
|
The generated `gpu.zig` references types from other SDL headers:
|
|
- `FColor` (SDL_pixels.h)
|
|
- `Rect` (SDL_rect.h)
|
|
- `PropertiesID` (SDL_properties.h)
|
|
- `Window` (SDL_video.h - opaque type)
|
|
- `FlipMode` (SDL_surface.h)
|
|
- `GPUShaderFormat` (special case: #define flags)
|
|
|
|
Without these types, the generated code won't compile.
|
|
|
|
## Analysis of SDL Header Structure
|
|
|
|
SDL_gpu.h includes:
|
|
```c
|
|
#include <SDL3/SDL_stdinc.h> // Basic types (Uint32, etc.)
|
|
#include <SDL3/SDL_pixels.h> // SDL_FColor
|
|
#include <SDL3/SDL_properties.h> // SDL_PropertiesID
|
|
#include <SDL3/SDL_rect.h> // SDL_Rect
|
|
#include <SDL3/SDL_surface.h> // SDL_FlipMode
|
|
#include <SDL3/SDL_video.h> // SDL_Window (opaque)
|
|
```
|
|
|
|
## Solution Options
|
|
|
|
### Option 1: Parse Dependencies Recursively (REJECTED - Too Complex)
|
|
- Parse all included headers
|
|
- Build dependency graph
|
|
- Generate all files in correct order
|
|
- **Issues**:
|
|
- SDL has circular dependencies
|
|
- Would need to parse entire SDL API
|
|
- Overkill for our use case
|
|
|
|
### Option 2: Manual Type Imports (REJECTED - Not Maintainable)
|
|
- Manually copy type definitions
|
|
- **Issues**:
|
|
- Not automated
|
|
- Breaks on SDL updates
|
|
- Defeats purpose of parser
|
|
|
|
### Option 3: Hybrid Approach - Parse Referenced Types Only (RECOMMENDED)
|
|
|
|
#### Phase 1: Dependency Detection
|
|
1. Parse target header (e.g., SDL_gpu.h)
|
|
2. Collect all non-GPU SDL types referenced in signatures
|
|
3. Map types to their source headers (from #include directives)
|
|
|
|
#### Phase 2: Selective Type Extraction
|
|
For each dependency header, extract ONLY referenced types:
|
|
- Parse dependency header in "extract mode"
|
|
- Only output declarations that match our needed types
|
|
- Generate minimal `<module>.zig` files (e.g., `pixels.zig`, `rect.zig`)
|
|
|
|
#### Phase 3: Code Generation
|
|
Generate main file with imports:
|
|
```zig
|
|
pub const c = @import("c.zig").c;
|
|
|
|
// Import minimal dependencies
|
|
const pixels = @import("pixels.zig");
|
|
const rect = @import("rect.zig");
|
|
const properties = @import("properties.zig");
|
|
const video = @import("video.zig");
|
|
const surface = @import("surface.zig");
|
|
|
|
// Re-export needed types
|
|
pub const FColor = pixels.FColor;
|
|
pub const Rect = rect.Rect;
|
|
pub const PropertiesID = properties.PropertiesID;
|
|
pub const Window = video.Window;
|
|
pub const FlipMode = surface.FlipMode;
|
|
|
|
// Manual override for #define-based types
|
|
pub const GPUShaderFormat = packed struct(u32) {
|
|
// ... handwritten
|
|
};
|
|
|
|
// Generated GPU declarations follow...
|
|
```
|
|
|
|
## Implementation Plan
|
|
|
|
### Step 1: Add Dependency Analysis
|
|
```zig
|
|
const DependencyInfo = struct {
|
|
types_needed: []const []const u8,
|
|
source_headers: std.StringHashMap([]const u8), // type -> header
|
|
};
|
|
|
|
fn analyzeDependencies(decls: []Declaration) !DependencyInfo {
|
|
// Scan all function signatures for SDL_ types
|
|
// Map types to headers based on SDL conventions
|
|
}
|
|
```
|
|
|
|
### Step 2: Extract Types from Dependencies
|
|
```zig
|
|
fn extractTypesFromHeader(
|
|
header_path: []const u8,
|
|
types_to_extract: []const []const u8,
|
|
) ![]Declaration {
|
|
// Parse dependency header
|
|
// Filter to only needed types
|
|
// Return minimal declaration set
|
|
}
|
|
```
|
|
|
|
### Step 3: Generate Import Structure
|
|
```zig
|
|
fn generateWithDependencies(
|
|
main_decls: []Declaration,
|
|
deps: DependencyInfo,
|
|
output_dir: []const u8,
|
|
) !void {
|
|
// Generate dependency .zig files
|
|
// Generate main file with imports
|
|
}
|
|
```
|
|
|
|
### Step 4: Handle Special Cases
|
|
|
|
**Opaque Types (e.g., Window)**:
|
|
- SDL_Window is `typedef struct SDL_Window SDL_Window;` (forward decl)
|
|
- Generate as: `pub const Window = opaque {};` or `pub const Window = c.SDL_Window;`
|
|
- Decision: Use `c.SDL_Window` for true opaque types
|
|
|
|
**#define Flags (e.g., GPUShaderFormat)**:
|
|
- Cannot be auto-parsed
|
|
- Maintain "overrides" file: `overrides.zig`
|
|
- User can provide manual definitions for unparseable types
|
|
|
|
## File Structure
|
|
|
|
```
|
|
v2/
|
|
├── gpu.zig # Main generated file with imports
|
|
├── pixels.zig # Minimal: FColor only
|
|
├── rect.zig # Minimal: Rect only
|
|
├── properties.zig # Minimal: PropertiesID only
|
|
├── video.zig # Minimal: Window only
|
|
├── surface.zig # Minimal: FlipMode only
|
|
└── overrides.zig # Manual definitions (GPUShaderFormat)
|
|
```
|
|
|
|
## Advantages
|
|
|
|
1. ✅ Automated - no manual copying
|
|
2. ✅ Minimal - only extracts needed types
|
|
3. ✅ Maintainable - regenerate on SDL updates
|
|
4. ✅ Avoids circular dependencies - only extracts leaf types
|
|
5. ✅ Flexible - handles special cases via overrides
|
|
|
|
## Testing Strategy
|
|
|
|
1. Parse SDL_gpu.h → detect dependencies
|
|
2. Parse dependency headers → extract types
|
|
3. Generate all files
|
|
4. Run `zig build` to verify compilation
|
|
5. Compare API compatibility with handwritten version
|
|
|
|
## Future Enhancements
|
|
|
|
- Cache parsed headers to avoid re-parsing
|
|
- Support transitive dependencies (if type A needs type B)
|
|
- Auto-generate overrides file with placeholders
|
|
- Support multiple target headers in one run
|