diff --git a/builder/library.go b/builder/library.go index 53ae5d9d6..ca0ff779f 100644 --- a/builder/library.go +++ b/builder/library.go @@ -15,6 +15,9 @@ import ( // Library is a container for information about a single C library, such as a // compiler runtime or libc. +// +// Note: whenever a library gets changed, the version in compileopts/config.go +// probably also needs to be incremented. type Library struct { // The library name, such as compiler-rt or picolibc. name string @@ -50,7 +53,7 @@ type Library struct { // As a side effect, this call creates the library header files if they didn't // exist yet. func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJob, abortLock func(), err error) { - outdir := config.LibcPath(l.name) + outdir := config.LibraryPath(l.name) archiveFilePath := filepath.Join(outdir, "lib.a") // Create a lock on the output (if supported). diff --git a/compileopts/config.go b/compileopts/config.go index 9fa482952..6cc87aabd 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -8,12 +8,23 @@ import ( "os" "path/filepath" "regexp" + "strconv" "strings" "github.com/google/shlex" "github.com/tinygo-org/tinygo/goenv" ) +// Library versions. Whenever an existing library is changed, this number should +// be added/increased so that existing caches are invalidated. +// +// (This is a bit of a layering violation, this should really be part of the +// builder.Library struct but that's hard to do since we want to know the +// library path in advance in several places). +var libVersions = map[string]int{ + "musl": 2, +} + // Config keeps all configuration affecting the build in a single struct. type Config struct { Options *Options @@ -247,9 +258,9 @@ func MuslArchitecture(triple string) string { return CanonicalArchName(triple) } -// LibcPath returns the path to the libc directory. The libc path will be a libc -// path in the cache directory (which might not yet be built). -func (c *Config) LibcPath(name string) string { +// LibraryPath returns the path to the library build directory. The path will be +// a library path in the cache directory (which might not yet be built). +func (c *Config) LibraryPath(name string) string { archname := c.Triple() if c.CPU() != "" { archname += "-" + c.CPU() @@ -265,6 +276,11 @@ func (c *Config) LibcPath(name string) string { archname += "-" + c.Target.Libc } + // Append a version string, if this library has a version. + if v, ok := libVersions[name]; ok { + archname += "-v" + strconv.Itoa(v) + } + // No precompiled library found. Determine the path name that will be used // in the build cache. return filepath.Join(goenv.Get("GOCACHE"), name+"-"+archname) @@ -351,7 +367,7 @@ func (c *Config) LibcCFlags() []string { case "picolibc": root := goenv.Get("TINYGOROOT") picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc") - path := c.LibcPath("picolibc") + path := c.LibraryPath("picolibc") return []string{ "-nostdlibinc", "-isystem", filepath.Join(path, "include"), @@ -361,7 +377,7 @@ func (c *Config) LibcCFlags() []string { } case "musl": root := goenv.Get("TINYGOROOT") - path := c.LibcPath("musl") + path := c.LibraryPath("musl") arch := MuslArchitecture(c.Triple()) return []string{ "-nostdlibinc", @@ -371,7 +387,7 @@ func (c *Config) LibcCFlags() []string { "-isystem", filepath.Join(root, "lib", "musl", "include"), } case "wasi-libc": - path := c.LibcPath("wasi-libc") + path := c.LibraryPath("wasi-libc") return []string{ "-nostdlibinc", "-isystem", filepath.Join(path, "include"), @@ -381,7 +397,7 @@ func (c *Config) LibcCFlags() []string { return nil case "mingw-w64": root := goenv.Get("TINYGOROOT") - path := c.LibcPath("mingw-w64") + path := c.LibraryPath("mingw-w64") return []string{ "-nostdlibinc", "-isystem", filepath.Join(path, "include"),