| /* |
| 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 |
| } |