5
5
package harnesses
6
6
7
7
import (
8
+ "debug/buildinfo"
8
9
"fmt"
10
+ "go/version"
9
11
"os/exec"
10
12
"path/filepath"
13
+ "strings"
11
14
12
15
"golang.org/x/benchmarks/sweet/common"
13
16
"golang.org/x/benchmarks/sweet/common/fileutil"
@@ -17,6 +20,7 @@ import (
17
20
type buildBenchmark struct {
18
21
name string
19
22
pkg string
23
+ minGo string // skip if toolchain is older than this
20
24
clone func (outDir string ) error
21
25
}
22
26
60
64
// Added for #72815. This codebase has at least a few packages
61
65
// that are difficult for the Go compiler to handle, performance-wise,
62
66
// as of Mar. 13 2025.
63
- name : "tsgo" ,
64
- pkg : "cmd/tsgo" ,
67
+ name : "tsgo" ,
68
+ pkg : "cmd/tsgo" ,
69
+ minGo : "go1.24" ,
65
70
clone : func (outDir string ) error {
66
71
return gitCloneToCommit (
67
72
outDir ,
@@ -85,8 +90,13 @@ func (h GoBuild) CheckPrerequisites() error {
85
90
}
86
91
87
92
func (h GoBuild ) Get (gcfg * common.GetConfig ) error {
93
+ benchmarks , err := goBuildBenchmarks (nil , gcfg .Short )
94
+ if err != nil {
95
+ return fmt .Errorf ("error getting benchmark list: %v" , err )
96
+ }
97
+
88
98
// Clone the sources that we're going to build.
89
- for _ , bench := range goBuildBenchmarks ( gcfg . Short ) {
99
+ for _ , bench := range benchmarks {
90
100
if err := bench .clone (filepath .Join (gcfg .SrcDir , bench .name )); err != nil {
91
101
return err
92
102
}
@@ -98,9 +108,6 @@ func (h GoBuild) Build(pcfg *common.Config, bcfg *common.BuildConfig) error {
98
108
// Local copy of config for updating GOROOT.
99
109
cfg := pcfg .Copy ()
100
110
101
- // Get the benchmarks we're going to build.
102
- benchmarks := goBuildBenchmarks (bcfg .Short )
103
-
104
111
// cfg.GoRoot is our source toolchain. We need to rebuild cmd/compile
105
112
// and cmd/link with cfg.BuildEnv to apply any configured build options
106
113
// (e.g., PGO).
@@ -115,6 +122,12 @@ func (h GoBuild) Build(pcfg *common.Config, bcfg *common.BuildConfig) error {
115
122
return fmt .Errorf ("error building cmd/compile and cmd/link: %v" , err )
116
123
}
117
124
125
+ // Get the benchmarks we're going to build.
126
+ benchmarks , err := goBuildBenchmarks (cfg , bcfg .Short )
127
+ if err != nil {
128
+ return fmt .Errorf ("error getting benchmark list: %v" , err )
129
+ }
130
+
118
131
for _ , bench := range benchmarks {
119
132
// Generate a symlink to the repository and put it in bin.
120
133
// It's not a binary, but it's the only place we can put it
@@ -153,7 +166,11 @@ func (h GoBuild) Run(pcfg *common.Config, rcfg *common.RunConfig) error {
153
166
cfg := pcfg .Copy ()
154
167
cfg .GoRoot = filepath .Join (rcfg .BinDir , "goroot" ) // see Build, above.
155
168
156
- benchmarks := goBuildBenchmarks (rcfg .Short )
169
+ benchmarks , err := goBuildBenchmarks (cfg , rcfg .Short )
170
+ if err != nil {
171
+ return fmt .Errorf ("error getting benchmark list: %v" , err )
172
+ }
173
+
157
174
for _ , bench := range benchmarks {
158
175
cmd := exec .Command (
159
176
filepath .Join (rcfg .BinDir , "go-build-bench" ),
@@ -174,9 +191,41 @@ func (h GoBuild) Run(pcfg *common.Config, rcfg *common.RunConfig) error {
174
191
return nil
175
192
}
176
193
177
- func goBuildBenchmarks (short bool ) []* buildBenchmark {
194
+ // goBuildBenchmarks returns the set of benchmarks to run for this
195
+ // configuration.
196
+ //
197
+ // cfg may be nil if the build configuration isn't known yet. In that case, it
198
+ // returns the set of benchmarks that may run.
199
+ func goBuildBenchmarks (cfg * common.Config , short bool ) ([]* buildBenchmark , error ) {
200
+ var bi * buildinfo.BuildInfo
201
+ if cfg != nil {
202
+ var err error
203
+ bi , err = buildinfo .ReadFile (cfg .GoTool ().Tool )
204
+ if err != nil {
205
+ return nil , fmt .Errorf ("error reading build info from Go toolchain: %v" , err )
206
+ }
207
+
208
+ // NOTE(go.dev/issue/73369): Tip toolchain versions look like
209
+ // "devel go1.25-9ce47e66e8 Wed Mar 26 03:48:50 2025 -0700".
210
+ // This is not a valid go/version version, so it sorts before
211
+ // every valid version. If we strip "devel", then the remainder
212
+ // is valid.
213
+ bi .GoVersion = strings .TrimPrefix (bi .GoVersion , "devel " )
214
+ }
215
+
216
+ base := buildBenchmarks
178
217
if short {
179
- return buildBenchmarksShort
218
+ base = buildBenchmarksShort
180
219
}
181
- return buildBenchmarks
220
+
221
+ var out []* buildBenchmark
222
+ for _ , bench := range base {
223
+ if bench .minGo != "" && bi != nil && version .Compare (bi .GoVersion , bench .minGo ) < 0 {
224
+ log .Printf ("Skipping go-build on %s: toolchain version %s less than required %s" , bench .name , bi .GoVersion , bench .minGo )
225
+ continue
226
+ }
227
+ out = append (out , bench )
228
+ }
229
+
230
+ return out , nil
182
231
}
0 commit comments