blob: 43d4612f7eaaa5564face1638775e686b9077adb [file] [log] [blame]
/*
Copyright 2015 Runtime Inc.
Licensed 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 cli
import (
"log"
"os"
)
// Recursively iterates through a package's dependencies, adding each package
// encountered to the supplied set.
func collectDepsAux(em *EggMgr, egg *Egg, set *map[*Egg]bool) error {
if (*set)[egg] {
return nil
}
(*set)[egg] = true
for _, dep := range egg.Deps {
if dep.Name == "" {
break
}
// Get package structure
degg, err := em.ResolveEggName(dep.Name)
if err != nil {
return err
}
collectDepsAux(em, degg, set)
}
return nil
}
// Recursively iterates through a package's dependencies. The resulting array
// contains a pointer to each encountered package.
func collectDeps(em *EggMgr, egg *Egg) ([]*Egg, error) {
set := map[*Egg]bool{}
err := collectDepsAux(em, egg, &set)
if err != nil {
return nil, err
}
arr := []*Egg{}
for p, _ := range set {
arr = append(arr, p)
}
return arr, nil
}
// Calculates the include paths exported by the specified package and all of
// its recursive dependencies.
func recursiveIncludePaths(em *EggMgr, egg *Egg,
t *Target) ([]string, error) {
deps, err := collectDeps(em, egg)
if err != nil {
return nil, err
}
incls := []string{}
for _, p := range deps {
eggIncls, err := p.GetIncludes(t)
if err != nil {
return nil, err
}
incls = append(incls, eggIncls...)
}
return incls, nil
}
// Calculates the include paths exported by the specified target's BSP and all
// of its recursive dependencies.
func BspIncludePaths(em *EggMgr, t *Target) ([]string, error) {
if t.Bsp == "" {
return nil, NewNewtError("Expected a BSP")
}
bspEgg, err := em.ResolveEggName(t.Bsp)
if err != nil {
return nil, NewNewtError("No BSP package for " + t.Bsp + " exists")
}
return recursiveIncludePaths(em, bspEgg, t)
}
func buildBsp(t *Target, em *EggMgr, incls *[]string,
libs *[]string) (string, error) {
if t.Bsp == "" {
return "", NewNewtError("Expected a BSP")
}
bspEgg, err := em.ResolveEggName(t.Bsp)
if err != nil {
return "", NewNewtError("No BSP package for " + t.Bsp + " exists")
}
if err = em.Build(t, t.Bsp, *incls, libs); err != nil {
return "", err
}
// A BSP doesn't have to contain source; don't fail if no library was
// built.
if lib := em.GetEggLib(t, bspEgg); NodeExist(lib) {
*libs = append(*libs, lib)
}
var linkerScript string
if bspEgg.LinkerScript != "" {
linkerScript = bspEgg.BasePath + "/" + bspEgg.LinkerScript
} else {
linkerScript = ""
}
return linkerScript, nil
}
// Creates the set of compiler flags that should be specified when building a
// particular target-entity pair. The "entity" is what is being built; either
// a package or a project.
func CreateCflags(em *EggMgr, c *Compiler, t *Target,
entityCflags string) string {
cflags := c.Cflags + " " + entityCflags + " " + t.Cflags
// The 'test' identity causes the TEST symbol to be defined. This allows
// package code to behave differently in test builds.
if t.HasIdentity("test") {
cflags += " -DTEST"
}
cflags += " -DARCH_" + t.Arch
// If a non-BSP package is being built, add the BSP's C flags to the list.
// The BSP's compiler flags get exported to all packages.
bspEgg, err := em.ResolveEggName(t.Bsp)
if err == nil && bspEgg.Cflags != entityCflags {
cflags += " " + bspEgg.Cflags
}
return cflags
}
func EggIncludeDirs(egg *Egg, t *Target) []string {
srcDir := egg.BasePath + "/src/"
incls := egg.Includes
incls = append(incls, srcDir)
incls = append(incls, srcDir+"/arch/"+t.Arch)
if t.HasIdentity("test") {
testSrcDir := srcDir + "/test"
incls = append(incls, testSrcDir)
incls = append(incls, testSrcDir+"/arch/"+t.Arch)
}
return incls
}
// Recursively compiles all the .c and .s files in the specified directory.
// Architecture-specific files are also compiled.
func BuildDir(srcDir string, c *Compiler, t *Target, ignDirs []string) error {
var err error
log.Printf("[DEBUG] compiling src in base directory: %s", srcDir)
// First change into the package src directory, and build all the objects
// there
os.Chdir(srcDir)
// Don't recurse into destination directories.
ignDirs = append(ignDirs, "obj")
ignDirs = append(ignDirs, "bin")
// Ignore architecture-specific source files for now. Use a temporary
// string array here so that the "arch" director is not ignored in the
// subsequent architecture-specific compile phase.
baseIgnDirs := append(ignDirs, "arch")
if err = c.RecursiveCompile("*.c", 0, baseIgnDirs); err != nil {
return err
}
log.Printf("[DEBUG] compiling architecture specific src packages")
archDir := srcDir + "/arch/" + t.Arch + "/"
if NodeExist(archDir) {
if err := os.Chdir(archDir); err != nil {
return NewNewtError(err.Error())
}
if err := c.RecursiveCompile("*.c", 0, ignDirs); err != nil {
return err
}
// compile assembly sources in recursive compile as well
if err = c.RecursiveCompile("*.s", 1, ignDirs); err != nil {
return err
}
}
return nil
}