@@ -209,8 +209,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
209
209
// Add jobs to compile each package.
210
210
// Packages that have a cache hit will not be compiled again.
211
211
var packageJobs []* compileJob
212
- packageBitcodePaths := make (map [string ]string )
213
- packageActionIDs := make (map [string ]string )
212
+ packageActionIDJobs := make (map [string ]* compileJob )
214
213
215
214
if config .Options .GlobalValues ["runtime" ]["buildVersion" ] == "" {
216
215
version := goenv .Version
@@ -235,52 +234,68 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
235
234
}
236
235
sort .Strings (undefinedGlobals )
237
236
238
- // Create a cache key: a hash from the action ID below that contains all
239
- // the parameters for the build.
240
- actionID := packageAction {
241
- ImportPath : pkg .ImportPath ,
242
- CompilerBuildID : string (compilerBuildID ),
243
- TinyGoVersion : goenv .Version ,
244
- LLVMVersion : llvm .Version ,
245
- Config : compilerConfig ,
246
- CFlags : pkg .CFlags ,
247
- FileHashes : make (map [string ]string , len (pkg .FileHashes )),
248
- Imports : make (map [string ]string , len (pkg .Pkg .Imports ())),
249
- OptLevel : optLevel ,
250
- SizeLevel : sizeLevel ,
251
- UndefinedGlobals : undefinedGlobals ,
252
- }
253
- for filePath , hash := range pkg .FileHashes {
254
- actionID .FileHashes [filePath ] = hex .EncodeToString (hash )
255
- }
237
+ // Action ID jobs need to know the action ID of all the jobs the package
238
+ // imports.
239
+ var importedPackages []* compileJob
256
240
for _ , imported := range pkg .Pkg .Imports () {
257
- hash , ok := packageActionIDs [imported .Path ()]
241
+ job , ok := packageActionIDJobs [imported .Path ()]
258
242
if ! ok {
259
243
return fmt .Errorf ("package %s imports %s but couldn't find dependency" , pkg .ImportPath , imported .Path ())
260
244
}
261
- actionID .Imports [imported .Path ()] = hash
262
- }
263
- buf , err := json .Marshal (actionID )
264
- if err != nil {
265
- panic (err ) // shouldn't happen
245
+ importedPackages = append (importedPackages , job )
266
246
}
267
- hash := sha512 .Sum512_224 (buf )
268
- packageActionIDs [pkg .ImportPath ] = hex .EncodeToString (hash [:])
269
247
270
- // Determine the path of the bitcode file (which is a serialized version
271
- // of a LLVM module).
272
- bitcodePath := filepath .Join (cacheDir , "pkg-" + hex .EncodeToString (hash [:])+ ".bc" )
273
- packageBitcodePaths [pkg .ImportPath ] = bitcodePath
248
+ // Create a job that will calculate the action ID for a package compile
249
+ // job. The action ID is the cache key that is used for caching this
250
+ // package.
251
+ packageActionIDJob := & compileJob {
252
+ description : "calculate cache key for package " + pkg .ImportPath ,
253
+ dependencies : importedPackages ,
254
+ run : func (job * compileJob ) error {
255
+ // Create a cache key: a hash from the action ID below that contains all
256
+ // the parameters for the build.
257
+ actionID := packageAction {
258
+ ImportPath : pkg .ImportPath ,
259
+ CompilerBuildID : string (compilerBuildID ),
260
+ TinyGoVersion : goenv .Version ,
261
+ LLVMVersion : llvm .Version ,
262
+ Config : compilerConfig ,
263
+ CFlags : pkg .CFlags ,
264
+ FileHashes : make (map [string ]string , len (pkg .FileHashes )),
265
+ Imports : make (map [string ]string , len (pkg .Pkg .Imports ())),
266
+ OptLevel : optLevel ,
267
+ SizeLevel : sizeLevel ,
268
+ UndefinedGlobals : undefinedGlobals ,
269
+ }
270
+ for filePath , hash := range pkg .FileHashes {
271
+ actionID .FileHashes [filePath ] = hex .EncodeToString (hash )
272
+ }
273
+ for i , imported := range pkg .Pkg .Imports () {
274
+ actionID .Imports [imported .Path ()] = importedPackages [i ].result
275
+ }
276
+ buf , err := json .Marshal (actionID )
277
+ if err != nil {
278
+ return err // shouldn't happen
279
+ }
280
+ hash := sha512 .Sum512_224 (buf )
281
+ job .result = hex .EncodeToString (hash [:])
282
+ return nil
283
+ },
284
+ }
285
+ packageActionIDJobs [pkg .ImportPath ] = packageActionIDJob
274
286
275
- // The package has not yet been compiled, so create a job to do so.
287
+ // Now create the job to actually build the package. It will exit early
288
+ // if the package is already compiled.
276
289
job := & compileJob {
277
- description : "compile package " + pkg .ImportPath ,
278
- run : func (* compileJob ) error {
290
+ description : "compile package " + pkg .ImportPath ,
291
+ dependencies : []* compileJob {packageActionIDJob },
292
+ run : func (job * compileJob ) error {
293
+ job .result = filepath .Join (cacheDir , "pkg-" + packageActionIDJob .result + ".bc" )
279
294
// Acquire a lock (if supported).
280
- unlock := lock (bitcodePath + ".lock" )
295
+ unlock := lock (job . result + ".lock" )
281
296
defer unlock ()
282
297
283
- if _ , err := os .Stat (bitcodePath ); err == nil {
298
+ if _ , err := os .Stat (job . result ); err == nil {
284
299
// Already cached, don't recreate this package.
285
300
return nil
286
301
}
@@ -401,7 +416,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
401
416
// Write to a temporary path that is renamed to the destination
402
417
// file to avoid race conditions with other TinyGo invocatiosn
403
418
// that might also be compiling this package at the same time.
404
- f , err := ioutil .TempFile (filepath .Dir (bitcodePath ), filepath .Base (bitcodePath ))
419
+ f , err := ioutil .TempFile (filepath .Dir (job . result ), filepath .Base (job . result ))
405
420
if err != nil {
406
421
return err
407
422
}
@@ -421,13 +436,13 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
421
436
if err != nil {
422
437
// WriteBitcodeToFile doesn't produce a useful error on its
423
438
// own, so create a somewhat useful error message here.
424
- return fmt .Errorf ("failed to write bitcode for package %s to file %s" , pkg .ImportPath , bitcodePath )
439
+ return fmt .Errorf ("failed to write bitcode for package %s to file %s" , pkg .ImportPath , job . result )
425
440
}
426
441
err = f .Close ()
427
442
if err != nil {
428
443
return err
429
444
}
430
- return os .Rename (f .Name (), bitcodePath )
445
+ return os .Rename (f .Name (), job . result )
431
446
},
432
447
}
433
448
packageJobs = append (packageJobs , job )
@@ -451,8 +466,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
451
466
// anything, it only links the bitcode files together.
452
467
ctx := llvm .NewContext ()
453
468
mod = ctx .NewModule ("main" )
454
- for _ , pkg := range lprogram . Sorted () {
455
- pkgMod , err := ctx .ParseBitcodeFile (packageBitcodePaths [ pkg . ImportPath ] )
469
+ for _ , pkgJob := range packageJobs {
470
+ pkgMod , err := ctx .ParseBitcodeFile (pkgJob . result )
456
471
if err != nil {
457
472
return fmt .Errorf ("failed to load bitcode file: %w" , err )
458
473
}
0 commit comments