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 <jocelynm...@yahoo.fr>
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

Reply via email to