Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 39 additions & 65 deletions builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,18 @@ type BuildResult struct {
// key, avoiding the need for recompiling all dependencies when only the
// implementation of an imported package changes.
type packageAction struct {
ImportPath string
CompilerBuildID string
TinyGoVersion string
LLVMVersion string
Config *compiler.Config
CFlags []string
FileHashes map[string]string // hash of every file that's part of the package
EmbeddedFiles map[string]string // hash of all the //go:embed files in the package
Imports map[string]string // map from imported package to action ID hash
OptLevel string // LLVM optimization level (O0, O1, O2, Os, Oz)
UndefinedGlobals []string // globals that are left as external globals (no initializer)
ImportPath string
CompilerBuildID string
TinyGoVersion string
LLVMVersion string
CCompilerIdentity string
Config *compiler.Config
CFlags []string
FileHashes map[string]string // hash of every file that's part of the package
EmbeddedFiles map[string]string // hash of all the //go:embed files in the package
Imports map[string]string // map from imported package to action ID hash
OptLevel string // LLVM optimization level (O0, O1, O2, Os, Oz)
UndefinedGlobals []string // globals that are left as external globals (no initializer)
}

// Build performs a single package to executable Go build. It takes in a package
Expand Down Expand Up @@ -146,53 +147,33 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
// As a side effect, this also creates the headers for the given libc, if
// the libc needs them.
root := goenv.Get("TINYGOROOT")
libraries, err := configuredLibraries(config)
if err != nil {
return BuildResult{}, err
}
libraryKeys, err := makeLibraryCacheKeys(config, libraries)
if err != nil {
return BuildResult{}, err
}
config.LibraryKeys = libraryKeys
var libcDependencies []*compileJob
switch config.Target.Libc {
case "darwin-libSystem":
if config.Target.Libc == "darwin-libSystem" {
libcJob := makeDarwinLibSystemJob(config, tmpdir)
libcDependencies = append(libcDependencies, libcJob)
case "musl":
var unlock func()
libcJob, unlock, err := libMusl.load(config, tmpdir)
if err != nil {
return BuildResult{}, err
}
defer unlock()
libcDependencies = append(libcDependencies, dummyCompileJob(filepath.Join(filepath.Dir(libcJob.result), "crt1.o")))
libcDependencies = append(libcDependencies, libcJob)
case "picolibc":
libcJob, unlock, err := libPicolibc.load(config, tmpdir)
if err != nil {
return BuildResult{}, err
}
defer unlock()
libcDependencies = append(libcDependencies, libcJob)
case "wasi-libc":
libcJob, unlock, err := libWasiLibc.load(config, tmpdir)
if err != nil {
return BuildResult{}, err
}
defer unlock()
libcDependencies = append(libcDependencies, libcJob)
case "wasmbuiltins":
libcJob, unlock, err := libWasmBuiltins.load(config, tmpdir)
}
if libraries.libc != nil {
libcJob, unlock, err := libraries.libc.load(config, tmpdir)
if err != nil {
return BuildResult{}, err
}
defer unlock()
libcDependencies = append(libcDependencies, libcJob)
case "mingw-w64":
libcJob, unlock, err := libMinGW.load(config, tmpdir)
if err != nil {
return BuildResult{}, err
if libraries.libc.crt1Source != "" {
libcDependencies = append(libcDependencies, dummyCompileJob(filepath.Join(filepath.Dir(libcJob.result), "crt1.o")))
}
defer unlock()
libcDependencies = append(libcDependencies, libcJob)
}
if config.Target.Libc == "mingw-w64" {
libcDependencies = append(libcDependencies, makeMinGWExtraLibs(tmpdir, config.GOARCH())...)
case "":
// no library specified, so nothing to do
default:
return BuildResult{}, fmt.Errorf("unknown libc: %s", config.Target.Libc)
}

optLevel, speedLevel, sizeLevel := config.OptLevel()
Expand Down Expand Up @@ -364,6 +345,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
OptLevel: optLevel,
UndefinedGlobals: undefinedGlobals,
}
if len(pkg.CGoHeaders) != 0 {
compilerID, err := clangCompilerIdentity()
if err != nil {
return err
}
actionID.CCompilerIdentity = compilerID
}
for filePath, hash := range pkg.FileHashes {
actionID.FileHashes[filePath] = hex.EncodeToString(hash)
}
Expand Down Expand Up @@ -413,9 +401,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
}

// Load bitcode of CGo headers and join the modules together.
// This may seem vulnerable to cache problems, but this is not
// the case: the Go code that was just compiled already tracks
// all C files that are read and hashes them.
// These headers could be compiled in parallel but the benefit
// is so small that it's probably not worth parallelizing.
// Packages are compiled independently anyway.
Expand Down Expand Up @@ -734,27 +719,16 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
}
}

// Add compiler-rt dependency if needed. Usually this is a simple load from
// a cache.
if config.Target.RTLib == "compiler-rt" {
job, unlock, err := libCompilerRT.load(config, tmpdir)
// Add library dependencies needed by the linker, usually from the cache.
for _, library := range libraries.linker {
job, unlock, err := library.load(config, tmpdir)
if err != nil {
return result, err
}
defer unlock()
linkerDependencies = append(linkerDependencies, job)
}

// The Boehm collector is stored in a separate C library.
if config.GC() == "boehm" {
job, unlock, err := BoehmGC.load(config, tmpdir)
if err != nil {
return BuildResult{}, err
}
defer unlock()
linkerDependencies = append(linkerDependencies, job)
}

// Add jobs to compile extra files. These files are in C or assembly and
// contain things like the interrupt vector table and low level operations
// such as stack switching.
Expand Down
Loading
Loading