Repository: incubator-mynewt-newt Updated Branches: refs/heads/develop e322f97cd -> 046317aa3
MYNEWT-558 newt - depgraph should show api / hard The `target dep` and `target revdep` commands only indicated package names in the dependency graph. This change enhances the output of these commands to show what created the dependency in the first place. Specifically, they now show whether the dependency is "hard" (package explicitly depends on another) or "soft" (package requires an API; other package happens to implement that API). This is useful when trying to completely remove a package from a build. In the future, we should also indicate which, if any, syscfg settings generated a particular dependency. The fix required a lot of changes to the newt code. The major change was to scale back the responsibilities of the pkg.LocalPackage type. This struct was being used during build and depgraph resolution, and its client relied on its inheritance of the pkg.Package interface. Consequently, it was difficult to add new features without breaking everything or bloating the LocalPackage struct. Now, instances of LocalPackage get converted to resolve.ResolvePackage during dependency and API resolution. Furthermore, builder.BuildPackage and resolve.ResolvePackage no longer inherit from LocalPackage. Instead, each contains a pointer to its corresponding LocalPackage or ResolvePackage. Since these types never need to be treated as generic package types, the code is simplified by eliminating these edges from the inheritance tree. 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/e4ac2617 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/e4ac2617 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/e4ac2617 Branch: refs/heads/develop Commit: e4ac2617615ad95fc5b56591b2576fc0ee978332 Parents: e322f97 Author: Christopher Collins <ccoll...@apache.org> Authored: Thu Feb 2 07:30:00 2017 -0800 Committer: Christopher Collins <ccoll...@apache.org> Committed: Sun Feb 5 12:17:47 2017 -0800 ---------------------------------------------------------------------- newt/builder/build.go | 98 +++++++++-------- newt/builder/buildpackage.go | 59 +++++------ newt/builder/buildutil.go | 32 +++--- newt/builder/depgraph.go | 102 +++++++++--------- newt/builder/library.go | 2 +- newt/builder/load.go | 2 +- newt/builder/paths.go | 30 +++--- newt/builder/selftest.go | 86 ++++++++++----- newt/builder/targetbuild.go | 75 +++++++------ newt/cli/target_cmds.go | 26 ++--- newt/cli/util.go | 23 ++++ newt/pkg/localpackage.go | 32 ------ newt/pkg/package.go | 2 - newt/resolve/resolve.go | 218 +++++++++++++++++++++++++------------- newt/resolve/resolveutil.go | 92 ++++++++++++++++ 15 files changed, 538 insertions(+), 341 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/build.go ---------------------------------------------------------------------- diff --git a/newt/builder/build.go b/newt/builder/build.go index 232a39e..d82d9ff 100644 --- a/newt/builder/build.go +++ b/newt/builder/build.go @@ -30,6 +30,7 @@ import ( "mynewt.apache.org/newt/newt/newtutil" "mynewt.apache.org/newt/newt/pkg" "mynewt.apache.org/newt/newt/repo" + "mynewt.apache.org/newt/newt/resolve" "mynewt.apache.org/newt/newt/symbol" "mynewt.apache.org/newt/newt/syscfg" "mynewt.apache.org/newt/newt/target" @@ -38,7 +39,7 @@ import ( ) type Builder struct { - PkgMap map[*pkg.LocalPackage]*BuildPackage + PkgMap map[*resolve.ResolvePackage]*BuildPackage apiMap map[string]*BuildPackage appPkg *BuildPackage @@ -54,11 +55,15 @@ type Builder struct { injectedSettings map[string]string } -func NewBuilder(t *TargetBuilder, buildName string, lpkgs []*pkg.LocalPackage, - apiMap map[string]*pkg.LocalPackage, cfg syscfg.Cfg) (*Builder, error) { +func NewBuilder( + t *TargetBuilder, + buildName string, + rpkgs []*resolve.ResolvePackage, + apiMap map[string]*resolve.ResolvePackage, + cfg syscfg.Cfg) (*Builder, error) { b := &Builder{ - PkgMap: make(map[*pkg.LocalPackage]*BuildPackage, len(lpkgs)), + PkgMap: make(map[*resolve.ResolvePackage]*BuildPackage, len(rpkgs)), cfg: cfg, buildName: buildName, @@ -68,8 +73,8 @@ func NewBuilder(t *TargetBuilder, buildName string, lpkgs []*pkg.LocalPackage, injectedSettings: map[string]string{}, } - for _, lpkg := range lpkgs { - if _, err := b.addPackage(lpkg); err != nil { + for _, rpkg := range rpkgs { + if _, err := b.addPackage(rpkg); err != nil { return nil, err } } @@ -79,15 +84,15 @@ func NewBuilder(t *TargetBuilder, buildName string, lpkgs []*pkg.LocalPackage, return nil, err } - for api, lpkg := range apiMap { - bpkg := b.PkgMap[lpkg] + for api, rpkg := range apiMap { + bpkg := b.PkgMap[rpkg] if bpkg == nil { - for _, lpkg := range b.sortedLocalPackages() { - log.Debugf(" * %s", lpkg.Name()) + for _, rpkg := range b.sortedRpkgs() { + log.Debugf(" * %s", rpkg.Lpkg.Name()) } return nil, util.FmtNewtError( "Unexpected unsatisfied API: %s; required by: %s", api, - lpkg.Name()) + rpkg.Lpkg.Name()) } b.apiMap[api] = bpkg @@ -96,17 +101,19 @@ func NewBuilder(t *TargetBuilder, buildName string, lpkgs []*pkg.LocalPackage, return b, nil } -func (b *Builder) addPackage(npkg *pkg.LocalPackage) (*BuildPackage, error) { +func (b *Builder) addPackage(rpkg *resolve.ResolvePackage) ( + *BuildPackage, error) { + // Don't allow nil entries to the map - if npkg == nil { + if rpkg == nil { panic("Cannot add nil package builder map") } - bpkg := b.PkgMap[npkg] + bpkg := b.PkgMap[rpkg] if bpkg == nil { - bpkg = NewBuildPackage(npkg) + bpkg = NewBuildPackage(rpkg) - switch bpkg.Type() { + switch bpkg.rpkg.Lpkg.Type() { case pkg.PACKAGE_TYPE_APP: if b.appPkg != nil { return nil, pkgTypeConflictErr(b.appPkg, bpkg) @@ -132,7 +139,7 @@ func (b *Builder) addPackage(npkg *pkg.LocalPackage) (*BuildPackage, error) { b.targetPkg = bpkg } - b.PkgMap[npkg] = bpkg + b.PkgMap[rpkg] = bpkg } return bpkg, nil @@ -140,7 +147,9 @@ func (b *Builder) addPackage(npkg *pkg.LocalPackage) (*BuildPackage, error) { func pkgTypeConflictErr(p1 *BuildPackage, p2 *BuildPackage) error { return util.FmtNewtError("Two %s packages in build: %s, %s", - pkg.PackageTypeNames[p1.Type()], p1.Name(), p2.Name()) + pkg.PackageTypeNames[p1.rpkg.Lpkg.Type()], + p1.rpkg.Lpkg.Name(), + p2.rpkg.Lpkg.Name()) } // Recursively compiles all the .c and .s files in the specified directory. @@ -243,7 +252,8 @@ func (b *Builder) newCompiler(bpkg *BuildPackage, c.AddInfo(b.compilerInfo) if bpkg != nil { - log.Debugf("Generating build flags for package %s", bpkg.FullName()) + log.Debugf("Generating build flags for package %s", + bpkg.rpkg.Lpkg.FullName()) ci, err := bpkg.CompilerInfo(b) if err != nil { return nil, err @@ -266,7 +276,7 @@ func (b *Builder) collectCompileEntriesBpkg(bpkg *BuildPackage) ( if len(bpkg.SourceDirectories) > 0 { for _, relDir := range bpkg.SourceDirectories { - dir := bpkg.BasePath() + "/" + relDir + dir := bpkg.rpkg.Lpkg.BasePath() + "/" + relDir if util.NodeNotExist(dir) { return nil, util.NewNewtError(fmt.Sprintf( "Specified source directory %s, does not exist.", @@ -275,7 +285,7 @@ func (b *Builder) collectCompileEntriesBpkg(bpkg *BuildPackage) ( srcDirs = append(srcDirs, dir) } } else { - srcDir := bpkg.BasePath() + "/src" + srcDir := bpkg.rpkg.Lpkg.BasePath() + "/src" if util.NodeNotExist(srcDir) { // Nothing to compile. return nil, nil @@ -302,7 +312,7 @@ func (b *Builder) createArchive(c *toolchain.Compiler, bpkg *BuildPackage) error { // Create a static library ("archive"). - c.SetSrcDir(bpkg.RelativePath()) + c.SetSrcDir(bpkg.rpkg.Lpkg.RelativePath()) archiveFile := b.ArchivePath(bpkg) if err := c.CompileArchive(archiveFile); err != nil { return err @@ -314,7 +324,7 @@ func (b *Builder) createArchive(c *toolchain.Compiler, func (b *Builder) RemovePackages(cmn map[string]bool) error { for pkgName, _ := range cmn { for lp, bpkg := range b.PkgMap { - if bpkg.Name() == pkgName { + if bpkg.rpkg.Lpkg.Name() == pkgName { delete(b.PkgMap, lp) } } @@ -387,7 +397,7 @@ func (b *Builder) PrepBuild() error { // Target flags. log.Debugf("Generating build flags for target %s", - b.targetPkg.FullName()) + b.targetPkg.rpkg.Lpkg.FullName()) targetCi, err := b.targetPkg.CompilerInfo(b) if err != nil { return err @@ -396,7 +406,8 @@ func (b *Builder) PrepBuild() error { // App flags. if b.appPkg != nil { - log.Debugf("Generating build flags for app %s", b.appPkg.FullName()) + log.Debugf("Generating build flags for app %s", + b.appPkg.rpkg.Lpkg.FullName()) appCi, err := b.appPkg.CompilerInfo(b) if err != nil { return err @@ -406,7 +417,8 @@ func (b *Builder) PrepBuild() error { } // Bsp flags. - log.Debugf("Generating build flags for bsp %s", b.bspPkg.FullName()) + log.Debugf("Generating build flags for bsp %s", + b.bspPkg.rpkg.Lpkg.FullName()) bspCi, err := b.bspPkg.CompilerInfo(b) if err != nil { return err @@ -420,12 +432,12 @@ func (b *Builder) PrepBuild() error { bspCi.Cflags = append(bspCi.Cflags, "-DARCH_NAME="+archName+"") if b.appPkg != nil { - appName := filepath.Base(b.appPkg.Name()) + appName := filepath.Base(b.appPkg.rpkg.Lpkg.Name()) bspCi.Cflags = append(bspCi.Cflags, "-DAPP_"+util.CIdentifier(appName)) bspCi.Cflags = append(bspCi.Cflags, "-DAPP_NAME="+appName+"") } - bspName := filepath.Base(b.bspPkg.Name()) + bspName := filepath.Base(b.bspPkg.rpkg.Lpkg.Name()) bspCi.Cflags = append(bspCi.Cflags, "-DBSP_"+util.CIdentifier(bspName)) bspCi.Cflags = append(bspCi.Cflags, "-DBSP_NAME="+bspName+"") @@ -433,7 +445,7 @@ func (b *Builder) PrepBuild() error { // All packages have access to the generated code header directory. baseCi.Cflags = append(baseCi.Cflags, - "-I"+GeneratedIncludeDir(b.targetPkg.Name())) + "-I"+GeneratedIncludeDir(b.targetPkg.rpkg.Lpkg.Name())) // Note: Compiler flags get added at the end, after the flags for library // package being built are calculated. @@ -447,12 +459,14 @@ func (b *Builder) AddCompilerInfo(info *toolchain.CompilerInfo) { } func (b *Builder) addSysinitBpkg() (*BuildPackage, error) { - lpkg := pkg.NewLocalPackage(b.targetPkg.Repo().(*repo.Repo), - GeneratedBaseDir(b.targetPkg.Name())) - lpkg.SetName(pkg.ShortName(b.targetPkg) + "-sysinit-" + b.buildName) + lpkg := pkg.NewLocalPackage(b.targetPkg.rpkg.Lpkg.Repo().(*repo.Repo), + GeneratedBaseDir(b.targetPkg.rpkg.Lpkg.Name())) + lpkg.SetName(pkg.ShortName(b.targetPkg.rpkg.Lpkg) + "-sysinit-" + + b.buildName) lpkg.SetType(pkg.PACKAGE_TYPE_GENERATED) - return b.addPackage(lpkg) + rpkg := resolve.NewResolvePkg(lpkg) + return b.addPackage(rpkg) } // Runs build jobs while any remain. On failure, signals the other workers to @@ -588,9 +602,9 @@ func (b *Builder) TentativeLink(linkerScripts []string) error { } func (b *Builder) pkgWithPath(path string) *BuildPackage { - for _, p := range b.PkgMap { - if p.BasePath() == path { - return p + for _, bpkg := range b.PkgMap { + if bpkg.rpkg.Lpkg.BasePath() == path { + return bpkg } } @@ -598,21 +612,21 @@ func (b *Builder) pkgWithPath(path string) *BuildPackage { } func (b *Builder) FetchSymbolMap() (error, *symbol.SymbolMap) { - loader_sm := symbol.NewSymbolMap() + loaderSm := symbol.NewSymbolMap() - for _, value := range b.PkgMap { - err, sm := b.ParseObjectLibrary(value) + for _, bpkg := range b.PkgMap { + err, sm := b.ParseObjectLibrary(bpkg) if err == nil { util.StatusMessage(util.VERBOSITY_VERBOSE, - "Size of %s Loader Map %d\n", value.Name(), len(*sm)) - loader_sm, err = loader_sm.Merge(sm) + "Size of %s Loader Map %d\n", bpkg.rpkg.Lpkg.Name(), len(*sm)) + loaderSm, err = loaderSm.Merge(sm) if err != nil { return err, nil } } } - return nil, loader_sm + return nil, loaderSm } func (b *Builder) GetTarget() *target.Target { http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/buildpackage.go ---------------------------------------------------------------------- diff --git a/newt/builder/buildpackage.go b/newt/builder/buildpackage.go index 5071185..e82566f 100644 --- a/newt/builder/buildpackage.go +++ b/newt/builder/buildpackage.go @@ -26,22 +26,21 @@ import ( "mynewt.apache.org/newt/newt/newtutil" "mynewt.apache.org/newt/newt/pkg" - "mynewt.apache.org/newt/newt/project" + "mynewt.apache.org/newt/newt/resolve" "mynewt.apache.org/newt/newt/syscfg" "mynewt.apache.org/newt/newt/toolchain" "mynewt.apache.org/newt/util" ) type BuildPackage struct { - *pkg.LocalPackage - - ci *toolchain.CompilerInfo + rpkg *resolve.ResolvePackage SourceDirectories []string + ci *toolchain.CompilerInfo } -func NewBuildPackage(pkg *pkg.LocalPackage) *BuildPackage { +func NewBuildPackage(rpkg *resolve.ResolvePackage) *BuildPackage { bpkg := &BuildPackage{ - LocalPackage: pkg, + rpkg: rpkg, } return bpkg @@ -58,22 +57,11 @@ func (bpkg *BuildPackage) collectDepsAux(b *Builder, (*set)[bpkg] = true - for _, dep := range bpkg.Deps() { - if dep.Name == "" { - break - } - - // Get pkg structure - p := project.GetProject().ResolveDependency(dep) - if p == nil { - return util.FmtNewtError("Cannot resolve dependency %+v", dep) - } - dpkg := p.(*pkg.LocalPackage) - - dbpkg := b.PkgMap[dpkg] + for _, dep := range bpkg.rpkg.Deps { + dbpkg := b.PkgMap[dep.Rpkg] if dbpkg == nil { return util.FmtNewtError("Package not found %s; required by %s", - dpkg.Name(), bpkg.Name()) + dbpkg.rpkg.Lpkg.Name(), bpkg.rpkg.Lpkg.Name()) } if err := dbpkg.collectDepsAux(b, set); err != nil { @@ -140,30 +128,30 @@ func (bpkg *BuildPackage) CompilerInfo( } ci := toolchain.NewCompilerInfo() - features := b.cfg.FeaturesForLpkg(bpkg.LocalPackage) + features := b.cfg.FeaturesForLpkg(bpkg.rpkg.Lpkg) // Read each set of flags and expand repo designators ("@<repo-nme>") into // paths. - ci.Cflags = newtutil.GetStringSliceFeatures(bpkg.PkgV, features, + ci.Cflags = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features, "pkg.cflags") expandFlags(ci.Cflags) - ci.Lflags = newtutil.GetStringSliceFeatures(bpkg.PkgV, features, + ci.Lflags = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features, "pkg.lflags") expandFlags(ci.Lflags) - ci.Aflags = newtutil.GetStringSliceFeatures(bpkg.PkgV, features, + ci.Aflags = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features, "pkg.aflags") expandFlags(ci.Aflags) // Package-specific injected settings get specified as C flags on the // command line. - for k, _ := range bpkg.InjectedSettings() { + for k, _ := range bpkg.rpkg.Lpkg.InjectedSettings() { ci.Cflags = append(ci.Cflags, syscfg.FeatureToCflag(k)) } ci.IgnoreFiles = []*regexp.Regexp{} - ignPats := newtutil.GetStringSliceFeatures(bpkg.PkgV, + ignPats := newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features, "pkg.ign_files") for _, str := range ignPats { re, err := regexp.Compile(str) @@ -175,7 +163,7 @@ func (bpkg *BuildPackage) CompilerInfo( } ci.IgnoreDirs = []*regexp.Regexp{} - ignPats = newtutil.GetStringSliceFeatures(bpkg.PkgV, + ignPats = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features, "pkg.ign_dirs") for _, str := range ignPats { re, err := regexp.Compile(str) @@ -186,7 +174,8 @@ func (bpkg *BuildPackage) CompilerInfo( ci.IgnoreDirs = append(ci.IgnoreDirs, re) } - bpkg.SourceDirectories = newtutil.GetStringSliceFeatures(bpkg.PkgV, + bpkg.SourceDirectories = newtutil.GetStringSliceFeatures( + bpkg.rpkg.Lpkg.PkgV, features, "pkg.src_dirs") includePaths, err := bpkg.recursiveIncludePaths(b) @@ -201,7 +190,7 @@ func (bpkg *BuildPackage) CompilerInfo( } func (bpkg *BuildPackage) findSdkIncludes() []string { - sdkDir := bpkg.BasePath() + "/src/ext/" + sdkDir := bpkg.rpkg.Lpkg.BasePath() + "/src/ext/" sdkPathList := []string{} err := filepath.Walk(sdkDir, @@ -221,15 +210,15 @@ func (bpkg *BuildPackage) findSdkIncludes() []string { } func (bpkg *BuildPackage) publicIncludeDirs(bspPkg *pkg.BspPackage) []string { - pkgBase := filepath.Base(bpkg.Name()) - bp := bpkg.BasePath() + pkgBase := filepath.Base(bpkg.rpkg.Lpkg.Name()) + bp := bpkg.rpkg.Lpkg.BasePath() incls := []string{ bp + "/include", bp + "/include/" + pkgBase + "/arch/" + bspPkg.Arch, } - if bpkg.Type() == pkg.PACKAGE_TYPE_SDK { + if bpkg.rpkg.Lpkg.Type() == pkg.PACKAGE_TYPE_SDK { incls = append(incls, bspPkg.BasePath()+"/include/bsp/") sdkIncls := bpkg.findSdkIncludes() @@ -240,17 +229,17 @@ func (bpkg *BuildPackage) publicIncludeDirs(bspPkg *pkg.BspPackage) []string { } func (bpkg *BuildPackage) privateIncludeDirs(b *Builder) []string { - srcDir := bpkg.BasePath() + "/src/" + srcDir := bpkg.rpkg.Lpkg.BasePath() + "/src/" incls := []string{} incls = append(incls, srcDir) incls = append(incls, srcDir+"/arch/"+b.targetBuilder.bspPkg.Arch) - switch bpkg.Type() { + switch bpkg.rpkg.Lpkg.Type() { case pkg.PACKAGE_TYPE_SDK: // If pkgType == SDK, include all the items in "ext" directly into the // include path - incls = append(incls, b.bspPkg.BasePath()+"/include/bsp/") + incls = append(incls, b.bspPkg.rpkg.Lpkg.BasePath()+"/include/bsp/") sdkIncls := bpkg.findSdkIncludes() incls = append(incls, sdkIncls...) http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/buildutil.go ---------------------------------------------------------------------- diff --git a/newt/builder/buildutil.go b/newt/builder/buildutil.go index e8299ff..15ab0c2 100644 --- a/newt/builder/buildutil.go +++ b/newt/builder/buildutil.go @@ -26,7 +26,7 @@ import ( log "github.com/Sirupsen/logrus" - "mynewt.apache.org/newt/newt/pkg" + "mynewt.apache.org/newt/newt/resolve" ) func TestTargetName(testPkgName string) string { @@ -64,7 +64,7 @@ func (b bpkgSorter) Swap(i, j int) { b.bpkgs[i], b.bpkgs[j] = b.bpkgs[j], b.bpkgs[i] } func (b bpkgSorter) Less(i, j int) bool { - return b.bpkgs[i].Name() < b.bpkgs[j].Name() + return b.bpkgs[i].rpkg.Lpkg.Name() < b.bpkgs[j].rpkg.Lpkg.Name() } func (b *Builder) sortedBuildPackages() []*BuildPackage { @@ -80,39 +80,33 @@ func (b *Builder) sortedBuildPackages() []*BuildPackage { return sorter.bpkgs } -func (b *Builder) sortedLocalPackages() []*pkg.LocalPackage { +func (b *Builder) sortedRpkgs() []*resolve.ResolvePackage { bpkgs := b.sortedBuildPackages() - lpkgs := make([]*pkg.LocalPackage, len(bpkgs), len(bpkgs)) + rpkgs := make([]*resolve.ResolvePackage, len(bpkgs), len(bpkgs)) for i, bpkg := range bpkgs { - lpkgs[i] = bpkg.LocalPackage + rpkgs[i] = bpkg.rpkg } - return lpkgs + return rpkgs } -func logDepInfo(builders []*Builder) { +func logDepInfo(res *resolve.Resolution) { // Log API set. apis := []string{} - apiMap := map[string]*BuildPackage{} - for _, b := range builders { - if b != nil { - for api, bpkg := range b.apiMap { - apiMap[api] = bpkg - apis = append(apis, api) - } - } + for api, _ := range res.ApiMap { + apis = append(apis, api) } sort.Strings(apis) log.Debugf("API set:") for _, api := range apis { - bpkg := apiMap[api] - log.Debugf(" * " + api + " (" + bpkg.FullName() + ")") + rpkg := res.ApiMap[api] + log.Debugf(" * " + api + " (" + rpkg.Lpkg.FullName() + ")") } // Log dependency graph. - dg, err := joinedDepGraph(builders) + dg, err := joinedDepGraph(res.Sets()) if err != nil { log.Debugf("Error while constructing dependency graph: %s\n", err.Error()) @@ -121,7 +115,7 @@ func logDepInfo(builders []*Builder) { } // Log reverse dependency graph. - rdg, err := joinedRevdepGraph(builders) + rdg, err := joinedRevdepGraph(res.Sets()) if err != nil { log.Debugf("Error while constructing reverse dependency graph: %s\n", err.Error()) http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/depgraph.go ---------------------------------------------------------------------- diff --git a/newt/builder/depgraph.go b/newt/builder/depgraph.go index 647028e..f38906c 100644 --- a/newt/builder/depgraph.go +++ b/newt/builder/depgraph.go @@ -23,18 +23,16 @@ import ( "bytes" "fmt" - "mynewt.apache.org/newt/newt/pkg" - "mynewt.apache.org/newt/newt/project" - "mynewt.apache.org/newt/util" + "mynewt.apache.org/newt/newt/resolve" ) -type DepGraph map[*pkg.LocalPackage][]*pkg.LocalPackage -type graphMap map[*pkg.LocalPackage]map[*pkg.LocalPackage]struct{} +type DepGraph map[*resolve.ResolvePackage][]*resolve.ResolveDep +type graphMap map[*resolve.ResolvePackage]map[*resolve.ResolveDep]struct{} -func graphMapAdd(gm graphMap, p *pkg.LocalPackage, c *pkg.LocalPackage) { +func graphMapAdd(gm graphMap, p *resolve.ResolvePackage, c *resolve.ResolveDep) { dstGraph := gm[p] if dstGraph == nil { - dstGraph = map[*pkg.LocalPackage]struct{}{} + dstGraph = map[*resolve.ResolveDep]struct{}{} } dstGraph[c] = struct{}{} @@ -45,42 +43,34 @@ func graphMapToDepGraph(gm graphMap) DepGraph { dg := DepGraph{} for parent, childMap := range gm { - dg[parent] = []*pkg.LocalPackage{} + dg[parent] = []*resolve.ResolveDep{} for child, _ := range childMap { dg[parent] = append(dg[parent], child) } - pkg.SortLclPkgs(dg[parent]) + resolve.SortResolveDeps(dg[parent]) } return dg } -func (b *Builder) depGraph() (DepGraph, error) { +func depGraph(rs *resolve.ResolveSet) (DepGraph, error) { graph := DepGraph{} - proj := project.GetProject() - for parent, _ := range b.PkgMap { - graph[parent] = []*pkg.LocalPackage{} + for _, parent := range rs.Rpkgs { + graph[parent] = []*resolve.ResolveDep{} - for _, dep := range parent.Deps() { - child := proj.ResolveDependency(dep).(*pkg.LocalPackage) - if child == nil { - return nil, util.FmtNewtError( - "cannot resolve package \"%s\"; depender=\"%s\"", - dep.String(), parent.FullName()) - } - - graph[parent] = append(graph[parent], child) + for _, dep := range parent.Deps { + graph[parent] = append(graph[parent], dep) } - pkg.SortLclPkgs(graph[parent]) + resolve.SortResolveDeps(graph[parent]) } return graph, nil } -func (b *Builder) revdepGraph() (DepGraph, error) { - graph, err := b.depGraph() +func revdepGraph(rs *resolve.ResolveSet) (DepGraph, error) { + graph, err := depGraph(rs) if err != nil { return nil, err } @@ -88,7 +78,11 @@ func (b *Builder) revdepGraph() (DepGraph, error) { revGm := graphMap{} for parent, children := range graph { for _, child := range children { - graphMapAdd(revGm, child, parent) + rParent := child.Rpkg + rChild := *child + rChild.Rpkg = parent + + graphMapAdd(revGm, rParent, &rChild) } } @@ -101,7 +95,7 @@ func mergeDepGraphs(graphs ...DepGraph) DepGraph { for _, graph := range graphs { for parent, children := range graph { if gm[parent] == nil { - gm[parent] = map[*pkg.LocalPackage]struct{}{} + gm[parent] = map[*resolve.ResolveDep]struct{}{} } for _, child := range children { @@ -115,11 +109,11 @@ func mergeDepGraphs(graphs ...DepGraph) DepGraph { return dg } -func joinedDepGraph(builders []*Builder) (DepGraph, error) { +func joinedDepGraph(rss []*resolve.ResolveSet) (DepGraph, error) { finalGraph := DepGraph{} - for _, b := range builders { - graph, err := b.depGraph() + for _, rs := range rss { + graph, err := depGraph(rs) if err != nil { return nil, err } @@ -129,11 +123,11 @@ func joinedDepGraph(builders []*Builder) (DepGraph, error) { return finalGraph, nil } -func joinedRevdepGraph(builders []*Builder) (DepGraph, error) { +func joinedRevdepGraph(rss []*resolve.ResolveSet) (DepGraph, error) { finalGraph := DepGraph{} - for _, b := range builders { - graph, err := b.revdepGraph() + for _, rs := range rss { + graph, err := revdepGraph(rs) if err != nil { return nil, err } @@ -143,24 +137,33 @@ func joinedRevdepGraph(builders []*Builder) (DepGraph, error) { return finalGraph, nil } +func depString(dep *resolve.ResolveDep) string { + s := fmt.Sprintf("%s", dep.Rpkg.Lpkg.FullName()) + if dep.Api != "" { + s += fmt.Sprintf("(api:%s)", dep.Api) + } + + return s +} + func DepGraphText(graph DepGraph) string { - parents := make([]*pkg.LocalPackage, 0, len(graph)) + parents := make([]*resolve.ResolvePackage, 0, len(graph)) for lpkg, _ := range graph { parents = append(parents, lpkg) } - parents = pkg.SortLclPkgs(parents) + parents = resolve.SortResolvePkgs(parents) buffer := bytes.NewBufferString("") fmt.Fprintf(buffer, "Dependency graph (depender --> [dependees]):") for _, parent := range parents { - children := graph[parent] - fmt.Fprintf(buffer, "\n * %s --> [", parent.FullName()) + children := resolve.SortResolveDeps(graph[parent]) + fmt.Fprintf(buffer, "\n * %s --> [", parent.Lpkg.FullName()) for i, child := range children { if i != 0 { fmt.Fprintf(buffer, " ") } - fmt.Fprintf(buffer, "%s", child.FullName()) + fmt.Fprintf(buffer, "%s", depString(child)) } fmt.Fprintf(buffer, "]") } @@ -169,23 +172,23 @@ func DepGraphText(graph DepGraph) string { } func RevdepGraphText(graph DepGraph) string { - parents := make([]*pkg.LocalPackage, 0, len(graph)) + parents := make([]*resolve.ResolvePackage, 0, len(graph)) for lpkg, _ := range graph { parents = append(parents, lpkg) } - parents = pkg.SortLclPkgs(parents) + parents = resolve.SortResolvePkgs(parents) buffer := bytes.NewBufferString("") fmt.Fprintf(buffer, "Reverse dependency graph (dependee <-- [dependers]):") for _, parent := range parents { - children := graph[parent] - fmt.Fprintf(buffer, "\n * %s <-- [", parent.FullName()) + children := resolve.SortResolveDeps(graph[parent]) + fmt.Fprintf(buffer, "\n * %s <-- [", parent.Lpkg.FullName()) for i, child := range children { if i != 0 { fmt.Fprintf(buffer, " ") } - fmt.Fprintf(buffer, "%s", child.FullName()) + fmt.Fprintf(buffer, "%s", depString(child)) } fmt.Fprintf(buffer, "]") } @@ -195,15 +198,18 @@ func RevdepGraphText(graph DepGraph) string { // Extracts a new dependency graph containing only the specified parents. // -// @return DepGraph Filtered dependency graph -// []*pkg.LocalPackage Specified packages that were not parents in +// @param dg The source graph to filter. +// @param parents The parent nodes to keep. +// +// @return DepGraph Filtered dependency graph. +// []*ResolvePackage Specified packages that were not parents in // original graph. -func FilterDepGraph(dg DepGraph, parents []*pkg.LocalPackage) ( - DepGraph, []*pkg.LocalPackage) { +func FilterDepGraph(dg DepGraph, parents []*resolve.ResolvePackage) ( + DepGraph, []*resolve.ResolvePackage) { newDg := DepGraph{} - var missing []*pkg.LocalPackage + var missing []*resolve.ResolvePackage for _, p := range parents { if dg[p] == nil { missing = append(missing, p) http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/library.go ---------------------------------------------------------------------- diff --git a/newt/builder/library.go b/newt/builder/library.go index fd6f71c..af3c5b8 100644 --- a/newt/builder/library.go +++ b/newt/builder/library.go @@ -162,7 +162,7 @@ func (b *Builder) ParseObjectLibraryFile(bp *BuildPackage, /* assign the library */ if bp != nil { - (*si).Bpkg = bp.Name() + (*si).Bpkg = bp.rpkg.Lpkg.Name() } else { (*si).Bpkg = "elf" } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/load.go ---------------------------------------------------------------------- diff --git a/newt/builder/load.go b/newt/builder/load.go index 1cf9a84..eb7396e 100644 --- a/newt/builder/load.go +++ b/newt/builder/load.go @@ -171,7 +171,7 @@ func (b *Builder) debugBin(binPath string, extraJtagCmd string, reset bool, return err } - bspPath := b.bspPkg.BasePath() + bspPath := b.bspPkg.rpkg.Lpkg.BasePath() binBaseName := binPath featureString := b.FeatureString() http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/paths.go ---------------------------------------------------------------------- diff --git a/newt/builder/paths.go b/newt/builder/paths.go index b57dd2c..5beb6b3 100644 --- a/newt/builder/paths.go +++ b/newt/builder/paths.go @@ -123,39 +123,41 @@ func MfgBootDir(mfgPkgName string) string { } func (b *Builder) BinDir() string { - return BinDir(b.targetPkg.Name(), b.buildName) + return BinDir(b.targetPkg.rpkg.Lpkg.Name(), b.buildName) } func (b *Builder) FileBinDir(pkgName string) string { - return FileBinDir(b.targetPkg.Name(), b.buildName, pkgName) + return FileBinDir(b.targetPkg.rpkg.Lpkg.Name(), b.buildName, pkgName) } func (b *Builder) PkgBinDir(bpkg *BuildPackage) string { - return PkgBinDir(b.targetPkg.Name(), b.buildName, bpkg.Name(), bpkg.Type()) + return PkgBinDir(b.targetPkg.rpkg.Lpkg.Name(), b.buildName, bpkg.rpkg.Lpkg.Name(), + bpkg.rpkg.Lpkg.Type()) } // Generates the path+filename of the specified package's .a file. func (b *Builder) ArchivePath(bpkg *BuildPackage) string { - return ArchivePath(b.targetPkg.Name(), b.buildName, bpkg.Name(), - bpkg.Type()) + return ArchivePath(b.targetPkg.rpkg.Lpkg.Name(), b.buildName, bpkg.rpkg.Lpkg.Name(), + bpkg.rpkg.Lpkg.Type()) } func (b *Builder) AppTentativeElfPath() string { - return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) + + return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.rpkg.Lpkg.Name()) + "_tmp.elf" } func (b *Builder) AppElfPath() string { - return AppElfPath(b.targetPkg.Name(), b.buildName, b.appPkg.Name()) + return AppElfPath(b.targetPkg.rpkg.Lpkg.Name(), b.buildName, + b.appPkg.rpkg.Lpkg.Name()) } func (b *Builder) AppLinkerElfPath() string { - return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) + + return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.rpkg.Lpkg.Name()) + "linker.elf" } func (b *Builder) AppImgPath() string { - return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) + + return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.rpkg.Lpkg.Name()) + ".img" } @@ -168,14 +170,16 @@ func (b *Builder) AppPath() string { } func (b *Builder) TestExePath(bpkg *BuildPackage) string { - return TestExePath(b.targetPkg.Name(), b.buildName, bpkg.Name(), - bpkg.Type()) + return TestExePath(b.targetPkg.rpkg.Lpkg.Name(), b.buildName, + bpkg.rpkg.Lpkg.Name(), bpkg.rpkg.Lpkg.Type()) } func (b *Builder) ManifestPath() string { - return ManifestPath(b.targetPkg.Name(), b.buildName, b.appPkg.Name()) + return ManifestPath(b.targetPkg.rpkg.Lpkg.Name(), b.buildName, + b.appPkg.rpkg.Lpkg.Name()) } func (b *Builder) AppBinBasePath() string { - return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) + return b.PkgBinDir(b.appPkg) + "/" + + filepath.Base(b.appPkg.rpkg.Lpkg.Name()) } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/selftest.go ---------------------------------------------------------------------- diff --git a/newt/builder/selftest.go b/newt/builder/selftest.go index 36781b7..fc7268c 100644 --- a/newt/builder/selftest.go +++ b/newt/builder/selftest.go @@ -27,11 +27,28 @@ import ( "mynewt.apache.org/newt/newt/pkg" "mynewt.apache.org/newt/newt/project" + "mynewt.apache.org/newt/newt/resolve" "mynewt.apache.org/newt/util" ) -func (b *Builder) SelfTestLink(p *pkg.LocalPackage) error { - testBpkg := b.PkgMap[p] +func (b *Builder) getTestBpkg(rpkg *resolve.ResolvePackage) ( + *BuildPackage, error) { + + testBpkg := b.PkgMap[rpkg] + if testBpkg == nil { + return nil, util.FmtNewtError("builder missing test package: %s", + rpkg.Lpkg.FullName()) + } + + return testBpkg, nil +} + +func (b *Builder) SelfTestLink(rpkg *resolve.ResolvePackage) error { + testBpkg, err := b.getTestBpkg(rpkg) + if err != nil { + return err + } + testPath := b.TestExePath(testBpkg) if err := b.link(testPath, nil, nil); err != nil { return err @@ -40,6 +57,16 @@ func (b *Builder) SelfTestLink(p *pkg.LocalPackage) error { return nil } +func (t *TargetBuilder) getTestRpkg() (*resolve.ResolvePackage, error) { + testRpkg := t.res.LpkgRpkgMap[t.testPkg] + if testRpkg == nil { + return nil, util.FmtNewtError("resolution missing test package: %s", + t.testPkg.FullName()) + } + + return testRpkg, nil +} + func (t *TargetBuilder) SelfTestCreateExe() error { if err := t.PrepBuild(); err != nil { return err @@ -49,7 +76,12 @@ func (t *TargetBuilder) SelfTestCreateExe() error { return err } - if err := t.AppBuilder.SelfTestLink(t.testPkg); err != nil { + testRpkg, err := t.getTestRpkg() + if err != nil { + return err + } + + if err := t.AppBuilder.SelfTestLink(testRpkg); err != nil { return err } @@ -61,7 +93,12 @@ func (t *TargetBuilder) SelfTestExecute() error { return err } - if err := t.AppBuilder.SelfTestExecute(t.testPkg); err != nil { + testRpkg, err := t.getTestRpkg() + if err != nil { + return err + } + + if err := t.AppBuilder.SelfTestExecute(testRpkg); err != nil { return err } @@ -73,29 +110,27 @@ func (t *TargetBuilder) SelfTestDebug() error { return err } - lpkg := t.GetTestPkg() - if lpkg == nil { - panic("internal error: attempt to debug target builder with no test " + - "package") + testRpkg, err := t.getTestRpkg() + if err != nil { + return err } - bpkg := t.AppBuilder.PkgMap[lpkg] - if bpkg == nil { - panic("internal error: local package \"" + lpkg.FullName() + - "\" not built") + testBpkg, err := t.AppBuilder.getTestBpkg(testRpkg) + if err != nil { + return err } return t.AppBuilder.debugBin( - strings.TrimSuffix(t.AppBuilder.TestExePath(bpkg), ".elf"), + strings.TrimSuffix(t.AppBuilder.TestExePath(testBpkg), ".elf"), "", false, false) } -func (b *Builder) testOwner(p *BuildPackage) *BuildPackage { - if p.Type() != pkg.PACKAGE_TYPE_UNITTEST { - panic("Expected unittest package; got: " + p.Name()) +func (b *Builder) testOwner(bpkg *BuildPackage) *BuildPackage { + if bpkg.rpkg.Lpkg.Type() != pkg.PACKAGE_TYPE_UNITTEST { + panic("Expected unittest package; got: " + bpkg.rpkg.Lpkg.Name()) } - curPath := p.BasePath() + curPath := bpkg.rpkg.Lpkg.BasePath() for { parentPath := filepath.Dir(curPath) @@ -104,7 +139,9 @@ func (b *Builder) testOwner(p *BuildPackage) *BuildPackage { } parentPkg := b.pkgWithPath(parentPath) - if parentPkg != nil && parentPkg.Type() != pkg.PACKAGE_TYPE_UNITTEST { + if parentPkg != nil && + parentPkg.rpkg.Lpkg.Type() != pkg.PACKAGE_TYPE_UNITTEST { + return parentPkg } @@ -112,11 +149,10 @@ func (b *Builder) testOwner(p *BuildPackage) *BuildPackage { } } -func (b *Builder) SelfTestExecute(p *pkg.LocalPackage) error { - testBpkg := b.PkgMap[p] - if testBpkg == nil { - panic("internal error; package-under-test \"" + p.FullName() + - "\" not in builder") +func (b *Builder) SelfTestExecute(testRpkg *resolve.ResolvePackage) error { + testBpkg, err := b.getTestBpkg(testRpkg) + if err != nil { + return err } testPath := b.TestExePath(testBpkg) @@ -129,8 +165,8 @@ func (b *Builder) SelfTestExecute(p *pkg.LocalPackage) error { cmd := []string{testPath} if _, err := util.ShellCommand(cmd, nil); err != nil { newtError := err.(*util.NewtError) - newtError.Text = fmt.Sprintf("Test failure (%s):\n%s", p.Name(), - newtError.Text) + newtError.Text = fmt.Sprintf("Test failure (%s):\n%s", + testRpkg.Lpkg.Name(), newtError.Text) return newtError } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/builder/targetbuild.go ---------------------------------------------------------------------- diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go index 072e0b8..2bea6ef 100644 --- a/newt/builder/targetbuild.go +++ b/newt/builder/targetbuild.go @@ -98,19 +98,6 @@ func NewTargetBuilder(target *target.Target) (*TargetBuilder, error) { return NewTargetTester(target, nil) } -func (t *TargetBuilder) Builders() []*Builder { - builders := []*Builder{} - - if t.LoaderBuilder != nil { - builders = append(builders, t.LoaderBuilder) - } - if t.AppBuilder != nil { - builders = append(builders, t.AppBuilder) - } - - return builders -} - func (t *TargetBuilder) NewCompiler(dstDir string) ( *toolchain.Compiler, error) { @@ -217,12 +204,14 @@ func (t *TargetBuilder) generateSysinit() error { srcDir := GeneratedSrcDir(t.target.Name()) - if t.res.LoaderPkgs != nil { - sysinit.EnsureWritten(t.res.LoaderPkgs, srcDir, + if t.res.LoaderSet != nil { + lpkgs := resolve.RpkgSliceToLpkgSlice(t.res.LoaderSet.Rpkgs) + sysinit.EnsureWritten(lpkgs, srcDir, pkg.ShortName(t.target.Package()), true) } - sysinit.EnsureWritten(t.res.AppPkgs, srcDir, + lpkgs := resolve.RpkgSliceToLpkgSlice(t.res.AppSet.Rpkgs) + sysinit.EnsureWritten(lpkgs, srcDir, pkg.ShortName(t.target.Package()), false) return nil @@ -262,9 +251,9 @@ func (t *TargetBuilder) PrepBuild() error { } var err error - if t.res.LoaderPkgs != nil { + if t.res.LoaderSet != nil { t.LoaderBuilder, err = NewBuilder(t, BUILD_NAME_LOADER, - t.res.LoaderPkgs, t.res.ApiMap, t.res.Cfg) + t.res.LoaderSet.Rpkgs, t.res.ApiMap, t.res.Cfg) if err != nil { return err } @@ -279,7 +268,7 @@ func (t *TargetBuilder) PrepBuild() error { t.LoaderList = project.ResetDeps(nil) } - t.AppBuilder, err = NewBuilder(t, BUILD_NAME_APP, t.res.AppPkgs, + t.AppBuilder, err = NewBuilder(t, BUILD_NAME_APP, t.res.AppSet.Rpkgs, t.res.ApiMap, t.res.Cfg) if err != nil { return err @@ -288,7 +277,7 @@ func (t *TargetBuilder) PrepBuild() error { return err } - if t.res.LoaderPkgs != nil { + if t.res.LoaderSet != nil { appFlags := toolchain.NewCompilerInfo() appFlags.Cflags = append(appFlags.Cflags, "-DSPLIT_APPLICATION") t.AppBuilder.AddCompilerInfo(appFlags) @@ -296,7 +285,7 @@ func (t *TargetBuilder) PrepBuild() error { t.AppList = project.ResetDeps(nil) - logDepInfo(t.Builders()) + logDepInfo(t.res) if err := t.generateCode(); err != nil { return err @@ -400,12 +389,12 @@ func (t *TargetBuilder) RelinkLoader() (error, map[string]bool, /* fetch symbols from the elf and from the libraries themselves */ log.Debugf("Loader packages:") - for _, lpkg := range t.LoaderBuilder.sortedLocalPackages() { - log.Debugf(" * %s", lpkg.Name()) + for _, rpkg := range t.LoaderBuilder.sortedRpkgs() { + log.Debugf(" * %s", rpkg.Lpkg.Name()) } log.Debugf("App packages:") - for _, lpkg := range t.AppBuilder.sortedLocalPackages() { - log.Debugf(" * %s", lpkg.Name()) + for _, rpkg := range t.AppBuilder.sortedRpkgs() { + log.Debugf(" * %s", rpkg.Lpkg.Name()) } err, appLibSym := t.AppBuilder.ExtractSymbolInfo() if err != nil { @@ -439,14 +428,14 @@ func (t *TargetBuilder) RelinkLoader() (error, map[string]bool, uncommonPkgs := smNomatch.Packages() /* ensure that the loader and app packages are never shared */ - delete(commonPkgs, t.AppBuilder.appPkg.Name()) - uncommonPkgs[t.AppBuilder.appPkg.Name()] = true - ma := smMatch.FilterPkg(t.AppBuilder.appPkg.Name()) + delete(commonPkgs, t.AppBuilder.appPkg.rpkg.Lpkg.Name()) + uncommonPkgs[t.AppBuilder.appPkg.rpkg.Lpkg.Name()] = true + ma := smMatch.FilterPkg(t.AppBuilder.appPkg.rpkg.Lpkg.Name()) smMatch.RemoveMap(ma) - delete(commonPkgs, t.LoaderBuilder.appPkg.Name()) - uncommonPkgs[t.LoaderBuilder.appPkg.Name()] = true - ml := smMatch.FilterPkg(t.LoaderBuilder.appPkg.Name()) + delete(commonPkgs, t.LoaderBuilder.appPkg.rpkg.Lpkg.Name()) + uncommonPkgs[t.LoaderBuilder.appPkg.rpkg.Lpkg.Name()] = true + ml := smMatch.FilterPkg(t.LoaderBuilder.appPkg.rpkg.Lpkg.Name()) smMatch.RemoveMap(ml) util.StatusMessage(util.VERBOSITY_VERBOSE, @@ -457,9 +446,9 @@ func (t *TargetBuilder) RelinkLoader() (error, map[string]bool, var symbolStr string for v, _ := range uncommonPkgs { if t.AppBuilder.appPkg != nil && - t.AppBuilder.appPkg.Name() != v && + t.AppBuilder.appPkg.rpkg.Lpkg.Name() != v && t.LoaderBuilder.appPkg != nil && - t.LoaderBuilder.appPkg.Name() != v { + t.LoaderBuilder.appPkg.rpkg.Lpkg.Name() != v { trouble := smNomatch.FilterPkg(v) @@ -551,15 +540,15 @@ func (t *TargetBuilder) createManifest() error { } rm := image.NewRepoManager() - for _, lpkg := range t.AppBuilder.sortedLocalPackages() { + for _, rpkg := range t.AppBuilder.sortedRpkgs() { manifest.Pkgs = append(manifest.Pkgs, - rm.GetImageManifestPkg(lpkg)) + rm.GetImageManifestPkg(rpkg.Lpkg)) } if t.LoaderBuilder != nil { - for _, lpkg := range t.LoaderBuilder.sortedLocalPackages() { + for _, rpkg := range t.LoaderBuilder.sortedRpkgs() { manifest.LoaderPkgs = append(manifest.LoaderPkgs, - rm.GetImageManifestPkg(lpkg)) + rm.GetImageManifestPkg(rpkg.Lpkg)) } } @@ -676,9 +665,17 @@ func (t *TargetBuilder) CreateImages(version string, } func (t *TargetBuilder) CreateDepGraph() (DepGraph, error) { - return joinedDepGraph(t.Builders()) + if err := t.ensureResolved(); err != nil { + return nil, err + } + + return joinedDepGraph(t.res.Sets()) } func (t *TargetBuilder) CreateRevdepGraph() (DepGraph, error) { - return joinedRevdepGraph(t.Builders()) + if err := t.ensureResolved(); err != nil { + return nil, err + } + + return joinedRevdepGraph(t.res.Sets()) } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/cli/target_cmds.go ---------------------------------------------------------------------- diff --git a/newt/cli/target_cmds.go b/newt/cli/target_cmds.go index ded8183..54511fa 100644 --- a/newt/cli/target_cmds.go +++ b/newt/cli/target_cmds.go @@ -615,7 +615,8 @@ func targetDepCmd(cmd *cobra.Command, args []string) { NewtUsage(cmd, err) } - if err := b.PrepBuild(); err != nil { + res, err := b.Resolve() + if err != nil { NewtUsage(nil, err) } @@ -626,17 +627,17 @@ func targetDepCmd(cmd *cobra.Command, args []string) { // If user specified any package names, only include specified packages. if len(args) > 1 { - lpkgs, err := ResolvePackages(args[1:]) + rpkgs, err := ResolveRpkgs(res, args[1:]) if err != nil { NewtUsage(cmd, err) } - var missingLpkgs []*pkg.LocalPackage - dg, missingLpkgs = builder.FilterDepGraph(dg, lpkgs) - for _, lpkg := range missingLpkgs { + var missingRpkgs []*resolve.ResolvePackage + dg, missingRpkgs = builder.FilterDepGraph(dg, rpkgs) + for _, rpkg := range missingRpkgs { util.StatusMessage(util.VERBOSITY_QUIET, "Warning: Package \"%s\" not included in target \"%s\"\n", - lpkg.FullName(), b.GetTarget().FullName()) + rpkg.Lpkg.FullName(), b.GetTarget().FullName()) } } @@ -658,7 +659,8 @@ func targetRevdepCmd(cmd *cobra.Command, args []string) { NewtUsage(cmd, err) } - if err := b.PrepBuild(); err != nil { + res, err := b.Resolve() + if err != nil { NewtUsage(nil, err) } @@ -669,17 +671,17 @@ func targetRevdepCmd(cmd *cobra.Command, args []string) { // If user specified any package names, only include specified packages. if len(args) > 1 { - lpkgs, err := ResolvePackages(args[1:]) + rpkgs, err := ResolveRpkgs(res, args[1:]) if err != nil { NewtUsage(cmd, err) } - var missingLpkgs []*pkg.LocalPackage - dg, missingLpkgs = builder.FilterDepGraph(dg, lpkgs) - for _, lpkg := range missingLpkgs { + var missingRpkgs []*resolve.ResolvePackage + dg, missingRpkgs = builder.FilterDepGraph(dg, rpkgs) + for _, rpkg := range missingRpkgs { util.StatusMessage(util.VERBOSITY_QUIET, "Warning: Package \"%s\" not included in target \"%s\"\n", - lpkg.FullName(), b.GetTarget().FullName()) + rpkg.Lpkg.FullName(), b.GetTarget().FullName()) } } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/cli/util.go ---------------------------------------------------------------------- diff --git a/newt/cli/util.go b/newt/cli/util.go index 0ab578e..e9c0b4c 100644 --- a/newt/cli/util.go +++ b/newt/cli/util.go @@ -35,6 +35,7 @@ import ( "mynewt.apache.org/newt/newt/newtutil" "mynewt.apache.org/newt/newt/pkg" "mynewt.apache.org/newt/newt/project" + "mynewt.apache.org/newt/newt/resolve" "mynewt.apache.org/newt/newt/target" "mynewt.apache.org/newt/util" ) @@ -296,6 +297,28 @@ func ResolvePackages(pkgNames []string) ([]*pkg.LocalPackage, error) { return lpkgs, nil } +func ResolveRpkgs(res *resolve.Resolution, pkgNames []string) ( + []*resolve.ResolvePackage, error) { + + lpkgs, err := ResolvePackages(pkgNames) + if err != nil { + return nil, err + } + + rpkgs := []*resolve.ResolvePackage{} + for _, lpkg := range lpkgs { + rpkg := res.LpkgRpkgMap[lpkg] + if rpkg == nil { + return nil, util.FmtNewtError("Unexpected error; local package "+ + "%s lacks a corresponding resolve package", lpkg.FullName()) + } + + rpkgs = append(rpkgs, rpkg) + } + + return rpkgs, nil +} + func TargetBuilderForTargetOrUnittest(pkgName string) ( *builder.TargetBuilder, error) { http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/pkg/localpackage.go ---------------------------------------------------------------------- diff --git a/newt/pkg/localpackage.go b/newt/pkg/localpackage.go index b34bd59..8c935b1 100644 --- a/newt/pkg/localpackage.go +++ b/newt/pkg/localpackage.go @@ -61,9 +61,6 @@ type LocalPackage struct { // General information about the package desc *PackageDesc - // Dependencies for this package - deps map[string]*Dependency - // Package init function name and stage. These are used to generate the // sysinit C file. init map[string]int @@ -89,7 +86,6 @@ func NewLocalPackage(r *repo.Repo, pkgDir string) *LocalPackage { SyscfgV: viper.New(), repo: r, basePath: filepath.ToSlash(filepath.Clean(pkgDir)), - deps: map[string]*Dependency{}, init: map[string]int{}, injectedSettings: map[string]string{}, } @@ -196,34 +192,6 @@ func (pkg *LocalPackage) AddCfgFilename(cfgFilename string) { pkg.cfgFilenames = append(pkg.cfgFilenames, cfgFilename) } -func (pkg *LocalPackage) HasDep(searchDep *Dependency) bool { - return pkg.deps[searchDep.String()] != nil -} - -func (pkg *LocalPackage) AddDep(dep *Dependency) bool { - if pkg.deps[dep.String()] != nil { - return false - } - - pkg.deps[dep.String()] = dep - return true -} - -func (pkg *LocalPackage) Deps() []*Dependency { - names := make([]string, 0, len(pkg.deps)) - for name, _ := range pkg.deps { - names = append(names, name) - } - sort.Strings(names) - - deps := make([]*Dependency, len(names)) - for i, name := range names { - deps[i] = pkg.deps[name] - } - - return deps -} - func (pkg *LocalPackage) readDesc(v *viper.Viper) (*PackageDesc, error) { pdesc := &PackageDesc{} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/pkg/package.go ---------------------------------------------------------------------- diff --git a/newt/pkg/package.go b/newt/pkg/package.go index 03795cb..d5d9403 100644 --- a/newt/pkg/package.go +++ b/newt/pkg/package.go @@ -75,8 +75,6 @@ type Package interface { Hash() (string, error) // Description of this package Desc() *PackageDesc - // Dependency list for this package - Deps() []*Dependency // APIs exported by this package Apis() []string // APIs required by this package http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/resolve/resolve.go ---------------------------------------------------------------------- diff --git a/newt/resolve/resolve.go b/newt/resolve/resolve.go index 916f38c..c4a1d38 100644 --- a/newt/resolve/resolve.go +++ b/newt/resolve/resolve.go @@ -42,8 +42,19 @@ type Resolver struct { cfg syscfg.Cfg } +type ResolveDep struct { + // Package being depended on. + Rpkg *ResolvePackage + + // Name of API that generated the dependency; "" if a hard dependency. + Api string + + // XXX: slice of syscfg settings that generated this dependency. +} + type ResolvePackage struct { - *pkg.LocalPackage + Lpkg *pkg.LocalPackage + Deps map[*ResolvePackage]*ResolveDep // Keeps track of API requirements and whether they are satisfied. reqApiMap map[string]bool @@ -52,14 +63,23 @@ type ResolvePackage struct { apisSatisfied bool } +type ResolveSet struct { + // Parent resoluion. Contains this ResolveSet. + Res *Resolution + + // All seed pacakges and their dependencies. + Rpkgs []*ResolvePackage +} + // The result of resolving a target's configuration, APIs, and dependencies. type Resolution struct { Cfg syscfg.Cfg - ApiMap map[string]*pkg.LocalPackage - UnsatisfiedApis map[string][]*pkg.LocalPackage + ApiMap map[string]*ResolvePackage + UnsatisfiedApis map[string][]*ResolvePackage - LoaderPkgs []*pkg.LocalPackage - AppPkgs []*pkg.LocalPackage + LpkgRpkgMap map[*pkg.LocalPackage]*ResolvePackage + LoaderSet *ResolveSet + AppSet *ResolveSet } func newResolver( @@ -86,23 +106,80 @@ func newResolver( return r } -func newResolvePkg(lpkg *pkg.LocalPackage) *ResolvePackage { +func newResolution() *Resolution { + r := &Resolution{ + ApiMap: map[string]*ResolvePackage{}, + UnsatisfiedApis: map[string][]*ResolvePackage{}, + } + + r.LoaderSet = &ResolveSet{Res: r} + r.AppSet = &ResolveSet{Res: r} + + return r +} + +func (res *Resolution) Sets() []*ResolveSet { + rss := []*ResolveSet{} + + if res.LoaderSet != nil { + rss = append(rss, res.LoaderSet) + } + if res.AppSet != nil { + rss = append(rss, res.AppSet) + } + + return rss +} + +func NewResolvePkg(lpkg *pkg.LocalPackage) *ResolvePackage { return &ResolvePackage{ - LocalPackage: lpkg, - reqApiMap: map[string]bool{}, + Lpkg: lpkg, + reqApiMap: map[string]bool{}, + Deps: map[*ResolvePackage]*ResolveDep{}, } } -func (r *Resolver) lpkgSlice() []*pkg.LocalPackage { - lpkgs := make([]*pkg.LocalPackage, len(r.pkgMap)) +func (r *Resolver) resolveDep(dep *pkg.Dependency) (*pkg.LocalPackage, error) { + proj := project.GetProject() + + lpkg := proj.ResolveDependency(dep).(*pkg.LocalPackage) + if lpkg == nil { + return nil, util.FmtNewtError("Could not resolve package dependency: "+ + "%s; depender: %s", dep.String(), dep.Name) + } + + return lpkg, nil +} + +// @return true if rhe package's dependency list was +// modified. +func (rpkg *ResolvePackage) AddDep(apiPkg *ResolvePackage, api string) bool { + if dep := rpkg.Deps[apiPkg]; dep != nil { + if dep.Api != "" && api == "" { + dep.Api = api + return true + } else { + return false + } + } else { + rpkg.Deps[apiPkg] = &ResolveDep{ + Rpkg: apiPkg, + Api: api, + } + return true + } +} + +func (r *Resolver) rpkgSlice() []*ResolvePackage { + rpkgs := make([]*ResolvePackage, len(r.pkgMap)) i := 0 for _, rpkg := range r.pkgMap { - lpkgs[i] = rpkg.LocalPackage + rpkgs[i] = rpkg i++ } - return lpkgs + return rpkgs } func (r *Resolver) apiSlice() []string { @@ -117,14 +194,18 @@ func (r *Resolver) apiSlice() []string { return apis } -// @return bool true if this is a new package. -func (r *Resolver) addPkg(lpkg *pkg.LocalPackage) bool { +// @return ResolvePackage The rpkg corresponding to the specified lpkg. +// This is a new package if a package was +// added; old if it was already present. +// bool true if this is a new package. +func (r *Resolver) addPkg(lpkg *pkg.LocalPackage) (*ResolvePackage, bool) { if rpkg := r.pkgMap[lpkg]; rpkg != nil { - return false + return rpkg, false } - r.pkgMap[lpkg] = newResolvePkg(lpkg) - return true + rpkg := NewResolvePkg(lpkg) + r.pkgMap[lpkg] = rpkg + return rpkg, true } // @return bool true if this is a new API. @@ -137,7 +218,7 @@ func (r *Resolver) addApi(apiString string, rpkg *ResolvePackage) bool { if curRpkg != rpkg { util.StatusMessage(util.VERBOSITY_QUIET, "Warning: API conflict: %s (%s <-> %s)\n", apiString, - curRpkg.Name(), rpkg.Name()) + curRpkg.Lpkg.Name(), rpkg.Lpkg.Name()) } return false } @@ -146,6 +227,8 @@ func (r *Resolver) addApi(apiString string, rpkg *ResolvePackage) bool { // Searches for a package which can satisfy bpkg's API requirement. If such a // package is found, bpkg's API requirement is marked as satisfied, and the // package is added to bpkg's dependency list. +// +// @return bool true if the API is now satisfied. func (r *Resolver) satisfyApi(rpkg *ResolvePackage, reqApi string) bool { depRpkg := r.apis[reqApi] if depRpkg == nil { @@ -160,7 +243,7 @@ func (r *Resolver) satisfyApi(rpkg *ResolvePackage, reqApi string) bool { rpkg.depsResolved = false log.Debugf("API requirement satisfied; pkg=%s API=(%s, %s)", - rpkg.Name(), reqApi, depRpkg.FullName()) + rpkg.Lpkg.Name(), reqApi, depRpkg.Lpkg.FullName()) return true } @@ -174,11 +257,11 @@ func (r *Resolver) satisfyApis(rpkg *ResolvePackage) bool { rpkg.apisSatisfied = true newDeps := false - features := r.cfg.FeaturesForLpkg(rpkg.LocalPackage) + features := r.cfg.FeaturesForLpkg(rpkg.Lpkg) // Determine if any of the package's API requirements can now be satisfied. // If so, another full iteration is required. - reqApis := newtutil.GetStringSliceFeatures(rpkg.PkgV, features, + reqApis := newtutil.GetStringSliceFeatures(rpkg.Lpkg.PkgV, features, "pkg.req_apis") for _, reqApi := range reqApis { reqStatus := rpkg.reqApiMap[reqApi] @@ -204,39 +287,34 @@ func (r *Resolver) satisfyApis(rpkg *ResolvePackage) bool { // in this case. // error non-nil on failure. func (r *Resolver) loadDepsForPkg(rpkg *ResolvePackage) (bool, error) { - proj := project.GetProject() - features := r.cfg.FeaturesForLpkg(rpkg.LocalPackage) + features := r.cfg.FeaturesForLpkg(rpkg.Lpkg) changed := false - newDeps := newtutil.GetStringSliceFeatures(rpkg.PkgV, features, "pkg.deps") + newDeps := newtutil.GetStringSliceFeatures(rpkg.Lpkg.PkgV, features, + "pkg.deps") for _, newDepStr := range newDeps { - newDep, err := pkg.NewDependency(rpkg.Repo(), newDepStr) + newDep, err := pkg.NewDependency(rpkg.Lpkg.Repo(), newDepStr) if err != nil { return false, err } - lpkg, ok := proj.ResolveDependency(newDep).(*pkg.LocalPackage) - if !ok { - return false, - util.FmtNewtError("Could not resolve package dependency: "+ - "%s; depender: %s", newDep.String(), rpkg.FullName()) - } - - if r.addPkg(lpkg) { - changed = true + lpkg, err := r.resolveDep(newDep) + if err != nil { + return false, err } - if rpkg.AddDep(newDep) { + depRpkg, _ := r.addPkg(lpkg) + if rpkg.AddDep(depRpkg, "") { changed = true } } // Determine if this package supports any APIs that we haven't seen // yet. If so, another full iteration is required. - apis := newtutil.GetStringSliceFeatures(rpkg.PkgV, features, "pkg.apis") + apis := newtutil.GetStringSliceFeatures(rpkg.Lpkg.PkgV, features, + "pkg.apis") for _, api := range apis { - newApi := r.addApi(api, rpkg) - if newApi { + if r.addApi(api, rpkg) { changed = true } } @@ -278,7 +356,7 @@ func (r *Resolver) resolvePkg(rpkg *ResolvePackage) (bool, error) { // @return changed,err func (r *Resolver) reloadCfg() (bool, error) { - lpkgs := r.lpkgSlice() + lpkgs := RpkgSliceToLpkgSlice(r.rpkgSlice()) apis := r.apiSlice() // Determine which features have been detected so far. The feature map is @@ -330,7 +408,7 @@ func (r *Resolver) resolveDepsOnce() (bool, error) { return newDeps, nil } -func (r *Resolver) resolveDeps() ([]*pkg.LocalPackage, error) { +func (r *Resolver) resolveDeps() ([]*ResolvePackage, error) { if _, err := r.resolveDepsOnce(); err != nil { return nil, err } @@ -340,8 +418,8 @@ func (r *Resolver) resolveDeps() ([]*pkg.LocalPackage, error) { return nil, err } - lpkgs := r.lpkgSlice() - return lpkgs, nil + rpkgs := r.rpkgSlice() + return rpkgs, nil } func (r *Resolver) resolveDepsAndCfg() error { @@ -393,15 +471,8 @@ func (r *Resolver) resolveApiDeps() error { for _, rpkg := range r.pkgMap { for api, _ := range rpkg.reqApiMap { apiPkg := r.apis[api] - if apiPkg == nil { - //return util.FmtNewtError( - //"Unsatisfied API at unexpected time: %s", api) - } else { - - rpkg.AddDep(&pkg.Dependency{ - Name: apiPkg.Name(), - Repo: apiPkg.Repo().Name(), - }) + if apiPkg != nil { + rpkg.AddDep(apiPkg, api) } } } @@ -410,26 +481,26 @@ func (r *Resolver) resolveApiDeps() error { } func (r *Resolver) apiResolution() ( - map[string]*pkg.LocalPackage, - map[string][]*pkg.LocalPackage) { + map[string]*ResolvePackage, + map[string][]*ResolvePackage) { - apiMap := make(map[string]*pkg.LocalPackage, len(r.apis)) + apiMap := make(map[string]*ResolvePackage, len(r.apis)) anyUnsatisfied := false for api, rpkg := range r.apis { if rpkg == nil { anyUnsatisfied = true } else { - apiMap[api] = rpkg.LocalPackage + apiMap[api] = rpkg } } - unsatisfied := map[string][]*pkg.LocalPackage{} + unsatisfied := map[string][]*ResolvePackage{} if anyUnsatisfied { for _, rpkg := range r.pkgMap { for api, satisfied := range rpkg.reqApiMap { if !satisfied { slice := unsatisfied[api] - slice = append(slice, rpkg.LocalPackage) + slice = append(slice, rpkg) unsatisfied[api] = slice } } @@ -458,7 +529,7 @@ func ResolveFull( return nil, err } - res := &Resolution{} + res := newResolution() res.Cfg = r.cfg if err := r.resolveApiDeps(); err != nil { return nil, err @@ -466,14 +537,17 @@ func ResolveFull( // Determine which package satisfies each API and which APIs are // unsatisfied. - apiMap := map[string]*pkg.LocalPackage{} + apiMap := map[string]*ResolvePackage{} apiMap, res.UnsatisfiedApis = r.apiResolution() + res.LpkgRpkgMap = r.pkgMap + // If there is no loader, then the set of all packages is just the app // packages. We already resolved the necessary dependency information when // syscfg was calculated above. if loaderSeeds == nil { - res.AppPkgs = r.lpkgSlice() + res.AppSet.Rpkgs = r.rpkgSlice() + res.LoaderSet = nil return res, nil } @@ -486,9 +560,9 @@ func ResolveFull( // It is OK if the app requires an API that is supplied by the loader. // Ensure each set of packages has access to the API-providers. - for _, lpkg := range apiMap { - loaderSeeds = append(loaderSeeds, lpkg) - appSeeds = append(appSeeds, lpkg) + for _, rpkg := range apiMap { + loaderSeeds = append(loaderSeeds, rpkg.Lpkg) + appSeeds = append(appSeeds, rpkg.Lpkg) } // Resolve loader dependencies. @@ -497,23 +571,23 @@ func ResolveFull( var err error - res.LoaderPkgs, err = r.resolveDeps() + res.LoaderSet.Rpkgs, err = r.resolveDeps() if err != nil { return nil, err } // Resolve app dependencies. The app automtically gets all the packages // from the loader except for the loader-app-package. - for _, lpkg := range res.LoaderPkgs { - if lpkg.Type() != pkg.PACKAGE_TYPE_APP { - appSeeds = append(appSeeds, lpkg) + for _, rpkg := range res.LoaderSet.Rpkgs { + if rpkg.Lpkg.Type() != pkg.PACKAGE_TYPE_APP { + appSeeds = append(appSeeds, rpkg.Lpkg) } } r = newResolver(appSeeds, injectedSettings, flashMap) r.cfg = res.Cfg - res.AppPkgs, err = r.resolveDeps() + res.AppSet.Rpkgs, err = r.resolveDeps() if err != nil { return nil, err } @@ -535,10 +609,10 @@ func (res *Resolution) ErrorText() string { for _, api := range apiNames { str += fmt.Sprintf(" * %s, required by: ", api) - pkgs := res.UnsatisfiedApis[api] - pkgNames := make([]string, len(pkgs)) - for i, lpkg := range pkgs { - pkgNames[i] = lpkg.Name() + rpkgs := res.UnsatisfiedApis[api] + pkgNames := make([]string, len(rpkgs)) + for i, rpkg := range rpkgs { + pkgNames[i] = rpkg.Lpkg.Name() } sort.Strings(pkgNames) http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/e4ac2617/newt/resolve/resolveutil.go ---------------------------------------------------------------------- diff --git a/newt/resolve/resolveutil.go b/newt/resolve/resolveutil.go new file mode 100644 index 0000000..23884d3 --- /dev/null +++ b/newt/resolve/resolveutil.go @@ -0,0 +1,92 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. + */ + +package resolve + +import ( + "sort" + + "mynewt.apache.org/newt/newt/pkg" +) + +type rpkgSorter struct { + pkgs []*ResolvePackage +} + +func (s rpkgSorter) Len() int { + return len(s.pkgs) +} +func (s rpkgSorter) Swap(i, j int) { + s.pkgs[i], s.pkgs[j] = s.pkgs[j], s.pkgs[i] +} +func (s rpkgSorter) Less(i, j int) bool { + return s.pkgs[i].Lpkg.FullName() < s.pkgs[j].Lpkg.FullName() +} + +func SortResolvePkgs(pkgs []*ResolvePackage) []*ResolvePackage { + sorter := rpkgSorter{ + pkgs: make([]*ResolvePackage, 0, len(pkgs)), + } + + for _, p := range pkgs { + sorter.pkgs = append(sorter.pkgs, p) + } + + sort.Sort(sorter) + return sorter.pkgs +} + +type rdepSorter struct { + deps []*ResolveDep +} + +func (s rdepSorter) Len() int { + return len(s.deps) +} +func (s rdepSorter) Swap(i, j int) { + s.deps[i], s.deps[j] = s.deps[j], s.deps[i] +} + +func (s rdepSorter) Less(i, j int) bool { + return s.deps[i].Rpkg.Lpkg.FullName() < s.deps[j].Rpkg.Lpkg.FullName() +} +func SortResolveDeps(deps []*ResolveDep) []*ResolveDep { + sorter := rdepSorter{ + deps: make([]*ResolveDep, 0, len(deps)), + } + + for _, d := range deps { + sorter.deps = append(sorter.deps, d) + } + + sort.Sort(sorter) + return sorter.deps +} + +func RpkgSliceToLpkgSlice(rpkgs []*ResolvePackage) []*pkg.LocalPackage { + lpkgs := make([]*pkg.LocalPackage, len(rpkgs)) + + i := 0 + for _, rpkg := range rpkgs { + lpkgs[i] = rpkg.Lpkg + i++ + } + + return lpkgs +}