Skip to content

Commit 9dd249a

Browse files
aykevldeadprogram
authored andcommitted
builder: refactor package compile job
This commit moves the calculation of the package action ID (cache key) into a separate job. At the moment, this won't have a big effect but this change is necessary for some future changes I want to make.
1 parent 777d3f3 commit 9dd249a

File tree

1 file changed

+57
-42
lines changed

1 file changed

+57
-42
lines changed

builder/build.go

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
209209
// Add jobs to compile each package.
210210
// Packages that have a cache hit will not be compiled again.
211211
var packageJobs []*compileJob
212-
packageBitcodePaths := make(map[string]string)
213-
packageActionIDs := make(map[string]string)
212+
packageActionIDJobs := make(map[string]*compileJob)
214213

215214
if config.Options.GlobalValues["runtime"]["buildVersion"] == "" {
216215
version := goenv.Version
@@ -235,52 +234,68 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
235234
}
236235
sort.Strings(undefinedGlobals)
237236

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
256240
for _, imported := range pkg.Pkg.Imports() {
257-
hash, ok := packageActionIDs[imported.Path()]
241+
job, ok := packageActionIDJobs[imported.Path()]
258242
if !ok {
259243
return fmt.Errorf("package %s imports %s but couldn't find dependency", pkg.ImportPath, imported.Path())
260244
}
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)
266246
}
267-
hash := sha512.Sum512_224(buf)
268-
packageActionIDs[pkg.ImportPath] = hex.EncodeToString(hash[:])
269247

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
274286

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.
276289
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")
279294
// Acquire a lock (if supported).
280-
unlock := lock(bitcodePath + ".lock")
295+
unlock := lock(job.result + ".lock")
281296
defer unlock()
282297

283-
if _, err := os.Stat(bitcodePath); err == nil {
298+
if _, err := os.Stat(job.result); err == nil {
284299
// Already cached, don't recreate this package.
285300
return nil
286301
}
@@ -401,7 +416,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
401416
// Write to a temporary path that is renamed to the destination
402417
// file to avoid race conditions with other TinyGo invocatiosn
403418
// 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))
405420
if err != nil {
406421
return err
407422
}
@@ -421,13 +436,13 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
421436
if err != nil {
422437
// WriteBitcodeToFile doesn't produce a useful error on its
423438
// 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)
425440
}
426441
err = f.Close()
427442
if err != nil {
428443
return err
429444
}
430-
return os.Rename(f.Name(), bitcodePath)
445+
return os.Rename(f.Name(), job.result)
431446
},
432447
}
433448
packageJobs = append(packageJobs, job)
@@ -451,8 +466,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
451466
// anything, it only links the bitcode files together.
452467
ctx := llvm.NewContext()
453468
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)
456471
if err != nil {
457472
return fmt.Errorf("failed to load bitcode file: %w", err)
458473
}

0 commit comments

Comments
 (0)