This is an automated email from the ASF dual-hosted git repository.
janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git
The following commit(s) were added to refs/heads/master by this push:
new a798fcc6 Add pkg.whole_archive flag to allow --whole_archive linker
option to be set per package
a798fcc6 is described below
commit a798fcc687dd81857de7bb92e77711c9a74f0692
Author: Jocelyn Masserot <[email protected]>
AuthorDate: Wed Apr 10 15:04:51 2024 +0200
Add pkg.whole_archive flag to allow --whole_archive linker option to be set
per package
Depending on the project, it might be useful to have the ability to link a
package surrounded by
"--whole-archive" and "--no-whole-archive" flags.
---
newt/builder/build.go | 21 ++++++++++++------
newt/builder/buildpackage.go | 10 +++++++++
newt/toolchain/compiler.go | 51 ++++++++++++++++++++++++++++++++------------
newt/toolchain/deps.go | 8 +++++--
util/util.go | 28 ++++++++++++++++++++++++
5 files changed, 95 insertions(+), 23 deletions(-)
diff --git a/newt/builder/build.go b/newt/builder/build.go
index d2fc0c9e..b611df3a 100644
--- a/newt/builder/build.go
+++ b/newt/builder/build.go
@@ -449,8 +449,9 @@ func (b *Builder) link(elfName string, linkerScripts
[]string,
// Calculate the list of directories containing source .a files.
var dirs []string
+ staticLibs := []util.StaticLib{}
+
for _, bpkg := range b.sortedBuildPackages() {
- dirs = append(dirs, b.PkgBinDir(bpkg))
// Collect lflags from all constituent packages. Discard
everything
// from the compiler info except lflags; that is all that is
relevant
@@ -459,18 +460,23 @@ func (b *Builder) link(elfName string, linkerScripts
[]string,
if err != nil {
return err
}
+
c.AddInfo(&toolchain.CompilerInfo{Lflags: ci.Lflags})
+ fullANames, _ := filepath.Glob(b.PkgBinDir(bpkg) + "/*.a")
+ for _, archiveName := range fullANames {
+ s := util.NewStaticLib(archiveName, ci.WholeArch)
+ staticLibs = append(staticLibs, s)
+ }
}
dirs = append(dirs, extraADirs...)
// Find all .a files in the input directories.
- trimmedANames := []string{}
- for _, dir := range dirs {
+ for _, dir := range extraADirs {
fullANames, _ := filepath.Glob(dir + "/*.a")
- for i, archiveName := range fullANames {
- fullANames[i] = filepath.ToSlash(archiveName)
+ for _, archiveName := range fullANames {
+ s := util.NewStaticLib(archiveName, false)
+ staticLibs = append(staticLibs, s)
}
- trimmedANames = append(trimmedANames, fullANames...)
}
c.LinkerScripts = linkerScripts
@@ -479,7 +485,8 @@ func (b *Builder) link(elfName string, linkerScripts
[]string,
return err
}
- err = c.CompileElf(elfName, trimmedANames, keepSymbols, b.linkElf)
+ err = c.CompileElf(elfName, staticLibs, keepSymbols, b.linkElf)
+
if err != nil {
return err
}
diff --git a/newt/builder/buildpackage.go b/newt/builder/buildpackage.go
index b5a9135b..7bcd835d 100644
--- a/newt/builder/buildpackage.go
+++ b/newt/builder/buildpackage.go
@@ -166,6 +166,16 @@ func (bpkg *BuildPackage) CompilerInfo(
util.OneTimeWarningError(err)
expandFlags(ci.Aflags)
+ var strArray []string
+ // // Check if the package should be linked as whole or not
+ strArray, err =
bpkg.rpkg.Lpkg.PkgY.GetValStringSlice("pkg.whole_archive", settings)
+ util.OneTimeWarningError(err)
+ for _, str := range strArray {
+ if strings.Contains(str, "true") {
+ ci.WholeArch = true
+ }
+ }
+
// Package-specific injected settings get specified as C flags on the
// command line.
for _, k := range bpkg.rpkg.Lpkg.InjectedSettings().Names() {
diff --git a/newt/toolchain/compiler.go b/newt/toolchain/compiler.go
index 82ee88c1..f84e16ed 100644
--- a/newt/toolchain/compiler.go
+++ b/newt/toolchain/compiler.go
@@ -61,6 +61,7 @@ type CompilerInfo struct {
Aflags []string
IgnoreFiles []*regexp.Regexp
IgnoreDirs []*regexp.Regexp
+ WholeArch bool
}
type CompileCommand struct {
@@ -170,6 +171,7 @@ func NewCompilerInfo() *CompilerInfo {
ci.Aflags = []string{}
ci.IgnoreFiles = []*regexp.Regexp{}
ci.IgnoreDirs = []*regexp.Regexp{}
+ ci.WholeArch = false
return ci
}
@@ -992,6 +994,15 @@ func (c *Compiler) getObjFiles(baseObjFiles []string)
[]string {
return baseObjFiles
}
+func (c *Compiler) getStaticLibs(baseStaticLib []util.StaticLib)
[]util.StaticLib {
+ c.mutex.Lock()
+ for objName, _ := range c.objPathList {
+ baseStaticLib = append(baseStaticLib,
util.NewStaticLib(objName, false))
+ }
+ c.mutex.Unlock()
+ return baseStaticLib
+}
+
// Calculates the command-line invocation necessary to link the specified elf
// file.
//
@@ -1003,9 +1014,9 @@ func (c *Compiler) getObjFiles(baseObjFiles []string)
[]string {
//
// @return (success) The command tokens.
func (c *Compiler) CompileBinaryCmd(dstFile string, options map[string]bool,
- objFiles []string, keepSymbols []string, elfLib string) []string {
+ staticLib []util.StaticLib, keepSymbols []string, elfLib string)
[]string {
- objList := c.getObjFiles(util.UniqueStrings(objFiles))
+ libList := c.getStaticLibs(util.UniqueStaticLib(staticLib))
cmd := []string{
c.ccPath,
@@ -1020,10 +1031,19 @@ func (c *Compiler) CompileBinaryCmd(dstFile string,
options map[string]bool,
if c.ldResolveCircularDeps {
cmd = append(cmd, "-Wl,--start-group")
- cmd = append(cmd, objList...)
+ }
+
+ 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 c.ldResolveCircularDeps {
cmd = append(cmd, "-Wl,--end-group")
- } else {
- cmd = append(cmd, objList...)
}
if keepSymbols != nil {
@@ -1059,23 +1079,25 @@ func (c *Compiler) CompileBinaryCmd(dstFile string,
options map[string]bool,
// gets generated.
// @param objFiles An array of the source .o and .a filenames.
func (c *Compiler) CompileBinary(dstFile string, options map[string]bool,
- objFiles []string, keepSymbols []string, elfLib string) error {
+ staticLib []util.StaticLib, keepSymbols []string, elfLib string) error {
// Make sure the compiler package info is added to the global set.
c.ensureLclInfoAdded()
- objList := c.getObjFiles(util.UniqueStrings(objFiles))
-
util.StatusMessage(util.VERBOSITY_DEFAULT, "Linking %s\n", dstFile)
- util.StatusMessage(util.VERBOSITY_VERBOSE, "Linking %s with input files
%s\n",
- dstFile, objList)
+
+ libList := c.getStaticLibs(util.UniqueStaticLib(staticLib))
+
+ for _, lib := range libList {
+ util.StatusMessage(util.VERBOSITY_VERBOSE, "Linking %s with
input files %s\n", dstFile, lib.File)
+ }
if elfLib != "" {
util.StatusMessage(util.VERBOSITY_VERBOSE, "Linking %s with rom
image %s\n",
dstFile, elfLib)
}
- cmd := c.CompileBinaryCmd(dstFile, options, objFiles, keepSymbols,
elfLib)
+ cmd := c.CompileBinaryCmd(dstFile, options, libList, keepSymbols,
elfLib)
o, err := util.ShellCommand(cmd, nil)
if err != nil {
return err
@@ -1204,7 +1226,7 @@ func (c *Compiler) PrintSize(elfFilename string) (string,
error) {
// @param options Some build options specifying how the elf file
// gets generated.
// @param objFiles An array of the source .o and .a filenames.
-func (c *Compiler) CompileElf(binFile string, objFiles []string,
+func (c *Compiler) CompileElf(binFile string, staticLib []util.StaticLib,
keepSymbols []string, elfLib string) error {
options := map[string]bool{"mapFile": c.ldMapFile,
"listFile": true, "binFile": c.ldBinFile}
@@ -1213,7 +1235,8 @@ func (c *Compiler) CompileElf(binFile string, objFiles
[]string,
c.ensureLclInfoAdded()
linkRequired, err := c.depTracker.LinkRequired(binFile, options,
- objFiles, keepSymbols, elfLib)
+ staticLib, keepSymbols, elfLib)
+
if err != nil {
return err
}
@@ -1221,7 +1244,7 @@ func (c *Compiler) CompileElf(binFile string, objFiles
[]string,
if err := os.MkdirAll(filepath.Dir(binFile), 0755); err != nil {
return util.NewNewtError(err.Error())
}
- err := c.CompileBinary(binFile, options, objFiles, keepSymbols,
elfLib)
+ err := c.CompileBinary(binFile, options, staticLib,
keepSymbols, elfLib)
if err != nil {
return err
}
diff --git a/newt/toolchain/deps.go b/newt/toolchain/deps.go
index ee6bc623..fa526f7a 100644
--- a/newt/toolchain/deps.go
+++ b/newt/toolchain/deps.go
@@ -328,12 +328,12 @@ func (tracker *DepTracker) ArchiveRequired(archiveFile
string,
// * One or more source object files has a newer modification time than the
// library file.
func (tracker *DepTracker) LinkRequired(dstFile string,
- options map[string]bool, objFiles []string,
+ options map[string]bool, staticLib []util.StaticLib,
keepSymbols []string, elfLib string) (bool, error) {
// If the elf file was previously built with a different set of
options, a
// rebuild is required.
- cmd := tracker.compiler.CompileBinaryCmd(dstFile, options, objFiles,
keepSymbols, elfLib)
+ cmd := tracker.compiler.CompileBinaryCmd(dstFile, options, staticLib,
keepSymbols, elfLib)
if commandHasChanged(dstFile, cmd) {
logRebuildReqdCmdChanged(dstFile)
return true, nil
@@ -365,7 +365,11 @@ func (tracker *DepTracker) LinkRequired(dstFile string,
return true, nil
}
+ var objFiles []string
// Check timestamp of the linker script and all input libraries.
+ for _, obj := range staticLib {
+ objFiles = append(objFiles, obj.File)
+ }
for _, ls := range tracker.compiler.LinkerScripts {
objFiles = append(objFiles, ls)
}
diff --git a/util/util.go b/util/util.go
index 41632bcc..5823762a 100644
--- a/util/util.go
+++ b/util/util.go
@@ -70,6 +70,19 @@ const (
VERBOSITY_VERBOSE = 3
)
+type StaticLib struct {
+ File string
+ WholeArch bool
+}
+
+func NewStaticLib(file string, wholeArch bool) StaticLib {
+ s := StaticLib{
+ File: file,
+ WholeArch: wholeArch,
+ }
+ return s
+}
+
func (se *NewtError) Error() string {
return se.Text
}
@@ -668,6 +681,21 @@ func UniqueStrings(elems []string) []string {
return result
}
+// Removes all duplicate static lib from the specified array, while preserving
+// order.
+func UniqueStaticLib(libs []StaticLib) []StaticLib {
+ set := make(map[StaticLib]bool)
+ result := make([]StaticLib, 0)
+
+ for _, lib := range libs {
+ if !set[lib] {
+ result = append(result, lib)
+ set[lib] = true
+ }
+ }
+ return result
+}
+
// Sorts whitespace-delimited lists of strings.
//
// @param wsSepStrings A list of strings; each string contains one or