You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/07/09 23:30:11 UTC
incubator-mynewt-newt git commit: MYNEWT-323 Newt - Build flags
precedence hierarchy
Repository: incubator-mynewt-newt
Updated Branches:
refs/heads/develop 38b34ef49 -> a996d13f7
MYNEWT-323 Newt - Build flags precedence hierarchy
In the case of conflicting flags, the higher priority package's flag
wins. Package priorities are assigned as follows (highest priority
first):
* target
* app (if present)
* bsp
* <library package>
* compiler
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/a996d13f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/a996d13f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/a996d13f
Branch: refs/heads/develop
Commit: a996d13f7d971ad6f4d35a8d2ee066002c55b5ae
Parents: 38b34ef
Author: Christopher Collins <cc...@apache.org>
Authored: Sat Jul 9 16:28:50 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Sat Jul 9 16:28:50 2016 -0700
----------------------------------------------------------------------
newt/builder/build.go | 41 ++++++++++-----
newt/toolchain/compiler.go | 108 ++++++++++++++++++++++++++++++++++++----
2 files changed, 127 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/a996d13f/newt/builder/build.go
----------------------------------------------------------------------
diff --git a/newt/builder/build.go b/newt/builder/build.go
index d8a1e0a..2c67eac 100644
--- a/newt/builder/build.go
+++ b/newt/builder/build.go
@@ -24,6 +24,8 @@ import (
"os"
"path/filepath"
+ log "github.com/Sirupsen/logrus"
+
"mynewt.apache.org/newt/newt/pkg"
"mynewt.apache.org/newt/newt/target"
"mynewt.apache.org/newt/newt/toolchain"
@@ -204,6 +206,7 @@ func (b *Builder) newCompiler(bpkg *BuildPackage,
c.AddInfo(b.compilerInfo)
if bpkg != nil {
+ log.Debugf("Generating build flags for package %s", bpkg.FullName())
ci, err := bpkg.CompilerInfo(b)
if err != nil {
return nil, err
@@ -356,14 +359,32 @@ func (b *Builder) PrepBuild() error {
// Populate the base set of compiler flags. Flags from the following
// packages get applied to every source file:
+ // * target
// * app (if present)
// * bsp
// * compiler (not added here)
+ //
+ // In the case of conflicting flags, the higher priority package's flag
+ // wins. Package priorities are assigned as follows (highest priority
+ // first):
// * target
+ // * app (if present)
+ // * bsp
+ // * <library package>
+ // * compiler
baseCi := toolchain.NewCompilerInfo()
+ // Target flags.
+ log.Debugf("Generating build flags for target %s", b.target.FullName())
+ targetCi, err := targetBpkg.CompilerInfo(b)
+ if err != nil {
+ return err
+ }
+ baseCi.AddCompilerInfo(targetCi)
+
// App flags.
+ log.Debugf("Generating build flags for app %s", appPkg.FullName())
if appBpkg != nil {
appCi, err := appBpkg.CompilerInfo(b)
if err != nil {
@@ -373,29 +394,25 @@ func (b *Builder) PrepBuild() error {
}
// Bsp flags.
+ log.Debugf("Generating build flags for bsp %s", bspPkg.FullName())
bspCi, err := bspBpkg.CompilerInfo(b)
if err != nil {
return err
}
- // Define a cpp symbol indicating the BSP architecture, name of the BSP and app.
+
+ // Define a cpp symbol indicating the BSP architecture, name of the BSP and
+ // app.
bspCi.Cflags = append(bspCi.Cflags, "-DARCH_"+b.Bsp.Arch)
bspCi.Cflags = append(bspCi.Cflags,
- "-DBSP_NAME=\""+filepath.Base(b.Bsp.Name())+"\"");
+ "-DBSP_NAME=\""+filepath.Base(b.Bsp.Name())+"\"")
if appPkg != nil {
bspCi.Cflags = append(bspCi.Cflags,
- "-DAPP_NAME=\""+filepath.Base(appPkg.Name())+"\"");
+ "-DAPP_NAME=\""+filepath.Base(appPkg.Name())+"\"")
}
baseCi.AddCompilerInfo(bspCi)
- // Target flags.
- targetCi, err := targetBpkg.CompilerInfo(b)
- if err != nil {
- return err
- }
-
- baseCi.AddCompilerInfo(targetCi)
-
- // Note: Compiler flags get added when compiler is created.
+ // Note: Compiler flags get added at the end, after the flags for library
+ // package being built are calculated.
// Read the BSP configuration. These settings are necessary for the link
// step.
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/a996d13f/newt/toolchain/compiler.go
----------------------------------------------------------------------
diff --git a/newt/toolchain/compiler.go b/newt/toolchain/compiler.go
index 1167b83..85fbedb 100644
--- a/newt/toolchain/compiler.go
+++ b/newt/toolchain/compiler.go
@@ -65,8 +65,18 @@ type Compiler struct {
ldMapFile bool
dstDir string
+ // The info to be applied during compilation.
info CompilerInfo
+ // Info read from the compiler package itself. This is kept separate from
+ // the rest of the info because it has the lowest priority; it can only be
+ // added immediately before compiling beings.
+ lclInfo CompilerInfo
+
+ // Indicates whether the local compiler info has been appended to the
+ // common info set. Ensures the local info only gets added once.
+ lclInfoAdded bool
+
extraDeps []string
}
@@ -80,11 +90,66 @@ func NewCompilerInfo() *CompilerInfo {
return ci
}
+// Extracts the base of a flag string. A flag base is used when detecting flag
+// conflicts. If two flags have identicial bases, then they are in conflict.
+func flagsBase(cflags string) string {
+ eqIdx := strings.IndexByte(cflags, '=')
+ if eqIdx == -1 {
+ return cflags
+ } else {
+ return cflags[:eqIdx]
+ }
+}
+
+// Creates a map of flag bases to flag values, i.e.,
+// [flag-base] => flag
+//
+// This is used to make flag conflict detection more efficient.
+func flagsMap(cflags []string) map[string]string {
+ hash := map[string]string{}
+ for _, cf := range cflags {
+ hash[flagsBase(cf)] = cf
+ }
+
+ return hash
+}
+
+// Appends a new set of flags to an original set. If a new flag conflicts with
+// an original, the new flag is discarded. The assumption is that flags from
+// higher priority packages get added first.
+//
+// This is not terribly efficient: it results in flag maps being generated
+// repeatedly when they could be cached. Any inefficiencies here are probably
+// negligible compared to the time spent compiling and linking. If this
+// assumption turns out to be incorrect, we should cache the flag maps.
+func addFlags(flagType string, orig []string, new []string) []string {
+ origMap := flagsMap(orig)
+
+ combined := orig
+ for _, c := range new {
+ newBase := flagsBase(c)
+ origVal := origMap[newBase]
+ if origVal == "" {
+ // New flag; add it.
+ combined = append(combined, c)
+ } else {
+ // Flag already present from a higher priority package; discard the
+ // new one.
+ if origVal != c {
+ log.Debugf("Discarding %s %s in favor of %s", flagType, c,
+ origVal)
+ }
+ }
+ }
+
+ return combined
+}
+
func (ci *CompilerInfo) AddCompilerInfo(newCi *CompilerInfo) {
ci.Includes = append(ci.Includes, newCi.Includes...)
- ci.Cflags = append(ci.Cflags, newCi.Cflags...)
- ci.Lflags = append(ci.Lflags, newCi.Lflags...)
- ci.Aflags = append(ci.Aflags, newCi.Aflags...)
+ ci.Cflags = addFlags("cflag", ci.Cflags, newCi.Cflags)
+ ci.Lflags = addFlags("lflag", ci.Lflags, newCi.Lflags)
+ ci.Aflags = addFlags("aflag", ci.Aflags, newCi.Aflags)
}
func NewCompiler(compilerDir string, dstDir string,
@@ -146,9 +211,9 @@ func (c *Compiler) load(compilerDir string, buildProfile string) error {
c.osPath = newtutil.GetStringFeatures(v, features, "compiler.path.objsize")
c.ocPath = newtutil.GetStringFeatures(v, features, "compiler.path.objcopy")
- c.info.Cflags = loadFlags(v, features, "compiler.flags")
- c.info.Lflags = loadFlags(v, features, "compiler.ld.flags")
- c.info.Aflags = loadFlags(v, features, "compiler.as.flags")
+ c.lclInfo.Cflags = loadFlags(v, features, "compiler.flags")
+ c.lclInfo.Lflags = loadFlags(v, features, "compiler.ld.flags")
+ c.lclInfo.Aflags = loadFlags(v, features, "compiler.as.flags")
c.ldResolveCircularDeps, err = newtutil.GetBoolFeatures(v, features,
"compiler.ld.resolve_circular_deps")
@@ -162,7 +227,7 @@ func (c *Compiler) load(compilerDir string, buildProfile string) error {
return err
}
- if len(c.info.Cflags) == 0 {
+ if len(c.lclInfo.Cflags) == 0 {
// Assume no Cflags implies an unsupported build profile.
return util.FmtNewtError("Compiler doesn't support build profile "+
"specified by target on this OS (build_profile=\"%s\" OS=\"%s\")",
@@ -319,6 +384,17 @@ func writeCommandFile(dstFile string, cmd string) error {
return nil
}
+// Adds the info from the compiler package to the common set if it hasn't
+// already been added. The compiler package's info needs to be added last
+// because the compiler is the lowest priority package.
+func (c *Compiler) ensureLclInfoAdded() {
+ if !c.lclInfoAdded {
+ log.Debugf("Generating build flags for compiler")
+ c.AddInfo(&c.lclInfo)
+ c.lclInfoAdded = true
+ }
+}
+
// Compile the specified C or assembly file.
//
// @param file The filename of the source file to compile.
@@ -447,6 +523,9 @@ func (c *Compiler) processEntry(wd string, node os.FileInfo, cType int,
}
func (c *Compiler) RecursiveCompile(cType int, ignDirs []string) error {
+ // Make sure the compiler package info is added to the global set.
+ c.ensureLclInfoAdded()
+
// Get a list of files in the current directory, and if they are a
// directory, and that directory is not in the ignDirs variable, then
// recurse into that directory and compile the files in there
@@ -482,7 +561,8 @@ func (c *Compiler) RecursiveCompile(cType int, ignDirs []string) error {
case COMPILER_TYPE_ASM:
return c.CompileAs()
default:
- return util.NewNewtError("Wrong compiler type specified to RecursiveCompile")
+ return util.NewNewtError("Wrong compiler type specified to " +
+ "RecursiveCompile")
}
}
@@ -540,10 +620,15 @@ func (c *Compiler) CompileBinaryCmd(dstFile string, options map[string]bool,
func (c *Compiler) CompileBinary(dstFile string, options map[string]bool,
objFiles []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", path.Base(dstFile))
- util.StatusMessage(util.VERBOSITY_VERBOSE, "Linking %s with input files %s\n",
+ util.StatusMessage(util.VERBOSITY_DEFAULT, "Linking %s\n",
+ path.Base(dstFile))
+ util.StatusMessage(util.VERBOSITY_VERBOSE,
+ "Linking %s with input files %s\n",
dstFile, objList)
cmd := c.CompileBinaryCmd(dstFile, options, objFiles)
@@ -682,6 +767,9 @@ func (c *Compiler) CompileArchiveCmd(archiveFile string,
func (c *Compiler) CompileArchive(archiveFile string) error {
objFiles := []string{}
+ // Make sure the compiler package info is added to the global set.
+ c.ensureLclInfoAdded()
+
arRequired, err := c.depTracker.ArchiveRequired(archiveFile, objFiles)
if err != nil {
return err