func (t *TargetBuilder) PrepBuild() error { cfgResolution, err := t.ExportCfg() if err != nil { return err } flashErrText := t.bspPkg.FlashMap.ErrorText() if flashErrText != "" { return util.NewNewtError(flashErrText) } if err := t.validateAndWriteCfg(cfgResolution); err != nil { return err } loaderPkgs, appPkgs, err := t.resolvePkgs(cfgResolution) if err != nil { return err } if loaderPkgs != nil { t.LoaderBuilder, err = NewBuilder(t, BUILD_NAME_LOADER, loaderPkgs, cfgResolution.ApiMap, cfgResolution.Cfg) if err != nil { return err } if err := t.LoaderBuilder.PrepBuild(); err != nil { return err } loaderFlags := toolchain.NewCompilerInfo() loaderFlags.Cflags = append(loaderFlags.Cflags, "-DSPLIT_LOADER") t.LoaderBuilder.AddCompilerInfo(loaderFlags) t.LoaderList = project.ResetDeps(nil) } t.AppBuilder, err = NewBuilder(t, BUILD_NAME_APP, appPkgs, cfgResolution.ApiMap, cfgResolution.Cfg) if err != nil { return err } if err := t.AppBuilder.PrepBuild(); err != nil { return err } if loaderPkgs != nil { appFlags := toolchain.NewCompilerInfo() appFlags.Cflags = append(appFlags.Cflags, "-DSPLIT_APPLICATION") t.AppBuilder.AddCompilerInfo(appFlags) } t.AppList = project.ResetDeps(nil) if err := t.generateCode(cfgResolution); err != nil { return err } return nil }
func (t *TargetBuilder) buildLoader() error { /* Link the app as a test (using the normal single image linker script) */ if err := t.AppBuilder.TestLink(t.bspPkg.LinkerScripts); err != nil { return err } /* rebuild the loader */ project.ResetDeps(t.LoaderList) if err := t.bspPkg.Reload(t.LoaderBuilder.cfg.Features()); err != nil { return err } if err := t.LoaderBuilder.Build(); err != nil { return err } /* perform a test link of the loader */ if err := t.LoaderBuilder.TestLink(t.bspPkg.LinkerScripts); err != nil { return err } /* re-link the loader with app dependencies */ err, commonPkgs, commonSyms := t.RelinkLoader() if err != nil { return err } /* The app can ignore these packages next time */ delete(commonPkgs, t.bspPkg.Name()) t.AppBuilder.RemovePackages(commonPkgs) /* create the special elf to link the app against */ /* its just the elf with a set of symbols removed and renamed */ err = t.LoaderBuilder.buildRomElf(commonSyms) if err != nil { return err } /* set up the linker elf and linker script for the app */ t.AppBuilder.linkElf = t.LoaderBuilder.AppLinkerElfPath() return nil }
func (t *TargetBuilder) Build() error { if err := t.PrepBuild(); err != nil { return err } /* Build the Apps */ project.ResetDeps(t.AppList) if err := t.bspPkg.Reload(t.AppBuilder.cfg.Features()); err != nil { return err } if err := t.AppBuilder.Build(); err != nil { return err } var linkerScripts []string if t.LoaderBuilder == nil { linkerScripts = t.bspPkg.LinkerScripts } else { if err := t.buildLoader(); err != nil { return err } linkerScripts = t.bspPkg.Part2LinkerScripts } /* Link the app. */ if err := t.AppBuilder.Link(linkerScripts); err != nil { return err } /* Create manifest. */ if err := t.createManifest(); err != nil { return err } return nil }
/* * This function re-links the loader adding symbols from libraries * shared with the app. Returns a list of the common packages shared * by the app and loader */ func (t *TargetBuilder) RelinkLoader() (error, map[string]bool, *symbol.SymbolMap) { /* 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()) } log.Debugf("App packages:") for _, lpkg := range t.AppBuilder.sortedLocalPackages() { log.Debugf(" * %s", lpkg.Name()) } err, appLibSym := t.AppBuilder.ExtractSymbolInfo() if err != nil { return err, nil, nil } /* fetch the symbol list from the app temporary elf */ err, appElfSym := t.AppBuilder.ParseObjectElf(t.AppBuilder.AppTempElfPath()) if err != nil { return err, nil, nil } /* extract the library symbols and elf symbols from the loader */ err, loaderLibSym := t.LoaderBuilder.ExtractSymbolInfo() if err != nil { return err, nil, nil } err, loaderElfSym := t.LoaderBuilder.ParseObjectElf( t.LoaderBuilder.AppTempElfPath()) if err != nil { return err, nil, nil } /* create the set of matching and non-matching symbols */ err, smMatch, smNomatch := symbol.IdenticalUnion(appLibSym, loaderLibSym, true, false) /* which packages are shared between the two */ commonPkgs := smMatch.Packages() 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()) smMatch.RemoveMap(ma) delete(commonPkgs, t.LoaderBuilder.appPkg.Name()) uncommonPkgs[t.LoaderBuilder.appPkg.Name()] = true ml := smMatch.FilterPkg(t.LoaderBuilder.appPkg.Name()) smMatch.RemoveMap(ml) util.StatusMessage(util.VERBOSITY_VERBOSE, "Putting %d symbols from %d packages into loader\n", len(*smMatch), len(commonPkgs)) /* This is worth a special comment. We are building both apps as * stand-alone apps against the normal linker file, so they will both * have a Reset_Handler symbol. We need to ignore this here. When * we build the split app, we use a special linker file which * uses a different entry point */ specialSm := symbol.NewSymbolMap() specialSm.Add(*symbol.NewElfSymbol("Reset_Handler(app)")) specialSm.Add(*symbol.NewElfSymbol("Reset_Handler(loader)")) var badpkgs []string var symbolStr string for v, _ := range uncommonPkgs { if t.AppBuilder.appPkg != nil && t.AppBuilder.appPkg.Name() != v && t.LoaderBuilder.appPkg != nil && t.LoaderBuilder.appPkg.Name() != v { trouble := smNomatch.FilterPkg(v) var found bool for _, sym := range *trouble { if _, ok := specialSm.Find(sym.Name); !ok { if !sym.IsLocal() { found = true } } } if found { symbolStr = (*trouble).String("Non Matching Symbols") badpkgs = append(badpkgs, v) delete(commonPkgs, v) } } } if len(badpkgs) > 0 { errStr := fmt.Sprintf( "Common packages with different implementation\n %s\n", strings.Join(badpkgs, "\n ")) errStr += symbolStr return util.NewNewtError(errStr), nil, nil } /* for each symbol in the elf of the app, if that symbol is in * a common package, keep that symbol in the loader */ preserveElf := symbol.NewSymbolMap() /* go through each symbol in the app */ for _, elfsym := range *appElfSym { name := elfsym.Name if libsym, ok := (*appLibSym)[name]; ok { if _, ok := commonPkgs[libsym.Bpkg]; ok { /* if its not in the loader elf, add it as undefined */ if _, ok := (*loaderElfSym)[name]; !ok { preserveElf.Add(elfsym) } } } } /* re-link loader */ project.ResetDeps(t.LoaderList) util.StatusMessage(util.VERBOSITY_VERBOSE, "Migrating %d unused symbols into Loader\n", len(*preserveElf)) err = t.LoaderBuilder.KeepLink(t.bspPkg.LinkerScripts, preserveElf) if err != nil { return err, nil, nil } return err, commonPkgs, smMatch }