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.
Этот коммит содержится в:
		
							родитель
							
								
									777d3f3ea5
								
							
						
					
					
						коммит
						9dd249a431
					
				
					 1 изменённых файлов: 57 добавлений и 42 удалений
				
			
		| 
						 | 
					@ -209,8 +209,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
	// Add jobs to compile each package.
 | 
						// Add jobs to compile each package.
 | 
				
			||||||
	// Packages that have a cache hit will not be compiled again.
 | 
						// Packages that have a cache hit will not be compiled again.
 | 
				
			||||||
	var packageJobs []*compileJob
 | 
						var packageJobs []*compileJob
 | 
				
			||||||
	packageBitcodePaths := make(map[string]string)
 | 
						packageActionIDJobs := make(map[string]*compileJob)
 | 
				
			||||||
	packageActionIDs := make(map[string]string)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if config.Options.GlobalValues["runtime"]["buildVersion"] == "" {
 | 
						if config.Options.GlobalValues["runtime"]["buildVersion"] == "" {
 | 
				
			||||||
		version := goenv.Version
 | 
							version := goenv.Version
 | 
				
			||||||
| 
						 | 
					@ -235,52 +234,68 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		sort.Strings(undefinedGlobals)
 | 
							sort.Strings(undefinedGlobals)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Create a cache key: a hash from the action ID below that contains all
 | 
							// Action ID jobs need to know the action ID of all the jobs the package
 | 
				
			||||||
		// the parameters for the build.
 | 
							// imports.
 | 
				
			||||||
		actionID := packageAction{
 | 
							var importedPackages []*compileJob
 | 
				
			||||||
			ImportPath:       pkg.ImportPath,
 | 
					 | 
				
			||||||
			CompilerBuildID:  string(compilerBuildID),
 | 
					 | 
				
			||||||
			TinyGoVersion:    goenv.Version,
 | 
					 | 
				
			||||||
			LLVMVersion:      llvm.Version,
 | 
					 | 
				
			||||||
			Config:           compilerConfig,
 | 
					 | 
				
			||||||
			CFlags:           pkg.CFlags,
 | 
					 | 
				
			||||||
			FileHashes:       make(map[string]string, len(pkg.FileHashes)),
 | 
					 | 
				
			||||||
			Imports:          make(map[string]string, len(pkg.Pkg.Imports())),
 | 
					 | 
				
			||||||
			OptLevel:         optLevel,
 | 
					 | 
				
			||||||
			SizeLevel:        sizeLevel,
 | 
					 | 
				
			||||||
			UndefinedGlobals: undefinedGlobals,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for filePath, hash := range pkg.FileHashes {
 | 
					 | 
				
			||||||
			actionID.FileHashes[filePath] = hex.EncodeToString(hash)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, imported := range pkg.Pkg.Imports() {
 | 
							for _, imported := range pkg.Pkg.Imports() {
 | 
				
			||||||
			hash, ok := packageActionIDs[imported.Path()]
 | 
								job, ok := packageActionIDJobs[imported.Path()]
 | 
				
			||||||
			if !ok {
 | 
								if !ok {
 | 
				
			||||||
				return fmt.Errorf("package %s imports %s but couldn't find dependency", pkg.ImportPath, imported.Path())
 | 
									return fmt.Errorf("package %s imports %s but couldn't find dependency", pkg.ImportPath, imported.Path())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			actionID.Imports[imported.Path()] = hash
 | 
								importedPackages = append(importedPackages, job)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		buf, err := json.Marshal(actionID)
 | 
					
 | 
				
			||||||
		if err != nil {
 | 
							// Create a job that will calculate the action ID for a package compile
 | 
				
			||||||
			panic(err) // shouldn't happen
 | 
							// job. The action ID is the cache key that is used for caching this
 | 
				
			||||||
 | 
							// package.
 | 
				
			||||||
 | 
							packageActionIDJob := &compileJob{
 | 
				
			||||||
 | 
								description:  "calculate cache key for package " + pkg.ImportPath,
 | 
				
			||||||
 | 
								dependencies: importedPackages,
 | 
				
			||||||
 | 
								run: func(job *compileJob) error {
 | 
				
			||||||
 | 
									// Create a cache key: a hash from the action ID below that contains all
 | 
				
			||||||
 | 
									// the parameters for the build.
 | 
				
			||||||
 | 
									actionID := packageAction{
 | 
				
			||||||
 | 
										ImportPath:       pkg.ImportPath,
 | 
				
			||||||
 | 
										CompilerBuildID:  string(compilerBuildID),
 | 
				
			||||||
 | 
										TinyGoVersion:    goenv.Version,
 | 
				
			||||||
 | 
										LLVMVersion:      llvm.Version,
 | 
				
			||||||
 | 
										Config:           compilerConfig,
 | 
				
			||||||
 | 
										CFlags:           pkg.CFlags,
 | 
				
			||||||
 | 
										FileHashes:       make(map[string]string, len(pkg.FileHashes)),
 | 
				
			||||||
 | 
										Imports:          make(map[string]string, len(pkg.Pkg.Imports())),
 | 
				
			||||||
 | 
										OptLevel:         optLevel,
 | 
				
			||||||
 | 
										SizeLevel:        sizeLevel,
 | 
				
			||||||
 | 
										UndefinedGlobals: undefinedGlobals,
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for filePath, hash := range pkg.FileHashes {
 | 
				
			||||||
 | 
										actionID.FileHashes[filePath] = hex.EncodeToString(hash)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for i, imported := range pkg.Pkg.Imports() {
 | 
				
			||||||
 | 
										actionID.Imports[imported.Path()] = importedPackages[i].result
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									buf, err := json.Marshal(actionID)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return err // shouldn't happen
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									hash := sha512.Sum512_224(buf)
 | 
				
			||||||
 | 
									job.result = hex.EncodeToString(hash[:])
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		hash := sha512.Sum512_224(buf)
 | 
							packageActionIDJobs[pkg.ImportPath] = packageActionIDJob
 | 
				
			||||||
		packageActionIDs[pkg.ImportPath] = hex.EncodeToString(hash[:])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Determine the path of the bitcode file (which is a serialized version
 | 
							// Now create the job to actually build the package. It will exit early
 | 
				
			||||||
		// of a LLVM module).
 | 
							// if the package is already compiled.
 | 
				
			||||||
		bitcodePath := filepath.Join(cacheDir, "pkg-"+hex.EncodeToString(hash[:])+".bc")
 | 
					 | 
				
			||||||
		packageBitcodePaths[pkg.ImportPath] = bitcodePath
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// The package has not yet been compiled, so create a job to do so.
 | 
					 | 
				
			||||||
		job := &compileJob{
 | 
							job := &compileJob{
 | 
				
			||||||
			description: "compile package " + pkg.ImportPath,
 | 
								description:  "compile package " + pkg.ImportPath,
 | 
				
			||||||
			run: func(*compileJob) error {
 | 
								dependencies: []*compileJob{packageActionIDJob},
 | 
				
			||||||
 | 
								run: func(job *compileJob) error {
 | 
				
			||||||
 | 
									job.result = filepath.Join(cacheDir, "pkg-"+packageActionIDJob.result+".bc")
 | 
				
			||||||
				// Acquire a lock (if supported).
 | 
									// Acquire a lock (if supported).
 | 
				
			||||||
				unlock := lock(bitcodePath + ".lock")
 | 
									unlock := lock(job.result + ".lock")
 | 
				
			||||||
				defer unlock()
 | 
									defer unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if _, err := os.Stat(bitcodePath); err == nil {
 | 
									if _, err := os.Stat(job.result); err == nil {
 | 
				
			||||||
					// Already cached, don't recreate this package.
 | 
										// Already cached, don't recreate this package.
 | 
				
			||||||
					return nil
 | 
										return nil
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -401,7 +416,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
				// Write to a temporary path that is renamed to the destination
 | 
									// Write to a temporary path that is renamed to the destination
 | 
				
			||||||
				// file to avoid race conditions with other TinyGo invocatiosn
 | 
									// file to avoid race conditions with other TinyGo invocatiosn
 | 
				
			||||||
				// that might also be compiling this package at the same time.
 | 
									// that might also be compiling this package at the same time.
 | 
				
			||||||
				f, err := ioutil.TempFile(filepath.Dir(bitcodePath), filepath.Base(bitcodePath))
 | 
									f, err := ioutil.TempFile(filepath.Dir(job.result), filepath.Base(job.result))
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -421,13 +436,13 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					// WriteBitcodeToFile doesn't produce a useful error on its
 | 
										// WriteBitcodeToFile doesn't produce a useful error on its
 | 
				
			||||||
					// own, so create a somewhat useful error message here.
 | 
										// own, so create a somewhat useful error message here.
 | 
				
			||||||
					return fmt.Errorf("failed to write bitcode for package %s to file %s", pkg.ImportPath, bitcodePath)
 | 
										return fmt.Errorf("failed to write bitcode for package %s to file %s", pkg.ImportPath, job.result)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				err = f.Close()
 | 
									err = f.Close()
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return os.Rename(f.Name(), bitcodePath)
 | 
									return os.Rename(f.Name(), job.result)
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		packageJobs = append(packageJobs, job)
 | 
							packageJobs = append(packageJobs, job)
 | 
				
			||||||
| 
						 | 
					@ -451,8 +466,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
 | 
				
			||||||
			// anything, it only links the bitcode files together.
 | 
								// anything, it only links the bitcode files together.
 | 
				
			||||||
			ctx := llvm.NewContext()
 | 
								ctx := llvm.NewContext()
 | 
				
			||||||
			mod = ctx.NewModule("main")
 | 
								mod = ctx.NewModule("main")
 | 
				
			||||||
			for _, pkg := range lprogram.Sorted() {
 | 
								for _, pkgJob := range packageJobs {
 | 
				
			||||||
				pkgMod, err := ctx.ParseBitcodeFile(packageBitcodePaths[pkg.ImportPath])
 | 
									pkgMod, err := ctx.ParseBitcodeFile(pkgJob.result)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					return fmt.Errorf("failed to load bitcode file: %w", err)
 | 
										return fmt.Errorf("failed to load bitcode file: %w", err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче