Add comprehensive target configuration parsing and inheritance system: - Create internal/targets package with config structures - Support JSON configuration loading with inheritance resolution - Implement multi-level inheritance (e.g., rp2040 → cortex-m0plus → cortex-m) - Add 206 target configurations from TinyGo for embedded platforms - Support core fields: name, llvm-target, cpu, features, build-tags, goos, goarch, cflags, ldflags - Provide high-level resolver interface for target lookup - Include comprehensive unit tests with 100% target parsing coverage This foundation enables future -target parameter support for cross-compilation to diverse embedded platforms beyond current GOOS/GOARCH limitations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
package targets
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// Resolver provides high-level interface for target configuration resolution
|
|
type Resolver struct {
|
|
loader *Loader
|
|
}
|
|
|
|
// NewResolver creates a new target resolver
|
|
func NewResolver(targetsDir string) *Resolver {
|
|
return &Resolver{
|
|
loader: NewLoader(targetsDir),
|
|
}
|
|
}
|
|
|
|
// NewDefaultResolver creates a resolver with default targets directory
|
|
func NewDefaultResolver() *Resolver {
|
|
// Assume targets directory is relative to this package
|
|
_, filename, _, _ := runtime.Caller(0)
|
|
projectRoot := filepath.Dir(filepath.Dir(filepath.Dir(filename)))
|
|
targetsDir := filepath.Join(projectRoot, "targets")
|
|
|
|
return NewResolver(targetsDir)
|
|
}
|
|
|
|
// Resolve resolves a target configuration by name
|
|
func (r *Resolver) Resolve(targetName string) (*Config, error) {
|
|
config, err := r.loader.Load(targetName)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to resolve target %s: %w", targetName, err)
|
|
}
|
|
|
|
// Validate required fields
|
|
if err := r.validateConfig(config); err != nil {
|
|
return nil, fmt.Errorf("invalid target config %s: %w", targetName, err)
|
|
}
|
|
|
|
return config, nil
|
|
}
|
|
|
|
// ResolveAll resolves all available target configurations
|
|
func (r *Resolver) ResolveAll() (map[string]*Config, error) {
|
|
return r.loader.LoadAll()
|
|
}
|
|
|
|
// ListAvailableTargets returns a list of all available target names
|
|
func (r *Resolver) ListAvailableTargets() ([]string, error) {
|
|
return r.loader.ListTargets()
|
|
}
|
|
|
|
// validateConfig validates that a resolved config has required fields
|
|
func (r *Resolver) validateConfig(config *Config) error {
|
|
if config.Name == "" {
|
|
return fmt.Errorf("target name is required")
|
|
}
|
|
|
|
// For now, we don't require any specific fields since different targets
|
|
// may have different requirements. This can be extended in the future.
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetTargetsDirectory returns the path to the targets directory
|
|
func (r *Resolver) GetTargetsDirectory() string {
|
|
return r.loader.GetTargetsDir()
|
|
}
|
|
|
|
// HasTarget checks if a target with the given name exists
|
|
func (r *Resolver) HasTarget(name string) bool {
|
|
_, err := r.loader.LoadRaw(name)
|
|
return err == nil
|
|
}
|