// setPathHelper is a utility function for setting path environment // variables for different types of workspaces. func setPathHelper(ctx *tool.Context, env *envvar.Vars, name, root string, workspaces []string, suffix string) error { path := env.GetTokens(name, ":") projects, _, err := project.ReadManifest(ctx) if err != nil { return err } for _, workspace := range workspaces { absWorkspace := filepath.Join(root, workspace, suffix) // Only append an entry to the path if the workspace is rooted // under a jiri project that exists locally or vice versa. for _, project := range projects { // We check if <project.Path> is a prefix of <absWorkspace> to // account for Go workspaces nested under a single jiri project, // such as: $JIRI_ROOT/release/projects/chat/go. // // We check if <absWorkspace> is a prefix of <project.Path> to // account for Go workspaces that span multiple jiri projects, // such as: $JIRI_ROOT/release/go. if strings.HasPrefix(absWorkspace, project.Path) || strings.HasPrefix(project.Path, absWorkspace) { if _, err := ctx.Run().Stat(filepath.Join(absWorkspace)); err == nil { path = append(path, absWorkspace) break } } } } env.SetTokens(name, path, ":") return nil }
// setJavaEnv sets the environment variables used for building a Go // shared library that is invoked from Java code. If Java is not // installed on the host, this function is a no-op. func setJavaEnv(ctx *tool.Context, env *envvar.Vars, root string) error { jdkHome := os.Getenv(javaEnv) if jdkHome == "" { return nil } cflags := env.GetTokens("CGO_CFLAGS", " ") cflags = append(cflags, filepath.Join("-I"+jdkHome, "include"), filepath.Join("-I"+jdkHome, "include", runtime.GOOS)) env.SetTokens("CGO_CFLAGS", cflags, " ") return nil }
// ExpandEnv expands all instances of the JIRI_ROOT variable in the supplied // environment with the root from jirix. func ExpandEnv(x *X, env *envvar.Vars) { e := env.ToMap() rootEnv := "${" + RootEnv + "}" for k, v := range e { n := strings.Replace(v, rootEnv, x.Root, -1) if n != v { env.Set(k, n) } } }
// MergeEnvFromProfiles merges the environment variables stored in the specified // profiles and target with the env parameter. It uses MergeEnv to do so. func MergeEnvFromProfiles(concat map[string]string, ignore map[string]bool, env *envvar.Vars, target Target, profileNames ...string) ([]string, error) { vars := [][]string{} for _, name := range profileNames { t := LookupProfileTarget(name, target) if t == nil { return nil, fmt.Errorf("failed to lookup %v --target=%v", name, target) } vars = append(vars, t.Env.Vars) } MergeEnv(concat, ignore, env, vars...) return env.ToSlice(), nil }
// setArmEnv sets the environment variables used for arm cross-compilation. func setArmEnv(ctx *tool.Context, env *envvar.Vars, root string) error { // Set Go specific environment variables. env.Set("GOARCH", "arm") env.Set("GOARM", "6") env.Set("GOOS", "linux") // Add the paths to arm cross-compilation tools to the PATH. path := env.GetTokens("PATH", ":") path = append([]string{ filepath.Join(root, "third_party", "cout", "xgcc", "cross_arm"), filepath.Join(root, "third_party", "repos", "go_arm", "bin"), }, path...) env.SetTokens("PATH", path, ":") return nil }
// setNaclEnv sets the environment variables used for nacl // cross-compilation. func setNaclEnv(ctx *tool.Context, env *envvar.Vars, root string) error { env.Set("GOARCH", "amd64p32") env.Set("GOOS", "nacl") // Add the path to nacl cross-compiler to the PATH. path := env.GetTokens("PATH", ":") path = append([]string{ filepath.Join(root, "third_party", "repos", "go_ppapi", "bin"), }, path...) env.SetTokens("PATH", path, ":") return nil }
// MergeEnv merges vars with the variables in env taking care to concatenate // values as per the concat and ignore parameters similarly to SetEnvFromProfiles. func MergeEnv(concat map[string]string, ignore map[string]bool, env *envvar.Vars, vars ...[]string) { for _, ev := range vars { for _, tmp := range ev { k, v := envvar.SplitKeyValue(tmp) if ignore[k] { continue } if sep := concat[k]; len(sep) > 0 { ov := env.GetTokens(k, sep) nv := envvar.SplitTokens(v, sep) env.SetTokens(k, append(ov, nv...), " ") continue } env.Set(k, v) } } }
// setSyncbaseEnv adds the LevelDB third-party C++ libraries Vanadium // Go code depends on to the CGO_CFLAGS and CGO_LDFLAGS variables. func setSyncbaseEnv(ctx *tool.Context, env *envvar.Vars, root string) error { libs := []string{ "leveldb", "snappy", } // TODO(rogulenko): get these vars from a config file. goos, goarch := env.Get("GOOS"), env.Get("GOARCH") if goos == "" { goos = runtime.GOOS } if goarch == "" { goarch = runtime.GOARCH } for _, lib := range libs { cflags := env.GetTokens("CGO_CFLAGS", " ") cxxflags := env.GetTokens("CGO_CXXFLAGS", " ") ldflags := env.GetTokens("CGO_LDFLAGS", " ") dir, err := ThirdPartyCCodePath(goos, goarch) if err != nil { return err } dir = filepath.Join(dir, lib) if _, err := ctx.Run().Stat(dir); err != nil { if !os.IsNotExist(err) { return err } continue } cflags = append(cflags, filepath.Join("-I"+dir, "include")) cxxflags = append(cxxflags, filepath.Join("-I"+dir, "include")) ldflags = append(ldflags, filepath.Join("-L"+dir, "lib")) if runtime.GOARCH == "linux" { ldflags = append(ldflags, "-Wl,-rpath", filepath.Join(dir, "lib")) } env.SetTokens("CGO_CFLAGS", cflags, " ") env.SetTokens("CGO_CXXFLAGS", cxxflags, " ") env.SetTokens("CGO_LDFLAGS", ldflags, " ") } return nil }
// setAndroidEnv sets the environment variables used for android // cross-compilation. func setAndroidEnv(ctx *tool.Context, env *envvar.Vars, root string) error { // Compile using Android Go 1.5 (installed via // 'jiri profile install android'). androidGoDir := filepath.Join(root, "third_party", "android", "go") // Set Go-specific environment variables. env.Set("GOARCH", "arm") env.Set("GOARM", "7") env.Set("GOOS", "android") env.Set("GOROOT", androidGoDir) // Update PATH. if _, err := ctx.Run().Stat(androidGoDir); err != nil { return fmt.Errorf("Couldn't find android Go installation directory %s: did you run \"jiri profile install android\"?", androidGoDir) } path := env.GetTokens("PATH", ":") path = append([]string{filepath.Join(androidGoDir, "bin")}, path...) env.SetTokens("PATH", path, ":") return nil }
// UnsetGoEnvVars unsets Go environment variables in the given environment. func UnsetGoEnvVars(env *envvar.Vars) { for _, k := range GoFlags { env.Delete(k) } }
// MergeEnv merges environment variables in base with those // in vars according to the suppled policies. func MergeEnv(policies map[string]MergePolicy, base *envvar.Vars, vars ...[]string) { // Remove any variables that have the IgnoreBase policy. for k, _ := range base.ToMap() { switch policies[k].Action { case Ignore, IgnoreBaseAndAppend, IgnoreBaseAndPrepend, IgnoreBaseAndUseFirst, IgnoreBaseAndUseLast: base.Delete(k) } } for _, ev := range vars { for _, tmp := range ev { k, v := envvar.SplitKeyValue(tmp) policy := policies[k] action := policy.Action switch policy.Action { case IgnoreBaseAndAppend: action = Append case IgnoreBaseAndPrepend: action = Prepend case IgnoreBaseAndUseLast: action = Last case IgnoreBaseAndUseFirst: action = First } switch action { case Ignore, IgnoreProfiles: continue case Append, Prepend: sep := policy.Separator ov := base.GetTokens(k, sep) nv := envvar.SplitTokens(v, sep) if action == Append { base.SetTokens(k, append(ov, nv...), sep) } else { base.SetTokens(k, append(nv, ov...), sep) } case First: if !base.Contains(k) { base.Set(k, v) } case Last: base.Set(k, v) } } } }