diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 2c07148..b3ef61f 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -109,9 +109,6 @@ func parseSuite(path string) *dsl.File { return f } -// runListBuilds prints a JSON array of build names for CI matrix discovery. -// A legacy suite without structured builds reports ["default"] so workflows -// can always iterate `fromJSON` and have exactly one cell. func runListBuilds(args []string) { positional := positionalArgs(args) if len(positional) < 1 { diff --git a/dsl/build.go b/dsl/build.go index 85b42a0..c0c1453 100644 --- a/dsl/build.go +++ b/dsl/build.go @@ -1,8 +1,5 @@ package dsl -// BuildProfile is a named compilation profile. The translator maps it into -// compiler-specific flag sets at execution time (e.g. ProfileRelease → "-O2" -// on gnu-like compilers, "/O2" on msvc). type BuildProfile int const ( @@ -25,7 +22,6 @@ func (p BuildProfile) String() string { } } -// WarningLevel describes how strict the compiler should be about warnings. type WarningLevel int const ( @@ -48,52 +44,32 @@ func (w WarningLevel) String() string { } } -// BuildConfig describes one structured build variant. It is the new-style -// replacement for the free-form `build "shell-string"` field. -// -// A top-level `build_defaults { ... }` in the suite file produces a -// BuildConfig stored on File.BuildDefaults. Each `build "name" { ... }` -// block produces an entry in File.Builds; the effective configuration used -// by the runner is BuildDefaults merged with the named block, then merged -// with the OS-specific override (Linux / Windows / Darwin) when present. -// -// Zero-valued fields inherit from the parent during merge. Slice and map -// fields accumulate rather than replace. type BuildConfig struct { - // Name of the variant. Empty on BuildDefaults and on OS-override sub-blocks. Name string - Language string // e.g. "c", "c++" - Standard string // e.g. "c11", "c++17" - Sources []string // globs, relative to work dir - Includes []string // include search paths - Output string // binary name (OS-specific extension added automatically) + Language string + Standard string + Sources []string + Includes []string + Output string Profile BuildProfile Warnings WarningLevel Sanitize []string - Wrapper string // e.g. "address", "undefined", "thread" + Wrapper string Defines map[string]string - Link []string // libraries to link against (e.g. "pthread", "m") - Extra []string // raw passthrough flags + Link []string + Extra []string - // Filters — empty means "applies to any". A build is skipped at runtime - // if the current OS or compiler is not in the list. - Platforms []string // "linux", "windows", "darwin" - Compilers []string // "gcc", "clang", "msvc" + Platforms []string + Compilers []string - // OS-specific overrides. Only one level of nesting is allowed: these - // sub-configs must not themselves contain Linux/Windows/Darwin blocks. Linux *BuildConfig Windows *BuildConfig Darwin *BuildConfig } -// MergeFrom layers src on top of dst in place. Non-zero scalar fields in src -// overwrite dst; slices and maps accumulate. The Name and OS override fields -// on src are intentionally ignored — merging never copies the hierarchy, -// only the leaves. func (dst *BuildConfig) MergeFrom(src *BuildConfig) { if src == nil { return @@ -135,9 +111,6 @@ func (dst *BuildConfig) MergeFrom(src *BuildConfig) { } } -// Resolve returns the effective BuildConfig for the given OS by merging -// BuildDefaults → this block → the matching OS override. The result is a -// fresh value; the receiver is not mutated. func (b *BuildConfig) Resolve(defaults *BuildConfig, os string) BuildConfig { var out BuildConfig out.MergeFrom(defaults) @@ -158,8 +131,6 @@ func (b *BuildConfig) Resolve(defaults *BuildConfig, os string) BuildConfig { return out } -// AppliesTo reports whether this build should run on (os, compiler). -// An empty Platforms/Compilers list means no filter on that axis. func (b *BuildConfig) AppliesTo(os, compiler string) bool { if len(b.Platforms) > 0 && !contains(b.Platforms, os) { return false diff --git a/runner/runner.go b/runner/runner.go index 1bedfc5..6d33a45 100644 --- a/runner/runner.go +++ b/runner/runner.go @@ -76,9 +76,6 @@ func (r *Runner) Run() *SuiteResult { return result } -// runLegacyBuild handles the classic `build "shell-string"` form. It produces -// a single BuildRun named "default" so that downstream consumers always see -// the same shape. func (r *Runner) runLegacyBuild() *BuildRun { run := &BuildRun{Name: "default"} @@ -100,9 +97,6 @@ func (r *Runner) runLegacyBuild() *BuildRun { return run } -// runStructuredBuilds handles the new DSL form with one or more named builds. -// Each build is resolved against the current OS and toolchain, compiled via -// the structured translator, and then exercised against every group. func (r *Runner) resolveRuntimeToolchain() (Toolchain, string) { goos := runtime.GOOS wanted := os.Getenv("JUDGE_TOOLCHAIN") @@ -125,9 +119,6 @@ func (r *Runner) runStructuredBuilds() []*BuildRun { run := &BuildRun{Name: b.Name, Toolchain: tc.Name} if r.cfg.TargetBuild != "" && r.cfg.TargetBuild != b.Name { - // User asked for a different build. Don't include this one - // in the result at all — discovery via --list-builds is the - // caller's responsibility. continue } @@ -164,8 +155,6 @@ func (r *Runner) runStructuredBuilds() []*BuildRun { return runs } -// runGroups exercises every group/test in the suite against the currently -// selected binary (r.binary) and records the outcome into run. func (r *Runner) runGroups(run *BuildRun) { for _, g := range r.file.Groups { gr := r.runGroup(g) @@ -174,9 +163,6 @@ func (r *Runner) runGroups(run *BuildRun) { } } -// fillBuildError populates a BuildRun with one failing synthetic test per -// group when the build itself failed. This keeps the reported totals at 0 -// and matches the legacy behaviour. func (r *Runner) fillBuildError(run *BuildRun) { run.Groups = r.synthesizeBuildError() } @@ -205,8 +191,6 @@ func (r *Runner) synthesizeBuildError() []*GroupResult { return out } -// legacyBuild runs the free-form shell build command. Kept under the old -// name so reviewers can diff against the previous implementation easily. func (r *Runner) legacyBuild() (string, error) { buildCmd := r.buildCommand() @@ -241,11 +225,7 @@ func (r *Runner) legacyBuild() (string, error) { return out.String(), nil } -// compileStructured compiles one structured build via the translator and -// returns the build log plus the absolute path to the produced binary. -// The compiler is invoked via exec.Command directly — no shell involved. func (r *Runner) compileStructured(name string, cfg dsl.BuildConfig, tc Toolchain) (string, string, error) { - // Expand source globs against the work dir. sources, err := expandSources(r.cfg.WorkDir, cfg.Sources) if err != nil { return "", "", err @@ -255,7 +235,6 @@ func (r *Runner) compileStructured(name string, cfg dsl.BuildConfig, tc Toolchai } cfg.Sources = sources - // Decide output path: /build//[.exe]. outputName := cfg.Output if outputName == "" { outputName = "solution" @@ -298,9 +277,6 @@ func (r *Runner) compileStructured(name string, cfg dsl.BuildConfig, tc Toolchai return logPrefix + out.String(), outputPath, nil } -// expandSources expands each glob in patterns against workDir and returns -// a slice of paths relative to workDir. Globs that match no files cause an -// error — silent zero matches are almost always a typo. func expandSources(workDir string, patterns []string) ([]string, error) { var out []string seen := map[string]bool{} @@ -310,7 +286,6 @@ func expandSources(workDir string, patterns []string) ([]string, error) { return nil, fmt.Errorf("glob %q: %w", pat, err) } if len(matches) == 0 { - // Fall back to treating it as a literal path. if _, statErr := os.Stat(filepath.Join(workDir, pat)); statErr == nil { matches = []string{filepath.Join(workDir, pat)} } else {