diff --git a/newt/builder/build.go b/newt/builder/build.go index 6ce3fb4cee..2c868961d0 100644 --- a/newt/builder/build.go +++ b/newt/builder/build.go @@ -26,6 +26,7 @@ import ( "os" "path/filepath" "runtime" + "strings" log "github.com/sirupsen/logrus" @@ -410,8 +411,15 @@ func (b *Builder) createArchive(c *toolchain.Compiler, // Create a static library ("archive"). c.SetSrcDir(bpkg.rpkg.Lpkg.RelativePath()) - archiveFile := b.ArchivePath(bpkg) - if err := c.CompileArchive(archiveFile); err != nil { + outputFile := b.ArchivePath(bpkg) + ci, err := bpkg.CompilerInfo(b) + if err != nil { + return err + } + if ci.WholeArch { + outputFile = strings.TrimSuffix(outputFile, ".a") + ".list" + } + if err := c.CompileArchive(outputFile, ci.WholeArch); err != nil { return err } @@ -454,6 +462,7 @@ func (b *Builder) link(elfName string, linkerScripts []string, // Calculate the list of directories containing source .a files. var dirs []string staticLibs := []util.StaticLib{} + var extension string for _, bpkg := range b.sortedBuildPackages() { @@ -466,8 +475,13 @@ func (b *Builder) link(elfName string, linkerScripts []string, } c.AddInfo(&toolchain.CompilerInfo{Lflags: ci.Lflags}) - fullANames, _ := filepath.Glob(b.PkgBinDir(bpkg) + "/*.a") - for _, archiveName := range fullANames { + if ci.WholeArch { + extension = "/*.list" + } else { + extension = "/*.a" + } + fullNames, _ := filepath.Glob(b.PkgBinDir(bpkg) + extension) + for _, archiveName := range fullNames { s := util.NewStaticLib(archiveName, ci.WholeArch) staticLibs = append(staticLibs, s) } diff --git a/newt/toolchain/compiler.go b/newt/toolchain/compiler.go index f84e16ed6b..0cc42a7b6e 100644 --- a/newt/toolchain/compiler.go +++ b/newt/toolchain/compiler.go @@ -1034,12 +1034,10 @@ func (c *Compiler) CompileBinaryCmd(dstFile string, options map[string]bool, } for _, lib := range libList { - if lib.WholeArch { - cmd = append(cmd, "-Wl,--whole-archive") - } - cmd = append(cmd, lib.File) - if lib.WholeArch { - cmd = append(cmd, "-Wl,--no-whole-archive") + if lib.IsObjList { + cmd = append(cmd, "@"+lib.File) + } else { + cmd = append(cmd, lib.File) } } if c.ldResolveCircularDeps { @@ -1387,17 +1385,21 @@ func (c *Compiler) BuildSplitArchiveCmd(archiveFile string) string { return str } -// Archives the specified static library. +// Archives the specified static library or creates file with list of +// object files. // -// @param archiveFile The filename of the library to archive. -// @param objFiles An array of the source .o filenames. -func (c *Compiler) CompileArchive(archiveFile string) error { +// @param outputFile The filename of the library to archive. +// @param createList If true archive will not be compiled. Instead +// the file with list of all paths to object files +// from the library will be created, which later +// can be passed with @ to the linker. +func (c *Compiler) CompileArchive(outputFile string, createList bool) error { objFiles := []string{} // Make sure the compiler package info is added to the global set. c.ensureLclInfoAdded() - arRequired, err := c.depTracker.ArchiveRequired(archiveFile, objFiles) + arRequired, err := c.depTracker.ArchiveRequired(outputFile, objFiles) if err != nil { return err } @@ -1405,7 +1407,7 @@ func (c *Compiler) CompileArchive(archiveFile string) error { return nil } - if err := os.MkdirAll(filepath.Dir(archiveFile), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(outputFile), 0755); err != nil { return util.NewNewtError(err.Error()) } @@ -1416,25 +1418,41 @@ func (c *Compiler) CompileArchive(archiveFile string) error { if len(objList) == 0 { util.StatusMessage(util.VERBOSITY_VERBOSE, - "Not archiving %s; no object files\n", archiveFile) + "Not archiving %s; no object files\n", outputFile) return nil } util.StatusMessage(util.VERBOSITY_DEFAULT, "Archiving %s", - path.Base(archiveFile)) + path.Base(outputFile)) util.StatusMessage(util.VERBOSITY_VERBOSE, " with object files %s", strings.Join(objList, " ")) util.StatusMessage(util.VERBOSITY_DEFAULT, "\n") // Delete the old archive, if it exists. - err = os.Remove(archiveFile) + err = os.Remove(outputFile) if err != nil && !os.IsNotExist(err) { return util.NewNewtError(err.Error()) } - fullCmd := c.CompileArchiveCmd(archiveFile, objFiles) + if createList { + file, err := os.Create(outputFile) + if err != nil { + return util.NewNewtError(err.Error()) + } + + for _, objFilePath := range objList { + _, err = file.WriteString(objFilePath + "\n") + if err != nil { + return util.NewNewtError(err.Error()) + } + } + + return nil + } + + fullCmd := c.CompileArchiveCmd(outputFile, objFiles) - cmdSafe := c.CompileArchiveCmdSafe(archiveFile, objFiles) + cmdSafe := c.CompileArchiveCmdSafe(outputFile, objFiles) for _, cmd := range cmdSafe { o, err := util.ShellCommand(cmd, nil) if err != nil { @@ -1443,7 +1461,7 @@ func (c *Compiler) CompileArchive(archiveFile string) error { util.StatusMessage(util.VERBOSITY_DEFAULT, "%s", string(o)) } - err = writeCommandFile(archiveFile, fullCmd) + err = writeCommandFile(outputFile, fullCmd) if err != nil { return err } diff --git a/util/util.go b/util/util.go index 5ab9ac1ba2..727f349e31 100644 --- a/util/util.go +++ b/util/util.go @@ -74,13 +74,13 @@ const ( type StaticLib struct { File string - WholeArch bool + IsObjList bool } -func NewStaticLib(file string, wholeArch bool) StaticLib { +func NewStaticLib(file string, isObjList bool) StaticLib { s := StaticLib{ File: file, - WholeArch: wholeArch, + IsObjList: isObjList, } return s }