@@ -10,6 +10,7 @@ import (
10
10
"fmt"
11
11
"strconv"
12
12
"strings"
13
+ "sync"
13
14
"time"
14
15
15
16
ctrplatforms "github.com/containerd/containerd/platforms"
@@ -48,15 +49,81 @@ type platformContext struct {
48
49
options environment.Options
49
50
}
50
51
52
+ type platformContextCache struct { //nolint:govet
53
+ mu sync.Mutex
54
+ cache map [string ]platformContext
55
+
56
+ baseOptions environment.Options
57
+ exportMap bool
58
+ c client.Client
59
+ }
60
+
61
+ func newPlatformContextCache (baseOptions environment.Options , exportMap bool , c client.Client ) * platformContextCache {
62
+ return & platformContextCache {
63
+ cache : make (map [string ]platformContext ),
64
+
65
+ baseOptions : baseOptions ,
66
+ exportMap : exportMap ,
67
+ c : c ,
68
+ }
69
+ }
70
+
71
+ func (cache * platformContextCache ) get (ctx context.Context , platform environment.Platform ) (platformContext , error ) {
72
+ cache .mu .Lock ()
73
+ defer cache .mu .Unlock ()
74
+
75
+ if pc , ok := cache .cache [platform .ID ]; ok {
76
+ return pc , nil
77
+ }
78
+
79
+ options := cache .baseOptions
80
+ options .BuildPlatform = platform
81
+ options .TargetPlatform = platform
82
+
83
+ if cache .exportMap {
84
+ options .CommonPrefix = fmt .Sprintf ("%s " , platform .ID )
85
+ }
86
+
87
+ pkgRef , err := fetchPkgs (ctx , cache .c )
88
+ if err != nil {
89
+ return platformContext {}, fmt .Errorf ("error loading packages for %s: %w" , platform , err )
90
+ }
91
+
92
+ opts := cache .c .BuildOpts ().Opts
93
+
94
+ buildContext := options .GetVariables ().Copy ()
95
+ // push build arguments as `BUILD_ARGS_` prefixed variables
96
+ buildContext .Merge (prefix (filter (opts , buildArgPrefix ), "BUILD_ARG_" ))
97
+
98
+ loader := solver.BuildkitFrontendLoader {
99
+ Context : buildContext ,
100
+ Ref : pkgRef ,
101
+ Ctx : ctx ,
102
+ }
103
+
104
+ packages , err := solver .NewPackages (& loader )
105
+ if err != nil {
106
+ return platformContext {}, fmt .Errorf ("error loading packages for %s: %w" , platform , err )
107
+ }
108
+
109
+ cache .cache [platform .ID ] = platformContext {
110
+ options : options ,
111
+ packages : packages ,
112
+ }
113
+
114
+ return cache .cache [platform .ID ], nil
115
+ }
116
+
51
117
func solveTarget (
52
- platformContexts map [ string ] platformContext , c client.Client , cacheImports []client.CacheOptionsEntry ,
118
+ platformContextCache * platformContextCache , c client.Client , cacheImports []client.CacheOptionsEntry ,
53
119
) func (ctx context.Context , platform environment.Platform , target string ) (* client.Result , error ) {
54
120
return func (ctx context.Context , platform environment.Platform , target string ) (* client.Result , error ) {
55
- if _ , ok := platformContexts [platform .ID ]; ! ok {
56
- return nil , fmt .Errorf ("platform %s not found" , platform )
121
+ platformContext , err := platformContextCache .get (ctx , platform )
122
+ if err != nil {
123
+ return nil , fmt .Errorf ("failed to get platform context for %s: %w" , platform , err )
57
124
}
58
125
59
- options , packages := platformContexts [ platform . ID ]. options , platformContexts [ platform . ID ] .packages
126
+ options , packages := platformContext . options , platformContext .packages
60
127
61
128
if target == "" {
62
129
target = options .Target
@@ -67,7 +134,7 @@ func solveTarget(
67
134
return nil , fmt .Errorf ("failed to resolve packages for platform %s and target %s: %w" , platform , target , err )
68
135
}
69
136
70
- def , err := convert .MarshalLLB (ctx , graph , solveTarget (platformContexts , c , cacheImports ), & options )
137
+ def , err := convert .MarshalLLB (ctx , graph , solveTarget (platformContextCache , c , cacheImports ), & options )
71
138
if err != nil {
72
139
return nil , fmt .Errorf ("failed to marshal LLB for platform %s and target %s: %w" , platform , target , err )
73
140
}
@@ -175,44 +242,8 @@ func Build(ctx context.Context, c client.Client, options *environment.Options) (
175
242
}
176
243
177
244
// prepare platform contexts
178
- platformContexts := make (map [string ]platformContext , len (platforms ))
179
-
180
- for _ , platform := range platforms {
181
- options := * options
182
- options .BuildPlatform = platform
183
- options .TargetPlatform = platform
184
-
185
- if exportMap {
186
- options .CommonPrefix = fmt .Sprintf ("%s " , platform .ID )
187
- }
188
-
189
- pkgRef , err := fetchPkgs (ctx , c )
190
- if err != nil {
191
- return nil , fmt .Errorf ("error loading packages for %s: %w" , platform , err )
192
- }
193
-
194
- buildContext := options .GetVariables ().Copy ()
195
- // push build arguments as `BUILD_ARGS_` prefixed variables
196
- buildContext .Merge (prefix (filter (opts , buildArgPrefix ), "BUILD_ARG_" ))
197
-
198
- loader := solver.BuildkitFrontendLoader {
199
- Context : buildContext ,
200
- Ref : pkgRef ,
201
- Ctx : ctx ,
202
- }
203
-
204
- packages , err := solver .NewPackages (& loader )
205
- if err != nil {
206
- return nil , fmt .Errorf ("error loading packages for %s: %w" , platform , err )
207
- }
208
-
209
- platformContexts [platform .ID ] = platformContext {
210
- options : options ,
211
- packages : packages ,
212
- }
213
- }
214
-
215
- solveTarget := solveTarget (platformContexts , c , cacheImports )
245
+ platformContextCache := newPlatformContextCache (* options , exportMap , c )
246
+ solveTarget := solveTarget (platformContextCache , c , cacheImports )
216
247
217
248
var eg * errgroup.Group
218
249
eg , ctx = errgroup .WithContext (ctx )
@@ -232,6 +263,11 @@ func Build(ctx context.Context, c client.Client, options *environment.Options) (
232
263
return err
233
264
}
234
265
266
+ platformContext , err := platformContextCache .get (ctx , platform )
267
+ if err != nil {
268
+ return fmt .Errorf ("failed to get platform context for %s: %w" , platform , err )
269
+ }
270
+
235
271
img := image.Image {
236
272
Image : specs.Image {
237
273
Platform : specs.Platform {
@@ -245,7 +281,7 @@ func Build(ctx context.Context, c client.Client, options *environment.Options) (
245
281
},
246
282
Config : image.ImageConfig {
247
283
ImageConfig : specs.ImageConfig {
248
- Labels : platformContexts [ platform . ID ] .packages .ImageLabels (),
284
+ Labels : platformContext .packages .ImageLabels (),
249
285
},
250
286
},
251
287
}
0 commit comments