v.io/jiri: refactor to move DataDir out of jiri, part 1.

jiri project poll is moved into jiri-test poll
jiri contributors is moved into an external command jiri-contributors

Change-Id: I9a63717cb6cc41b70cf8af3eeae95aecd363fefc
diff --git a/jiri-contributors/contrib.go b/jiri-contributors/contrib.go
new file mode 100644
index 0000000..9ac4331
--- /dev/null
+++ b/jiri-contributors/contrib.go
@@ -0,0 +1,239 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The following enables go generate to generate the doc.go file.
+//go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go -env=CMDLINE_PREFIX=jiri .
+
+package main
+
+import (
+	"encoding/xml"
+	"fmt"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+
+	"v.io/jiri"
+	"v.io/jiri/collect"
+	"v.io/jiri/gitutil"
+	"v.io/jiri/project"
+	"v.io/jiri/tool"
+	"v.io/x/devtools/tooldata"
+	"v.io/x/lib/cmdline"
+	"v.io/x/lib/set"
+)
+
+const (
+	aliasesFileName = "aliases.v1.xml"
+)
+
+var (
+	countFlag   bool
+	aliasesFlag string
+)
+
+func init() {
+	cmdContributorsList.Flags.BoolVar(&countFlag, "n", false, "Show number of contributions.")
+	cmdContributorsList.Flags.StringVar(&aliasesFlag, "aliases", "", "Path to the aliases file.")
+}
+
+// cmdContributors represents the "jiri contributors" command.
+var cmdContributors = &cmdline.Command{
+	Name:     "contributors",
+	Short:    "List project contributors",
+	Long:     "List project contributors.",
+	Children: []*cmdline.Command{cmdContributorsList},
+}
+
+// cmdContributorsList represents the "jiri contributors list" command.
+var cmdContributorsList = &cmdline.Command{
+	Runner: jiri.RunnerFunc(runContributorsList),
+	Name:   "contributors",
+	Short:  "List project contributors",
+	Long: `
+Lists project contributors. Projects to consider can be specified as
+an argument. If no projects are specified, all projects in the current
+manifest are considered by default.
+`,
+	ArgsName: "<projects>",
+	ArgsLong: "<projects> is a list of projects to consider.",
+}
+
+type contributor struct {
+	count int
+	email string
+	name  string
+}
+
+var (
+	contributorRE = regexp.MustCompile("^(.*)\t(.*) <(.*)>$")
+)
+
+type aliasesSchema struct {
+	XMLName xml.Name      `xml:"aliases"`
+	Names   []nameSchema  `xml:"name"`
+	Emails  []emailSchema `xml:"email"`
+}
+
+type nameSchema struct {
+	Canonical string   `xml:"canonical"`
+	Aliases   []string `xml:"alias"`
+}
+
+type emailSchema struct {
+	Canonical string   `xml:"canonical"`
+	Aliases   []string `xml:"alias"`
+}
+
+type aliasMaps struct {
+	emails map[string]string
+	names  map[string]string
+}
+
+func canonicalize(aliases *aliasMaps, email, name string) (string, string) {
+	canonicalEmail, canonicalName := email, name
+	if email, ok := aliases.emails[email]; ok {
+		canonicalEmail = email
+	}
+	if name, ok := aliases.names[name]; ok {
+		canonicalName = name
+	}
+	return canonicalEmail, canonicalName
+}
+
+func loadAliases(jirix *jiri.X) (*aliasMaps, error) {
+	aliasesFile := aliasesFlag
+	if aliasesFile == "" {
+		dataDir, err := tooldata.DataDirPath(jirix, tool.Name)
+		if err != nil {
+			return nil, err
+		}
+		aliasesFile = filepath.Join(dataDir, aliasesFileName)
+	}
+	bytes, err := jirix.NewSeq().ReadFile(aliasesFile)
+	if err != nil {
+		return nil, err
+	}
+	var data aliasesSchema
+	if err := xml.Unmarshal(bytes, &data); err != nil {
+		return nil, fmt.Errorf("Unmarshal(%v) failed: %v", string(bytes), err)
+	}
+	aliases := &aliasMaps{
+		emails: map[string]string{},
+		names:  map[string]string{},
+	}
+	for _, email := range data.Emails {
+		for _, alias := range email.Aliases {
+			aliases.emails[alias] = email.Canonical
+		}
+	}
+	for _, name := range data.Names {
+		for _, alias := range name.Aliases {
+			aliases.names[alias] = name.Canonical
+		}
+	}
+	return aliases, nil
+}
+
+func runContributorsList(jirix *jiri.X, args []string) error {
+	localProjects, err := project.LocalProjects(jirix, project.FastScan)
+	if err != nil {
+		return err
+	}
+	projectNames := map[string]struct{}{}
+	if len(args) != 0 {
+		projectNames = set.String.FromSlice(args)
+	} else {
+		for _, p := range localProjects {
+			projectNames[p.Name] = struct{}{}
+		}
+	}
+
+	aliases, err := loadAliases(jirix)
+	if err != nil {
+		return err
+	}
+	contributors := map[string]*contributor{}
+	for name, _ := range projectNames {
+		projects := localProjects.Find(name)
+		if len(projects) == 0 {
+			continue
+		}
+
+		for _, project := range projects {
+			if err := jirix.NewSeq().Chdir(project.Path).Done(); err != nil {
+				return err
+			}
+			switch project.Protocol {
+			case "git":
+				lines, err := listCommitters(jirix)
+				if err != nil {
+					return err
+				}
+				for _, line := range lines {
+					matches := contributorRE.FindStringSubmatch(line)
+					if got, want := len(matches), 4; got != want {
+						return fmt.Errorf("unexpected length of %v: got %v, want %v", matches, got, want)
+					}
+					count, err := strconv.Atoi(strings.TrimSpace(matches[1]))
+					if err != nil {
+						return fmt.Errorf("Atoi(%v) failed: %v", strings.TrimSpace(matches[1]), err)
+					}
+					c := &contributor{
+						count: count,
+						email: strings.TrimSpace(matches[3]),
+						name:  strings.TrimSpace(matches[2]),
+					}
+					if c.email == "jenkins.veyron@gmail.com" || c.email == "jenkins.veyron.rw@gmail.com" {
+						continue
+					}
+					c.email, c.name = canonicalize(aliases, c.email, c.name)
+					if existing, ok := contributors[c.name]; ok {
+						existing.count += c.count
+					} else {
+						contributors[c.name] = c
+					}
+				}
+			}
+		}
+	}
+	names := []string{}
+	for name, _ := range contributors {
+		names = append(names, name)
+	}
+	sort.Strings(names)
+	for _, name := range names {
+		c := contributors[name]
+		if countFlag {
+			fmt.Fprintf(jirix.Stdout(), "%4d ", c.count)
+		}
+		fmt.Fprintf(jirix.Stdout(), "%v <%v>\n", c.name, c.email)
+	}
+	return nil
+}
+
+func listCommitters(jirix *jiri.X) (_ []string, e error) {
+	branch, err := gitutil.New(jirix.NewSeq()).CurrentBranchName()
+	if err != nil {
+		return nil, err
+	}
+	stashed, err := gitutil.New(jirix.NewSeq()).Stash()
+	if err != nil {
+		return nil, err
+	}
+	if stashed {
+		defer collect.Error(func() error { return gitutil.New(jirix.NewSeq()).StashPop() }, &e)
+	}
+	if err := gitutil.New(jirix.NewSeq()).CheckoutBranch("master"); err != nil {
+		return nil, err
+	}
+	defer collect.Error(func() error { return gitutil.New(jirix.NewSeq()).CheckoutBranch(branch) }, &e)
+	return gitutil.New(jirix.NewSeq()).Committers()
+}
+
+func main() {
+	cmdline.Main(cmdContributors)
+}
diff --git a/jiri-contributors/doc.go b/jiri-contributors/doc.go
new file mode 100644
index 0000000..5bf5512
--- /dev/null
+++ b/jiri-contributors/doc.go
@@ -0,0 +1,67 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+
+/*
+List project contributors.
+
+Usage:
+   jiri contributors [flags] <command>
+
+The jiri contributors commands are:
+   contributors List project contributors
+   help         Display help for commands or topics
+
+The global flags are:
+ -metadata=<just specify -metadata to activate>
+   Displays metadata for the program and exits.
+ -time=false
+   Dump timing information to stderr before exiting the program.
+
+Jiri contributors contributors - List project contributors
+
+Lists project contributors. Projects to consider can be specified as an
+argument. If no projects are specified, all projects in the current manifest are
+considered by default.
+
+Usage:
+   jiri contributors contributors [flags] <projects>
+
+<projects> is a list of projects to consider.
+
+The jiri contributors contributors flags are:
+ -aliases=
+   Path to the aliases file.
+ -n=false
+   Show number of contributions.
+
+Jiri contributors help - Display help for commands or topics
+
+Help with no args displays the usage of the parent command.
+
+Help with args displays the usage of the specified sub-command or help topic.
+
+"help ..." recursively displays help for all commands and topics.
+
+Usage:
+   jiri contributors help [flags] [command/topic ...]
+
+[command/topic ...] optionally identifies a specific sub-command or help topic.
+
+The jiri contributors help flags are:
+ -style=compact
+   The formatting style for help output:
+      compact   - Good for compact cmdline output.
+      full      - Good for cmdline output, shows all global flags.
+      godoc     - Good for godoc processing.
+      shortonly - Only output short description.
+   Override the default by setting the CMDLINE_STYLE environment variable.
+ -width=<terminal width>
+   Format output to this target width in runes, or unlimited if width < 0.
+   Defaults to the terminal width if available.  Override the default by setting
+   the CMDLINE_WIDTH environment variable.
+*/
+package main
diff --git a/jiri-profile-v23/doc.go b/jiri-profile-v23/doc.go
new file mode 100644
index 0000000..500261e
--- /dev/null
+++ b/jiri-profile-v23/doc.go
@@ -0,0 +1,251 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+
+/*
+Profiles are used to manage external sofware dependencies and offer a balance
+between providing no support at all and a full blown package manager. Profiles
+can be built natively as well as being cross compiled. A profile is a named
+collection of software required for a given system component or application.
+Current example profiles include 'syncbase' which consists of the leveldb and
+snappy libraries or 'android' which consists of all of the android components
+and downloads needed to build android applications. Profiles are built for
+specific targets.
+
+Targets
+
+Profiles generally refer to uncompiled source code that needs to be compiled for
+a specific "target". Targets hence represent compiled code and consist of:
+
+1. An 'architecture' that refers to the CPU to be generate code for
+
+2. An 'operating system' that refers to the operating system to generate code
+for
+
+3. A lexicographically orderd set of supported versions, one of which is
+designated as the default.
+
+4. An 'environment' which is a set of environment variables to use when
+compiling the profile
+
+Targets thus provide the basic support needed for cross compilation.
+
+Targets are versioned and multiple versions may be installed and used
+simultaneously. Versions are ordered lexicographically and each target specifies
+a 'default' version to be used when a specific version is not explicitly
+requested. A request to 'upgrade' the profile will result in the installation of
+the default version of the targets currently installed if that default version
+is not already installed.
+
+The Supported Commands
+
+Profiles, or more correctly, targets for specific profiles may be installed or
+removed. When doing so, the name of the profile is required, but the other
+components of the target are optional and will default to the values of the
+system that the commands are run on (so-called native builds) and the default
+version for that target. Once a profile is installed it may be referred to by
+its tag for subsequent removals.
+
+The are also update and cleanup commands. Update installs the default version of
+the requested profile or for all profiles for the already installed targets.
+Cleanup will uninstall targets whose version is older than the default.
+
+Finally, there are commands to list the available and installed profiles and to
+access the environment variables specified and stored in each profile
+installation and a command (recreate) to generate a list of commands that can be
+run to recreate the currently installed profiles.
+
+The Profiles Database
+
+The profiles packages manages a database that tracks the installed profiles and
+their configurations. Other command line tools and packages are expected to read
+information about the currently installed profiles from this database via the
+profiles package. The profile command line tools support displaying the database
+(via the list command) or for specifying an alternate version of the file (via
+the -profiles-db flag) which is generally useful for debugging.
+
+Adding Profiles
+
+Profiles are intended to be provided as go packages that register themselves
+with the profile command line tools via the *v.io/jiri/profiles* package. They
+must implement the interfaces defined by that package and be imported (e.g.
+import _ "myprofile") by the command line tools that are to use them.
+
+Usage:
+   jiri profile-v23 [flags] <command>
+
+The jiri profile-v23 commands are:
+   install     Install the given profiles
+   uninstall   Uninstall the given profiles
+   update      Install the latest default version of the given profiles
+   cleanup     Cleanup the locally installed profiles
+   available   List the available profiles
+   help        Display help for commands or topics
+
+The jiri profile-v23 flags are:
+ -color=true
+   Use color to format output.
+ -v=false
+   Print verbose output.
+
+The global flags are:
+ -metadata=<just specify -metadata to activate>
+   Displays metadata for the program and exits.
+ -time=false
+   Dump timing information to stderr before exiting the program.
+
+Jiri profile-v23 install - Install the given profiles
+
+Install the given profiles.
+
+Usage:
+   jiri profile-v23 install [flags] <profiles>
+
+<profiles> is a list of profiles to install.
+
+The jiri profile-v23 install flags are:
+ -env=
+   specify an environment variable in the form: <var>=[<val>],...
+ -force=false
+   force install the profile even if it is already installed
+ -go.sysroot-image=
+   sysroot image for cross compiling to the currently specified target
+ -go.sysroot-image-dirs-to-use=/lib:/usr/lib:/usr/include
+   a colon separated list of directories to use from the sysroot image
+ -mojodev.dir=
+   Path of mojo repo checkout.
+ -profiles-db=$JIRI_ROOT/.jiri_root/profile_db
+   the path, relative to JIRI_ROOT, that contains the profiles database.
+ -profiles-dir=.jiri_root/profiles
+   the directory, relative to JIRI_ROOT, that profiles are installed in
+ -target=<runtime.GOARCH>-<runtime.GOOS>
+   specifies a profile target in the following form: <arch>-<os>[@<version>]
+
+ -color=true
+   Use color to format output.
+ -v=false
+   Print verbose output.
+
+Jiri profile-v23 uninstall - Uninstall the given profiles
+
+Uninstall the given profiles.
+
+Usage:
+   jiri profile-v23 uninstall [flags] <profiles>
+
+<profiles> is a list of profiles to uninstall.
+
+The jiri profile-v23 uninstall flags are:
+ -all-targets=false
+   apply to all targets for the specified profile(s)
+ -go.sysroot-image=
+   sysroot image for cross compiling to the currently specified target
+ -go.sysroot-image-dirs-to-use=/lib:/usr/lib:/usr/include
+   a colon separated list of directories to use from the sysroot image
+ -profiles-db=$JIRI_ROOT/.jiri_root/profile_db
+   the path, relative to JIRI_ROOT, that contains the profiles database.
+ -profiles-dir=.jiri_root/profiles
+   the directory, relative to JIRI_ROOT, that profiles are installed in
+ -target=<runtime.GOARCH>-<runtime.GOOS>
+   specifies a profile target in the following form: <arch>-<os>[@<version>]
+ -v=false
+   print more detailed information
+
+ -color=true
+   Use color to format output.
+
+Jiri profile-v23 update - Install the latest default version of the given profiles
+
+Install the latest default version of the given profiles.
+
+Usage:
+   jiri profile-v23 update [flags] <profiles>
+
+<profiles> is a list of profiles to update, if omitted all profiles are updated.
+
+The jiri profile-v23 update flags are:
+ -profiles-db=$JIRI_ROOT/.jiri_root/profile_db
+   the path, relative to JIRI_ROOT, that contains the profiles database.
+ -profiles-dir=.jiri_root/profiles
+   the directory, relative to JIRI_ROOT, that profiles are installed in
+ -v=false
+   print more detailed information
+
+ -color=true
+   Use color to format output.
+
+Jiri profile-v23 cleanup - Cleanup the locally installed profiles
+
+Cleanup the locally installed profiles. This is generally required when
+recovering from earlier bugs or when preparing for a subsequent change to the
+profiles implementation.
+
+Usage:
+   jiri profile-v23 cleanup [flags] <profiles>
+
+<profiles> is a list of profiles to cleanup, if omitted all profiles are
+cleaned.
+
+The jiri profile-v23 cleanup flags are:
+ -gc=false
+   uninstall profile targets that are older than the current default
+ -profiles-db=$JIRI_ROOT/.jiri_root/profile_db
+   the path, relative to JIRI_ROOT, that contains the profiles database.
+ -profiles-dir=.jiri_root/profiles
+   the directory, relative to JIRI_ROOT, that profiles are installed in
+ -rewrite-profiles-db=false
+   rewrite the profiles database to use the latest schema version
+ -rm-all=false
+   remove profiles database and all profile generated output files.
+ -v=false
+   print more detailed information
+
+ -color=true
+   Use color to format output.
+
+Jiri profile-v23 available - List the available profiles
+
+List the available profiles.
+
+Usage:
+   jiri profile-v23 available [flags]
+
+The jiri profile-v23 available flags are:
+ -describe=false
+   print the profile description
+ -v=false
+   print more detailed information
+
+ -color=true
+   Use color to format output.
+
+Jiri profile-v23 help - Display help for commands or topics
+
+Help with no args displays the usage of the parent command.
+
+Help with args displays the usage of the specified sub-command or help topic.
+
+"help ..." recursively displays help for all commands and topics.
+
+Usage:
+   jiri profile-v23 help [flags] [command/topic ...]
+
+[command/topic ...] optionally identifies a specific sub-command or help topic.
+
+The jiri profile-v23 help flags are:
+ -style=compact
+   The formatting style for help output:
+      compact   - Good for compact cmdline output.
+      full      - Good for cmdline output, shows all global flags.
+      godoc     - Good for godoc processing.
+      shortonly - Only output short description.
+   Override the default by setting the CMDLINE_STYLE environment variable.
+ -width=<terminal width>
+   Format output to this target width in runes, or unlimited if width < 0.
+   Defaults to the terminal width if available.  Override the default by setting
+   the CMDLINE_WIDTH environment variable.
+*/
+package main
diff --git a/jiri-test/doc.go b/jiri-test/doc.go
index 129c9ed..d83368b 100644
--- a/jiri-test/doc.go
+++ b/jiri-test/doc.go
@@ -12,6 +12,7 @@
    jiri test [flags] <command>
 
 The jiri test commands are:
+   poll        Poll existing jiri projects
    project     Run tests for a vanadium project
    run         Run vanadium tests
    list        List vanadium tests
@@ -41,6 +42,38 @@
  -time=false
    Dump timing information to stderr before exiting the program.
 
+Jiri test poll - Poll existing jiri projects
+
+Poll jiri projects that can affect the outcome of the given tests and report
+whether any new changes in these projects exist. If no tests are specified, all
+projects are polled by default.
+
+Usage:
+   jiri test poll [flags] <test ...>
+
+<test ...> is a list of tests that determine what projects to poll.
+
+The jiri test poll flags are:
+ -manifest=
+   Name of the project manifest.
+
+ -color=true
+   Use color to format output.
+ -env=
+   specify an environment variable in the form: <var>=[<val>],...
+ -merge-policies=+CCFLAGS,+CGO_CFLAGS,+CGO_CXXFLAGS,+CGO_LDFLAGS,+CXXFLAGS,GOARCH,GOOS,GOPATH:,^GOROOT*,+LDFLAGS,:PATH,VDLPATH:
+   specify policies for merging environment variables
+ -profiles=v23:base,jiri
+   a comma separated list of profiles to use
+ -profiles-db=$JIRI_ROOT/.jiri_root/profile_db
+   the path, relative to JIRI_ROOT, that contains the profiles database.
+ -skip-profiles=false
+   if set, no profiles will be used
+ -target=<runtime.GOARCH>-<runtime.GOOS>
+   specifies a profile target in the following form: <arch>-<os>[@<version>]
+ -v=false
+   Print verbose output.
+
 Jiri test project - Run tests for a vanadium project
 
 Runs tests for a vanadium project that is by the remote URL specified as the
diff --git a/jiri-test/test.go b/jiri-test/test.go
index 8ab0bb1..a844362 100644
--- a/jiri-test/test.go
+++ b/jiri-test/test.go
@@ -8,16 +8,20 @@
 package main
 
 import (
+	"encoding/json"
 	"fmt"
 	"runtime"
 	"strings"
 
 	"v.io/jiri"
 	"v.io/jiri/profiles/profilescmdline"
+	"v.io/jiri/project"
 	"v.io/jiri/tool"
 	"v.io/x/devtools/internal/test"
 	jiriTest "v.io/x/devtools/jiri-test/internal/test"
+	"v.io/x/devtools/tooldata"
 	"v.io/x/lib/cmdline"
+	"v.io/x/lib/set"
 )
 
 var (
@@ -48,6 +52,7 @@
 	cmdTestRun.Flags.StringVar(&mockTestFilePaths, "mock-file-paths", "", "Colon-separated file paths to read when testing presubmit test. This flag is only used when running presubmit end-to-end test.")
 	cmdTestRun.Flags.StringVar(&mockTestFileContents, "mock-file-contents", "", "Colon-separated file contents to check when testing presubmit test. This flag is only used when running presubmit end-to-end test.")
 	tool.InitializeRunFlags(&cmdTest.Flags)
+	tool.InitializeProjectFlags(&cmdProjectPoll.Flags)
 	profilescmdline.RegisterReaderFlags(&cmdTest.Flags, &readerFlags, jiri.ProfilesDBDir)
 }
 
@@ -56,7 +61,7 @@
 	Name:     "test",
 	Short:    "Manage vanadium tests",
 	Long:     "Manage vanadium tests.",
-	Children: []*cmdline.Command{cmdTestProject, cmdTestRun, cmdTestList},
+	Children: []*cmdline.Command{cmdProjectPoll, cmdTestProject, cmdTestRun, cmdTestList},
 }
 
 // cmdTestProject represents the "jiri test project" command.
@@ -121,6 +126,68 @@
 	return nil
 }
 
+// cmdProjectPoll represents the "jiri project poll" command.
+var cmdProjectPoll = &cmdline.Command{
+	Runner: jiri.RunnerFunc(runProjectPoll),
+	Name:   "poll",
+	Short:  "Poll existing jiri projects",
+	Long: `
+Poll jiri projects that can affect the outcome of the given tests
+and report whether any new changes in these projects exist. If no
+tests are specified, all projects are polled by default.
+`,
+	ArgsName: "<test ...>",
+	ArgsLong: "<test ...> is a list of tests that determine what projects to poll.",
+}
+
+// runProjectPoll generates a description of changes that exist
+// remotely but do not exist locally.
+func runProjectPoll(jirix *jiri.X, args []string) error {
+	projectSet := map[string]struct{}{}
+	if len(args) > 0 {
+		config, err := tooldata.LoadConfig(jirix)
+		if err != nil {
+			return err
+		}
+		// Compute a map from tests to projects that can change the
+		// outcome of the test.
+		testProjects := map[string][]string{}
+		for _, project := range config.Projects() {
+			for _, test := range config.ProjectTests([]string{project}) {
+				testProjects[test] = append(testProjects[test], project)
+			}
+		}
+		for _, arg := range args {
+			projects, ok := testProjects[arg]
+			if !ok {
+				return fmt.Errorf("failed to find any projects for test %q", arg)
+			}
+			set.String.Union(projectSet, set.String.FromSlice(projects))
+		}
+	}
+	update, err := project.PollProjects(jirix, projectSet)
+	if err != nil {
+		return err
+	}
+
+	// Remove projects with empty changes.
+	for project := range update {
+		if changes := update[project]; len(changes) == 0 {
+			delete(update, project)
+		}
+	}
+
+	// Print update if it is not empty.
+	if len(update) > 0 {
+		bytes, err := json.MarshalIndent(update, "", "  ")
+		if err != nil {
+			return fmt.Errorf("MarshalIndent() failed: %v", err)
+		}
+		fmt.Fprintf(jirix.Stdout(), "%s\n", bytes)
+	}
+	return nil
+}
+
 func optsFromFlags() (opts []jiriTest.Opt) {
 	if partFlag >= 0 {
 		opt := jiriTest.PartOpt(partFlag)
diff --git a/jiridoc/doc.go b/jiridoc/doc.go
index 4a41e53..3766690 100644
--- a/jiridoc/doc.go
+++ b/jiridoc/doc.go
@@ -1480,6 +1480,7 @@
    jiri test [flags] <command>
 
 The jiri test commands are:
+   poll        Poll existing jiri projects
    project     Run tests for a vanadium project
    run         Run vanadium tests
    list        List vanadium tests
@@ -1502,6 +1503,38 @@
  -v=false
    Print verbose output.
 
+Jiri test poll - Poll existing jiri projects
+
+Poll jiri projects that can affect the outcome of the given tests and report
+whether any new changes in these projects exist. If no tests are specified, all
+projects are polled by default.
+
+Usage:
+   jiri test poll [flags] <test ...>
+
+<test ...> is a list of tests that determine what projects to poll.
+
+The jiri test poll flags are:
+ -manifest=
+   Name of the project manifest.
+
+ -color=true
+   Use color to format output.
+ -env=
+   specify an environment variable in the form: <var>=[<val>],...
+ -merge-policies=+CCFLAGS,+CGO_CFLAGS,+CGO_CXXFLAGS,+CGO_LDFLAGS,+CXXFLAGS,GOARCH,GOOS,GOPATH:,^GOROOT*,+LDFLAGS,:PATH,VDLPATH:
+   specify policies for merging environment variables
+ -profiles=v23:base,jiri
+   a comma separated list of profiles to use
+ -profiles-db=$JIRI_ROOT/.jiri_root/profile_db
+   the path, relative to JIRI_ROOT, that contains the profiles database.
+ -skip-profiles=false
+   if set, no profiles will be used
+ -target=<runtime.GOARCH>-<runtime.GOOS>
+   specifies a profile target in the following form: <arch>-<os>[@<version>]
+ -v=false
+   Print verbose output.
+
 Jiri test project - Run tests for a vanadium project
 
 Runs tests for a vanadium project that is by the remote URL specified as the
diff --git a/tooldata/.api b/tooldata/.api
new file mode 100644
index 0000000..56f4e19
--- /dev/null
+++ b/tooldata/.api
@@ -0,0 +1,45 @@
+pkg tooldata, func ConfigFilePath(*jiri.X) (string, error)
+pkg tooldata, func DataDirPath(*jiri.X, string) (string, error)
+pkg tooldata, func LoadConfig(*jiri.X) (*Config, error)
+pkg tooldata, func LoadOncallRotation(*jiri.X) (*OncallRotation, error)
+pkg tooldata, func NewConfig(...ConfigOpt) *Config
+pkg tooldata, func Oncall(*jiri.X, time.Time) (*OncallShift, error)
+pkg tooldata, func OncallRotationPath(*jiri.X) (string, error)
+pkg tooldata, func SaveConfig(*jiri.X, *Config) error
+pkg tooldata, func ThirdPartyBinPath(*jiri.X, string) (string, error)
+pkg tooldata, method (Config) APICheckProjects() map[string]struct{}
+pkg tooldata, method (Config) CopyrightCheckProjects() map[string]struct{}
+pkg tooldata, method (Config) GoPath(*jiri.X) string
+pkg tooldata, method (Config) GoWorkspaces() []string
+pkg tooldata, method (Config) GroupTests([]string) []string
+pkg tooldata, method (Config) JenkinsMatrixJobs() map[string]JenkinsMatrixJobInfo
+pkg tooldata, method (Config) ProjectTests([]string) []string
+pkg tooldata, method (Config) Projects() []string
+pkg tooldata, method (Config) TestDependencies(string) []string
+pkg tooldata, method (Config) TestParts(string) []string
+pkg tooldata, method (Config) VDLPath(*jiri.X) string
+pkg tooldata, method (Config) VDLWorkspaces() []string
+pkg tooldata, type APICheckProjectsOpt map[string]struct{}
+pkg tooldata, type Config struct
+pkg tooldata, type ConfigOpt interface, unexported methods
+pkg tooldata, type CopyrightCheckProjectsOpt map[string]struct{}
+pkg tooldata, type GoWorkspacesOpt []string
+pkg tooldata, type JenkinsMatrixJobInfo struct
+pkg tooldata, type JenkinsMatrixJobInfo struct, HasArch bool
+pkg tooldata, type JenkinsMatrixJobInfo struct, HasOS bool
+pkg tooldata, type JenkinsMatrixJobInfo struct, HasParts bool
+pkg tooldata, type JenkinsMatrixJobInfo struct, Name string
+pkg tooldata, type JenkinsMatrixJobInfo struct, ShowOS bool
+pkg tooldata, type JenkinsMatrixJobsOpt map[string]JenkinsMatrixJobInfo
+pkg tooldata, type OncallRotation struct
+pkg tooldata, type OncallRotation struct, Shifts []OncallShift
+pkg tooldata, type OncallRotation struct, XMLName xml.Name
+pkg tooldata, type OncallShift struct
+pkg tooldata, type OncallShift struct, Date string
+pkg tooldata, type OncallShift struct, Primary string
+pkg tooldata, type OncallShift struct, Secondary string
+pkg tooldata, type ProjectTestsOpt map[string][]string
+pkg tooldata, type TestDependenciesOpt map[string][]string
+pkg tooldata, type TestGroupsOpt map[string][]string
+pkg tooldata, type TestPartsOpt map[string][]string
+pkg tooldata, type VDLWorkspacesOpt []string
diff --git a/tooldata/config.go b/tooldata/config.go
new file mode 100644
index 0000000..25a5ee2
--- /dev/null
+++ b/tooldata/config.go
@@ -0,0 +1,458 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tooldata
+
+import (
+	"encoding/xml"
+	"fmt"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"v.io/jiri"
+	"v.io/jiri/project"
+	"v.io/x/lib/envvar"
+	"v.io/x/lib/set"
+)
+
+// Config holds configuration common to jiri tools.
+type Config struct {
+	// apiCheckProjects identifies the set of project names for which
+	// the API check is required.
+	apiCheckProjects map[string]struct{}
+	// copyrightCheckProjects identifies the set of project names for
+	// which the copyright check is required.
+	copyrightCheckProjects map[string]struct{}
+	// goWorkspaces identifies JIRI_ROOT subdirectories that contain a
+	// Go workspace.
+	goWorkspaces []string
+	// jenkinsMatrixJobs identifies the set of matrix (multi-configutation) jobs
+	// in Jenkins.
+	jenkinsMatrixJobs map[string]JenkinsMatrixJobInfo
+	// projectTests maps jiri projects to sets of tests that should be
+	// executed to test changes in the given project.
+	projectTests map[string][]string
+	// testDependencies maps tests to sets of tests that the given test
+	// depends on.
+	testDependencies map[string][]string
+	// testGroups maps test group labels to sets of tests that the label
+	// identifies.
+	testGroups map[string][]string
+	// testParts maps test names to lists of strings that identify
+	// different parts of a test. If a list L has n elements, then the
+	// corresponding test has n+1 parts: the first n parts are identified
+	// by L[0] to L[n-1]. The last part is whatever is left.
+	testParts map[string][]string
+	// vdlWorkspaces identifies JIRI_ROOT subdirectories that contain
+	// a VDL workspace.
+	vdlWorkspaces []string
+}
+
+// ConfigOpt is an interface for Config factory options.
+type ConfigOpt interface {
+	configOpt()
+}
+
+// APICheckProjectsOpt is the type that can be used to pass the Config
+// factory a API check projects option.
+type APICheckProjectsOpt map[string]struct{}
+
+func (APICheckProjectsOpt) configOpt() {}
+
+// CopyrightCheckProjectsOpt is the type that can be used to pass the
+// Config factory a copyright check projects option.
+type CopyrightCheckProjectsOpt map[string]struct{}
+
+func (CopyrightCheckProjectsOpt) configOpt() {}
+
+// GoWorkspacesOpt is the type that can be used to pass the Config
+// factory a Go workspace option.
+type GoWorkspacesOpt []string
+
+func (GoWorkspacesOpt) configOpt() {}
+
+// JenkinsMatrixJobsOpt is the type that can be used to pass the Config factory
+// a Jenkins matrix jobs option.
+type JenkinsMatrixJobsOpt map[string]JenkinsMatrixJobInfo
+
+func (JenkinsMatrixJobsOpt) configOpt() {}
+
+// ProjectTestsOpt is the type that can be used to pass the Config
+// factory a project tests option.
+type ProjectTestsOpt map[string][]string
+
+func (ProjectTestsOpt) configOpt() {}
+
+// TestDependenciesOpt is the type that can be used to pass the Config
+// factory a test dependencies option.
+type TestDependenciesOpt map[string][]string
+
+func (TestDependenciesOpt) configOpt() {}
+
+// TestGroupsOpt is the type that can be used to pass the Config
+// factory a test groups option.
+type TestGroupsOpt map[string][]string
+
+func (TestGroupsOpt) configOpt() {}
+
+// TestPartsOpt is the type that can be used to pass the Config
+// factory a test parts option.
+type TestPartsOpt map[string][]string
+
+func (TestPartsOpt) configOpt() {}
+
+// VDLWorkspacesOpt is the type that can be used to pass the Config
+// factory a VDL workspace option.
+type VDLWorkspacesOpt []string
+
+func (VDLWorkspacesOpt) configOpt() {}
+
+// NewConfig is the Config factory.
+func NewConfig(opts ...ConfigOpt) *Config {
+	var c Config
+	for _, opt := range opts {
+		switch typedOpt := opt.(type) {
+		case APICheckProjectsOpt:
+			c.apiCheckProjects = map[string]struct{}(typedOpt)
+		case CopyrightCheckProjectsOpt:
+			c.copyrightCheckProjects = map[string]struct{}(typedOpt)
+		case GoWorkspacesOpt:
+			c.goWorkspaces = []string(typedOpt)
+		case JenkinsMatrixJobsOpt:
+			c.jenkinsMatrixJobs = map[string]JenkinsMatrixJobInfo(typedOpt)
+		case ProjectTestsOpt:
+			c.projectTests = map[string][]string(typedOpt)
+		case TestDependenciesOpt:
+			c.testDependencies = map[string][]string(typedOpt)
+		case TestGroupsOpt:
+			c.testGroups = map[string][]string(typedOpt)
+		case TestPartsOpt:
+			c.testParts = map[string][]string(typedOpt)
+		case VDLWorkspacesOpt:
+			c.vdlWorkspaces = []string(typedOpt)
+		}
+	}
+	return &c
+}
+
+// APICheckProjects returns the set of project names for which the API
+// check is required.
+func (c Config) APICheckProjects() map[string]struct{} {
+	return c.apiCheckProjects
+}
+
+// CopyrightCheckProjects returns the set of project names for which
+// the copyright check is required.
+func (c Config) CopyrightCheckProjects() map[string]struct{} {
+	return c.copyrightCheckProjects
+}
+
+// GroupTests returns a list of Jenkins tests associated with the
+// given test groups.
+func (c Config) GroupTests(groups []string) []string {
+	testSet := map[string]struct{}{}
+	testGroups := c.testGroups
+	for _, group := range groups {
+		if testGroup, ok := testGroups[group]; ok {
+			set.String.Union(testSet, set.String.FromSlice(testGroup))
+		}
+	}
+	tests := set.String.ToSlice(testSet)
+	sort.Strings(tests)
+	return tests
+}
+
+// GoWorkspaces returns the Go workspaces included in the config.
+func (c Config) GoWorkspaces() []string {
+	return c.goWorkspaces
+}
+
+// JenkinsMatrixJobs returns the set of Jenkins matrix jobs.
+func (c Config) JenkinsMatrixJobs() map[string]JenkinsMatrixJobInfo {
+	return c.jenkinsMatrixJobs
+}
+
+// Projects returns a list of projects included in the config.
+func (c Config) Projects() []string {
+	var projects []string
+	for project, _ := range c.projectTests {
+		projects = append(projects, project)
+	}
+	sort.Strings(projects)
+	return projects
+}
+
+// ProjectTests returns a list of Jenkins tests associated with the
+// given projects by the config.
+func (c Config) ProjectTests(projects []string) []string {
+	testSet := map[string]struct{}{}
+	testGroups := c.testGroups
+	for _, project := range projects {
+		for _, test := range c.projectTests[project] {
+			if testGroup, ok := testGroups[test]; ok {
+				set.String.Union(testSet, set.String.FromSlice(testGroup))
+			} else {
+				testSet[test] = struct{}{}
+			}
+		}
+	}
+	tests := set.String.ToSlice(testSet)
+	sort.Strings(tests)
+	return tests
+}
+
+// TestDependencies returns a list of dependencies for the given test.
+func (c Config) TestDependencies(test string) []string {
+	return c.testDependencies[test]
+}
+
+// TestParts returns a list of strings that identify different test parts.
+func (c Config) TestParts(test string) []string {
+	return c.testParts[test]
+}
+
+// VDLWorkspaces returns the VDL workspaces included in the config.
+func (c Config) VDLWorkspaces() []string {
+	return c.vdlWorkspaces
+}
+
+// GoPath computes and returns the GOPATH environment variable based on the
+// current jiri configuration.
+func (c Config) GoPath(jirix *jiri.X) string {
+	projects, err := project.LocalProjects(jirix, project.FastScan)
+	if err != nil {
+		return ""
+	}
+	path := pathHelper(jirix, projects, c.goWorkspaces, "")
+	return "GOPATH=" + envvar.JoinTokens(path, ":")
+}
+
+// VDLPath computes and returns the VDLPATH environment variable based on the
+// current jiri configuration.
+func (c Config) VDLPath(jirix *jiri.X) string {
+	projects, err := project.LocalProjects(jirix, project.FastScan)
+	if err != nil {
+		return ""
+	}
+	path := pathHelper(jirix, projects, c.vdlWorkspaces, "src")
+	return "VDLPATH=" + envvar.JoinTokens(path, ":")
+}
+
+// pathHelper is a utility function for determining paths for project workspaces.
+func pathHelper(jirix *jiri.X, projects project.Projects, workspaces []string, suffix string) []string {
+	path := []string{}
+	for _, workspace := range workspaces {
+		absWorkspace := filepath.Join(jirix.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 := jirix.NewSeq().Stat(filepath.Join(absWorkspace)); err == nil {
+					path = append(path, absWorkspace)
+					break
+				}
+			}
+		}
+	}
+	return path
+}
+
+type configSchema struct {
+	APICheckProjects       []string                `xml:"apiCheckProjects>project"`
+	CopyrightCheckProjects []string                `xml:"copyrightCheckProjects>project"`
+	GoWorkspaces           []string                `xml:"goWorkspaces>workspace"`
+	JenkinsMatrixJobs      jenkinsMatrixJobsSchema `xml:"jenkinsMatrixJobs>job"`
+	ProjectTests           testGroupSchemas        `xml:"projectTests>project"`
+	TestDependencies       dependencyGroupSchemas  `xml:"testDependencies>test"`
+	TestGroups             testGroupSchemas        `xml:"testGroups>group"`
+	TestParts              partGroupSchemas        `xml:"testParts>test"`
+	VDLWorkspaces          []string                `xml:"vdlWorkspaces>workspace"`
+	XMLName                xml.Name                `xml:"config"`
+}
+
+type dependencyGroupSchema struct {
+	Name         string   `xml:"name,attr"`
+	Dependencies []string `xml:"dependency"`
+}
+
+type dependencyGroupSchemas []dependencyGroupSchema
+
+func (d dependencyGroupSchemas) Len() int           { return len(d) }
+func (d dependencyGroupSchemas) Swap(i, j int)      { d[i], d[j] = d[j], d[i] }
+func (d dependencyGroupSchemas) Less(i, j int) bool { return d[i].Name < d[j].Name }
+
+type JenkinsMatrixJobInfo struct {
+	HasArch  bool `xml:"arch,attr"`
+	HasOS    bool `xml:"OS,attr"`
+	HasParts bool `xml:"parts,attr"`
+	// ShowOS determines whether to show OS label in job summary.
+	// It is possible that a job (e.g. jiri-go-race) has an OS axis but
+	// the axis only has a single value in order to constrain where its
+	// sub-builds run. In such cases, we do not want to show the OS label.
+	ShowOS bool   `xml:"showOS,attr"`
+	Name   string `xml:",chardata"`
+}
+
+type jenkinsMatrixJobsSchema []JenkinsMatrixJobInfo
+
+func (jobs jenkinsMatrixJobsSchema) Len() int           { return len(jobs) }
+func (jobs jenkinsMatrixJobsSchema) Swap(i, j int)      { jobs[i], jobs[j] = jobs[j], jobs[i] }
+func (jobs jenkinsMatrixJobsSchema) Less(i, j int) bool { return jobs[i].Name < jobs[j].Name }
+
+type partGroupSchema struct {
+	Name  string   `xml:"name,attr"`
+	Parts []string `xml:"part"`
+}
+
+type partGroupSchemas []partGroupSchema
+
+func (p partGroupSchemas) Len() int           { return len(p) }
+func (p partGroupSchemas) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+func (p partGroupSchemas) Less(i, j int) bool { return p[i].Name < p[j].Name }
+
+type testGroupSchema struct {
+	Name  string   `xml:"name,attr"`
+	Tests []string `xml:"test"`
+}
+
+type testGroupSchemas []testGroupSchema
+
+func (p testGroupSchemas) Len() int           { return len(p) }
+func (p testGroupSchemas) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+func (p testGroupSchemas) Less(i, j int) bool { return p[i].Name < p[j].Name }
+
+// LoadConfig returns the configuration stored in the tools
+// configuration file.
+func LoadConfig(jirix *jiri.X) (*Config, error) {
+	configPath, err := ConfigFilePath(jirix)
+	if err != nil {
+		return nil, err
+	}
+	return loadConfig(jirix, configPath)
+}
+
+func loadConfig(jirix *jiri.X, path string) (*Config, error) {
+	configBytes, err := jirix.NewSeq().ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	var data configSchema
+	if err := xml.Unmarshal(configBytes, &data); err != nil {
+		return nil, fmt.Errorf("Unmarshal(%v) failed: %v", string(configBytes), err)
+	}
+	config := &Config{
+		apiCheckProjects:       map[string]struct{}{},
+		copyrightCheckProjects: map[string]struct{}{},
+		goWorkspaces:           []string{},
+		jenkinsMatrixJobs:      map[string]JenkinsMatrixJobInfo{},
+		projectTests:           map[string][]string{},
+		testDependencies:       map[string][]string{},
+		testGroups:             map[string][]string{},
+		testParts:              map[string][]string{},
+		vdlWorkspaces:          []string{},
+	}
+	config.apiCheckProjects = set.String.FromSlice(data.APICheckProjects)
+	config.copyrightCheckProjects = set.String.FromSlice(data.CopyrightCheckProjects)
+	for _, workspace := range data.GoWorkspaces {
+		config.goWorkspaces = append(config.goWorkspaces, workspace)
+	}
+	sort.Strings(config.goWorkspaces)
+	for _, job := range data.JenkinsMatrixJobs {
+		config.jenkinsMatrixJobs[job.Name] = job
+	}
+	for _, project := range data.ProjectTests {
+		config.projectTests[project.Name] = project.Tests
+	}
+	for _, test := range data.TestDependencies {
+		config.testDependencies[test.Name] = test.Dependencies
+	}
+	for _, group := range data.TestGroups {
+		config.testGroups[group.Name] = group.Tests
+	}
+	for _, test := range data.TestParts {
+		config.testParts[test.Name] = test.Parts
+	}
+	for _, workspace := range data.VDLWorkspaces {
+		config.vdlWorkspaces = append(config.vdlWorkspaces, workspace)
+	}
+	sort.Strings(config.vdlWorkspaces)
+	return config, nil
+}
+
+// SaveConfig writes the given configuration to the tools
+// configuration file.
+func SaveConfig(jirix *jiri.X, config *Config) error {
+	configPath, err := ConfigFilePath(jirix)
+	if err != nil {
+		return err
+	}
+	return saveConfig(jirix, config, configPath)
+}
+
+func saveConfig(jirix *jiri.X, config *Config, path string) error {
+	var data configSchema
+	data.APICheckProjects = set.String.ToSlice(config.apiCheckProjects)
+	sort.Strings(data.APICheckProjects)
+	data.CopyrightCheckProjects = set.String.ToSlice(config.copyrightCheckProjects)
+	sort.Strings(data.CopyrightCheckProjects)
+	for _, workspace := range config.goWorkspaces {
+		data.GoWorkspaces = append(data.GoWorkspaces, workspace)
+	}
+	sort.Strings(data.GoWorkspaces)
+	for _, job := range config.jenkinsMatrixJobs {
+		data.JenkinsMatrixJobs = append(data.JenkinsMatrixJobs, job)
+	}
+	sort.Sort(data.JenkinsMatrixJobs)
+	for name, tests := range config.projectTests {
+		data.ProjectTests = append(data.ProjectTests, testGroupSchema{
+			Name:  name,
+			Tests: tests,
+		})
+	}
+	sort.Sort(data.ProjectTests)
+	for name, dependencies := range config.testDependencies {
+		data.TestDependencies = append(data.TestDependencies, dependencyGroupSchema{
+			Name:         name,
+			Dependencies: dependencies,
+		})
+	}
+	sort.Sort(data.TestDependencies)
+	for name, tests := range config.testGroups {
+		data.TestGroups = append(data.TestGroups, testGroupSchema{
+			Name:  name,
+			Tests: tests,
+		})
+	}
+	sort.Sort(data.TestGroups)
+	for name, parts := range config.testParts {
+		data.TestParts = append(data.TestParts, partGroupSchema{
+			Name:  name,
+			Parts: parts,
+		})
+	}
+	sort.Sort(data.TestParts)
+	for _, workspace := range config.vdlWorkspaces {
+		data.VDLWorkspaces = append(data.VDLWorkspaces, workspace)
+	}
+	sort.Strings(data.VDLWorkspaces)
+	bytes, err := xml.MarshalIndent(data, "", "  ")
+	if err != nil {
+		return fmt.Errorf("MarshalIndent(%v) failed: %v", data, err)
+	}
+	s := jirix.NewSeq()
+	if err := s.MkdirAll(filepath.Dir(path), os.FileMode(0755)).
+		WriteFile(path, bytes, os.FileMode(0644)).Done(); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/tooldata/config_test.go b/tooldata/config_test.go
new file mode 100644
index 0000000..1b16de8
--- /dev/null
+++ b/tooldata/config_test.go
@@ -0,0 +1,197 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tooldata_test
+
+import (
+	"path/filepath"
+	"reflect"
+	"testing"
+
+	"v.io/jiri/jiritest"
+	"v.io/jiri/project"
+	"v.io/x/devtools/tooldata"
+)
+
+var (
+	apiCheckProjects = map[string]struct{}{
+		"projectA": struct{}{},
+		"projectB": struct{}{},
+	}
+	copyrightCheckProjects = map[string]struct{}{
+		"projectC": struct{}{},
+		"projectD": struct{}{},
+	}
+	goWorkspaces      = []string{"test-go-workspace"}
+	jenkinsMatrixJobs = map[string]tooldata.JenkinsMatrixJobInfo{
+		"test-job-A": {
+			HasArch:  false,
+			HasOS:    true,
+			HasParts: true,
+			ShowOS:   false,
+			Name:     "test-job-A",
+		},
+		"test-job-B": {
+			HasArch:  true,
+			HasOS:    false,
+			HasParts: false,
+			ShowOS:   false,
+			Name:     "test-job-B",
+		},
+	}
+	projectTests = map[string][]string{
+		"test-project":  []string{"test-test-A", "test-test-group"},
+		"test-project2": []string{"test-test-D"},
+	}
+	testDependencies = map[string][]string{
+		"test-test-A": []string{"test-test-B"},
+		"test-test-B": []string{"test-test-C"},
+	}
+	testGroups = map[string][]string{
+		"test-test-group": []string{"test-test-B", "test-test-C"},
+	}
+	testParts = map[string][]string{
+		"test-test-A": []string{"p1", "p2"},
+	}
+	vdlWorkspaces = []string{"test-vdl-workspace"}
+)
+
+func testConfigAPI(t *testing.T, c *tooldata.Config) {
+	if got, want := c.APICheckProjects(), apiCheckProjects; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected results: got %v, want %v", got, want)
+	}
+	if got, want := c.CopyrightCheckProjects(), copyrightCheckProjects; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected results: got %v, want %v", got, want)
+	}
+	if got, want := c.GoWorkspaces(), goWorkspaces; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.GroupTests([]string{"test-test-group"}), []string{"test-test-B", "test-test-C"}; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.JenkinsMatrixJobs(), jenkinsMatrixJobs; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.Projects(), []string{"test-project", "test-project2"}; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.ProjectTests([]string{"test-project"}), []string{"test-test-A", "test-test-B", "test-test-C"}; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.ProjectTests([]string{"test-project", "test-project2"}), []string{"test-test-A", "test-test-B", "test-test-C", "test-test-D"}; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.TestDependencies("test-test-A"), []string{"test-test-B"}; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.TestDependencies("test-test-B"), []string{"test-test-C"}; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.TestParts("test-test-A"), []string{"p1", "p2"}; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+	if got, want := c.VDLWorkspaces(), vdlWorkspaces; !reflect.DeepEqual(got, want) {
+		t.Fatalf("unexpected result: got %v, want %v", got, want)
+	}
+}
+
+func TestConfigAPI(t *testing.T) {
+	config := tooldata.NewConfig(
+		tooldata.APICheckProjectsOpt(apiCheckProjects),
+		tooldata.CopyrightCheckProjectsOpt(copyrightCheckProjects),
+		tooldata.GoWorkspacesOpt(goWorkspaces),
+		tooldata.JenkinsMatrixJobsOpt(jenkinsMatrixJobs),
+		tooldata.ProjectTestsOpt(projectTests),
+		tooldata.TestDependenciesOpt(testDependencies),
+		tooldata.TestGroupsOpt(testGroups),
+		tooldata.TestPartsOpt(testParts),
+		tooldata.VDLWorkspacesOpt(vdlWorkspaces),
+	)
+
+	testConfigAPI(t, config)
+}
+
+func TestConfigSerialization(t *testing.T) {
+	fake, cleanup := jiritest.NewFakeJiriRoot(t)
+	defer cleanup()
+
+	config := tooldata.NewConfig(
+		tooldata.APICheckProjectsOpt(apiCheckProjects),
+		tooldata.CopyrightCheckProjectsOpt(copyrightCheckProjects),
+		tooldata.GoWorkspacesOpt(goWorkspaces),
+		tooldata.JenkinsMatrixJobsOpt(jenkinsMatrixJobs),
+		tooldata.ProjectTestsOpt(projectTests),
+		tooldata.TestDependenciesOpt(testDependencies),
+		tooldata.TestGroupsOpt(testGroups),
+		tooldata.TestPartsOpt(testParts),
+		tooldata.VDLWorkspacesOpt(vdlWorkspaces),
+	)
+
+	if err := tooldata.SaveConfig(fake.X, config); err != nil {
+		t.Fatalf("%v", err)
+	}
+	gotConfig, err := tooldata.LoadConfig(fake.X)
+	if err != nil {
+		t.Fatalf("%v", err)
+	}
+
+	testConfigAPI(t, gotConfig)
+}
+
+func testSetPathHelper(t *testing.T, name string) {
+	fake, cleanup := jiritest.NewFakeJiriRoot(t)
+	defer cleanup()
+
+	// Create a test project and identify it as a Go workspace.
+	if err := fake.CreateRemoteProject("test"); err != nil {
+		t.Fatalf("%v", err)
+	}
+	if err := fake.AddProject(project.Project{
+		Name:   "test",
+		Path:   "test",
+		Remote: fake.Projects["test"],
+	}); err != nil {
+		t.Fatalf("%v", err)
+	}
+	if err := fake.UpdateUniverse(false); err != nil {
+		t.Fatalf("%v", err)
+	}
+	var config *tooldata.Config
+	switch name {
+	case "GOPATH":
+		config = tooldata.NewConfig(tooldata.GoWorkspacesOpt([]string{"test", "does/not/exist"}))
+	case "VDLPATH":
+		config = tooldata.NewConfig(tooldata.VDLWorkspacesOpt([]string{"test", "does/not/exist"}))
+	}
+
+	if err := tooldata.SaveConfig(fake.X, config); err != nil {
+		t.Fatalf("%v", err)
+	}
+
+	var got, want string
+	switch name {
+	case "GOPATH":
+		want = "GOPATH=" + filepath.Join(fake.X.Root, "test")
+		got = config.GoPath(fake.X)
+	case "VDLPATH":
+		// Make a fake src directory.
+		want = filepath.Join(fake.X.Root, "test", "src")
+		if err := fake.X.NewSeq().MkdirAll(want, 0755).Done(); err != nil {
+			t.Fatalf("%v", err)
+		}
+		want = "VDLPATH=" + want
+		got = config.VDLPath(fake.X)
+	}
+	if got != want {
+		t.Fatalf("unexpected value: got %v, want %v", got, want)
+	}
+}
+
+func TestGoPath(t *testing.T) {
+	testSetPathHelper(t, "GOPATH")
+}
+
+func TestVDLPath(t *testing.T) {
+	testSetPathHelper(t, "VDLPATH")
+}
diff --git a/tooldata/data/AUTHORS b/tooldata/data/AUTHORS
new file mode 100644
index 0000000..574583c
--- /dev/null
+++ b/tooldata/data/AUTHORS
@@ -0,0 +1,9 @@
+# This is the official list of Vanadium authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as:
+#   Name or Organization <email address>
+# The email address is not required for organizations.
+
+# Please keep the list sorted.
diff --git a/tooldata/data/CONTRIBUTING.md b/tooldata/data/CONTRIBUTING.md
new file mode 100644
index 0000000..de03ce0
--- /dev/null
+++ b/tooldata/data/CONTRIBUTING.md
@@ -0,0 +1,23 @@
+# Contributing to Vanadium
+
+Vanadium is an open source project.
+
+It is the work of many contributors. We appreciate your help!
+
+## Filing issues
+
+We use a single GitHub repository for [tracking all
+issues](https://github.com/vanadium/issues/issues) across all Vanadium
+repositories.
+
+## Contributing code
+
+Please read the [contribution
+guidelines](https://vanadium.github.io/community/contributing.html) before
+sending patches.
+
+**We do not accept GitHub pull requests.** (We use
+[Gerrit](https://www.gerritcodereview.com/) instead for code reviews.)
+
+Unless otherwise noted, the Vanadium source files are distributed under the
+BSD-style license found in the LICENSE file.
diff --git a/tooldata/data/CONTRIBUTORS b/tooldata/data/CONTRIBUTORS
new file mode 100644
index 0000000..b294e50
--- /dev/null
+++ b/tooldata/data/CONTRIBUTORS
@@ -0,0 +1,10 @@
+# People who have agreed to one of the CLAs and can contribute patches.
+# The AUTHORS file lists the copyright holders; this file
+# lists people.  For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+# https://developers.google.com/open-source/cla/individual
+# https://developers.google.com/open-source/cla/corporate
+#
+# Names should be added to this file as:
+#     Name <email address>
diff --git a/tooldata/data/COPYRIGHT b/tooldata/data/COPYRIGHT
new file mode 100644
index 0000000..a26470e
--- /dev/null
+++ b/tooldata/data/COPYRIGHT
@@ -0,0 +1,3 @@
+Copyright [YEAR] The Vanadium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file.
\ No newline at end of file
diff --git a/tooldata/data/LICENSE b/tooldata/data/LICENSE
new file mode 100644
index 0000000..411db13
--- /dev/null
+++ b/tooldata/data/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2015 The Vanadium Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tooldata/data/PATENTS b/tooldata/data/PATENTS
new file mode 100644
index 0000000..d52cc55
--- /dev/null
+++ b/tooldata/data/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Vanadium project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Vanadium, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Vanadium. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Vanadium or any code incorporated within this
+implementation of Vanadium constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Vanadium
+shall terminate as of the date such litigation is filed.
diff --git a/tooldata/data/VERSION b/tooldata/data/VERSION
new file mode 100644
index 0000000..603150b
--- /dev/null
+++ b/tooldata/data/VERSION
@@ -0,0 +1 @@
+jiri-0.1
diff --git a/tooldata/data/aliases.v1.xml b/tooldata/data/aliases.v1.xml
new file mode 100644
index 0000000..d013d35
--- /dev/null
+++ b/tooldata/data/aliases.v1.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>
+<aliases>
+  <email>
+    <canonical>aghassemi@google.com</canonical>
+    <alias>aghassemi@aghassemi-macbookpro.roam.corp.google.com</alias>
+  </email>
+  <email>
+    <canonical>sadovsky@google.com</canonical>
+    <alias>asadovsky@gmail.com</alias>
+  </email>
+  <email>
+    <canonical>nevenag@google.com</canonical>
+    <alias>nevena.golubovic@gmail.com</alias>
+  </email>
+  <email>
+    <canonical>jregan@google.com</canonical>
+    <alias>git-jregan.google.com</alias>
+  </email>
+  <email>
+    <canonical>rjkroege@google.com</canonical>
+    <alias>rjkroege@chromium.org</alias>
+  </email>
+  <email>
+    <canonical>sjr@google.com</canonical>
+    <alias>sjr@jdns.org</alias>
+  </email>
+  <name>
+    <canonical>Ali Ghassemi</canonical>
+    <alias>aghassemi</alias>
+  </name>
+  <name>
+    <canonical>Ankur Taly</canonical>
+    <alias>Ankur</alias>
+  </name>
+  <name>
+    <canonical>Benjamin Prosnitz</canonical>
+    <alias>Benj Prosnitz</alias>
+  </name>
+  <name>
+    <canonical>Dave Presotto</canonical>
+    <alias>David Why Use Two When One Will Do Presotto</alias>
+    <alias>David Presotto</alias>
+  </name>
+  <name>
+    <canonical>Gautham Thambidorai</canonical>
+    <alias>Gautham</alias>
+    <alias>gauthamt</alias>
+  </name>
+  <name>
+    <canonical>Elizabeth Churchill</canonical>
+    <alias>xeeliz</alias>
+  </name>
+  <name>
+    <canonical>Ellen Isaacs</canonical>
+    <alias>lnizix</alias>
+  </name>
+  <name>
+    <canonical>Jeffrey Regan</canonical>
+    <alias>jregan</alias>
+  </name>
+  <name>
+    <canonical>Nicolas LaCasse</canonical>
+    <alias>Nicolas Lacasse</alias>
+  </name>
+  <name>
+    <canonical>William Leler</canonical>
+    <alias>Wm Leler</alias>
+    <alias>wmleler</alias>
+  </name>
+</aliases>
diff --git a/tooldata/data/config.v1.xml b/tooldata/data/config.v1.xml
new file mode 100644
index 0000000..3862c5c
--- /dev/null
+++ b/tooldata/data/config.v1.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" ?>
+<config>
+  <apiCheckProjects>
+    <project>release.go.jiri</project>
+    <project>release.go.v23</project>
+    <project>release.go.x.devtools</project>
+    <project>release.go.x.lib</project>
+  </apiCheckProjects>
+  <copyrightCheckProjects>
+    <project>release.go.jiri</project>
+    <project>release.go.v23</project>
+    <project>release.go.x.devtools</project>
+    <project>release.go.x.jni</project>
+    <project>release.go.x.lib</project>
+    <project>release.go.x.ref</project>
+    <project>release.java</project>
+    <project>release.js.core</project>
+    <project>release.js.syncbase</project>
+    <project>release.mojo.discovery</project>
+    <project>release.mojo.shared</project>
+    <project>release.mojo.syncbase</project>
+    <project>release.mojo.v23proxy</project>
+    <project>release.projects.baku</project>
+    <project>release.projects.browser</project>
+    <project>release.projects.chat</project>
+    <project>release.projects.croupier</project>
+    <project>release.projects.media-sharing</project>
+    <project>release.projects.physical-lock</project>
+    <project>release.projects.pipe2browser</project>
+    <project>release.projects.playground</project>
+    <project>release.projects.reader</project>
+    <project>release.projects.sensorlog</project>
+    <project>release.projects.syncslides</project>
+    <project>release.projects.travel</project>
+    <project>release.projects.todos</project>
+    <project>website</project>
+  </copyrightCheckProjects>
+  <goWorkspaces>
+    <workspace>infrastructure/go</workspace>
+    <workspace>release/go</workspace>
+    <workspace>release/javascript/core/go</workspace>
+    <workspace>release/projects/physical-lock/go</workspace>
+    <workspace>release/projects/sensorlog/go</workspace>
+    <workspace>roadmap/go</workspace>
+    <workspace>third_party/go</workspace>
+  </goWorkspaces>
+  <jenkinsMatrixJobs>
+    <job arch="false" OS="true" parts="false" showOS="true">third_party-go-build</job>
+    <job arch="false" OS="true" parts="false" showOS="true">third_party-go-test</job>
+    <job arch="false" OS="true" parts="true"  showOS="false">third_party-go-race</job>
+    <!-- TODO(spetrovic): this is flaky due to profile issues.  Re-enable after fixing.
+    <job arch="false" OS="true" parts="false" showOS="true">vanadium-android-build</job>
+    -->
+    <job arch="false" OS="true" parts="false" showOS="false">vanadium-bootstrap</job>
+    <job arch="true"  OS="true" parts="false" showOS="true">vanadium-go-build</job>
+    <job arch="true"  OS="true" parts="false" showOS="true">vanadium-go-test</job>
+    <job arch="false" OS="true" parts="true"  showOS="false">vanadium-go-race</job>
+    <job arch="false" OS="true" parts="false" showOS="true">vanadium-integration-test</job>
+    <job arch="false" OS="true" parts="false" showOS="true">vanadium-java-test</job>
+    <job arch="false" OS="true" parts="false" showOS="true">vanadium-website-site</job>
+    <job arch="false" OS="true" parts="false" showOS="true">vanadium-website-tutorials-core</job>
+    <job arch="false" OS="true" parts="false" showOS="true">vanadium-website-tutorials-external</job>
+    <job arch="false" OS="true" parts="false" showOS="true">vanadium-website-tutorials-java</job>
+  </jenkinsMatrixJobs>
+  <projectTests>
+    <project name="release.go.jiri">
+      <test>go</test>
+      <test>java</test>
+      <test>javascript</test>
+      <test>projects</test>
+      <test>vanadium-bootstrap</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.go.v23">
+      <test>go</test>
+      <test>java</test>
+      <test>javascript</test>
+      <test>mojo</test>
+      <test>projects</test>
+      <test>vanadium-bootstrap</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.go.x.devtools">
+      <test>go</test>
+      <test>java</test>
+      <test>javascript</test>
+      <test>mojo</test>
+      <test>projects</test>
+      <test>third_party-go</test>
+      <test>vanadium-bootstrap</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.go.x.jni">
+      <test>java</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.go.x.lib">
+      <test>go</test>
+      <test>java</test>
+      <test>javascript</test>
+      <test>mojo</test>
+      <test>projects</test>
+      <test>vanadium-bootstrap</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.go.x.ref">
+      <test>go</test>
+      <test>java</test>
+      <test>javascript</test>
+      <test>mojo</test>
+      <test>projects</test>
+      <test>vanadium-bootstrap</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.java">
+      <test>java</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.js.core">
+      <test>javascript</test>
+      <test>projects</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.mojo.discovery">
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.mojo.shared">
+      <test>mojo</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.mojo.syncbase">
+      <test>mojo</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.mojo.v23proxy">
+      <test>mojo</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.projects.baku">
+      <test>vanadium-copyright</test>
+      <test>vanadium-baku-test</test>
+    </project>
+    <project name="release.projects.croupier">
+      <test>vanadium-copyright</test>
+      <test>vanadium-croupier-unit</test>
+    </project>
+    <project name="release.projects.playground">
+      <test>vanadium-copyright</test>
+      <test>vanadium-playground-test</test>
+    </project>
+    <project name="release.projects.reader">
+      <test>vanadium-copyright</test>
+      <test>vanadium-reader-test</test>
+    </project>
+    <project name="release.projects.sensorlog">
+      <test>go</test>
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.projects.syncslides">
+      <test>vanadium-copyright</test>
+    </project>
+    <project name="release.projects.travel">
+      <test>vanadium-copyright</test>
+      <test>vanadium-travel-test</test>
+    </project>
+    <project name="third_party">
+      <test>go</test>
+      <test>javascript</test>
+      <test>projects</test>
+      <test>third_party-go</test>
+    </project>
+    <project name="website">
+      <test>vanadium-bootstrap</test>
+      <test>vanadium-copyright</test>
+      <test>vanadium-website-site</test>
+      <test>vanadium-website-tutorials-core</test>
+    </project>
+  </projectTests>
+  <testDependencies>
+    <test name="third_party-go-race">
+      <dependency>third_party-go-test</dependency>
+    </test>
+    <test name="third_party-go-test">
+      <dependency>third_party-go-build</dependency>
+    </test>
+    <test name="vanadium-playground-test">
+      <dependency>vanadium-go-build</dependency>
+    </test>
+    <test name="vanadium-go-race">
+      <dependency>vanadium-go-test</dependency>
+    </test>
+    <test name="vanadium-go-test">
+      <dependency>vanadium-go-build</dependency>
+    </test>
+    <test name="vanadium-integration-test">
+      <dependency>vanadium-go-build</dependency>
+    </test>
+  </testDependencies>
+  <testGroups>
+    <group name="go">
+      <test>vanadium-go-api</test>
+      <test>vanadium-go-build</test>
+      <test>vanadium-go-depcop</test>
+      <test>vanadium-go-format</test>
+      <test>vanadium-go-generate</test>
+      <test>vanadium-go-race</test>
+      <test>vanadium-go-test</test>
+      <test>vanadium-go-vdl</test>
+      <!-- TODO(sjr): figure out what to do with go vet. It currently produces
+           false positives which we can't workaround with CLs like
+           https://vanadium.googlesource.com/third_party/+/5e07c533eb2dfa525b5d0f3782112a2a5c4b6912,
+           because go vet moved back into core go as of Go 1.5.
+      <test>vanadium-go-vet</test>
+      -->
+      <test>vanadium-integration-test</test>
+      <test>vanadium-regression-test</test>
+      <test>vanadium-prod-services-test</test>
+      <test>vanadium-website-tutorials-core</test>
+    </group>
+    <group name="java">
+      <test>baku-android-build</test>
+      <test>baku-java-test</test>
+      <!-- TODO(spetrovic): this is flaky due to profile issues.  Re-enable after fixing.
+      <test>vanadium-android-build</test>
+      -->
+      <test>vanadium-java-test</test>
+    </group>
+    <group name="javascript">
+      <test>vanadium-js-unit</test>
+      <test>vanadium-js-vdl</test>
+      <test>vanadium-js-vdl-audit</test>
+      <test>vanadium-js-vom</test>
+    </group>
+    <group name="mojo">
+      <!-- NOTE(caprita): this is flaky. See v.io/i/1240
+      <test>vanadium-mojo-discovery-test</test>
+      -->
+      <test>vanadium-mojo-syncbase-test</test>
+      <test>vanadium-mojo-v23proxy-unit-test</test>
+      <!-- NOTE(caprita): this is flaky.  See v.io/i/1226
+      <test>vanadium-mojo-v23proxy-integration-test</test>
+      -->
+    </group>
+    <group name="projects">
+      <test>vanadium-playground-test</test>
+    </group>
+    <group name="third_party-go">
+      <test>third_party-go-build</test>
+      <test>third_party-go-race</test>
+      <test>third_party-go-test</test>
+    </group>
+  </testGroups>
+  <testParts>
+    <test name="vanadium-go-race">
+      <part>v.io/x/ref/services/device/...</part>
+      <part>v.io/x/ref/services/agent/...,v.io/x/ref/services/internal/...,v.io/x/ref/services/syncbase/...</part>
+      <part>v.io/x/ref/services/...</part>
+      <part>v.io/x/ref/runtime/...</part>
+      <part>v.io/x/ref/...</part>
+      <part>v.io/x/devtools/...</part>
+    </test>
+    <test name="third_party-go-race">
+      <part>golang.org/x/tools/go/ssa/...,golang.org/x/tools/go/pointer/...</part>
+      <part>golang.org/x/tools/...</part>
+      <part>golang.org/x/crypto/...</part>
+    </test>
+  </testParts>
+  <vdlWorkspaces>
+    <workspace>release/go</workspace>
+    <workspace>release/javascript/core/go</workspace>
+    <workspace>release/projects/physical-lock/go</workspace>
+    <workspace>release/projects/sensorlog/go</workspace>
+    <workspace>roadmap/go</workspace>
+  </vdlWorkspaces>
+</config>
diff --git a/tooldata/data/crosstool-ng-1.19.0.config b/tooldata/data/crosstool-ng-1.19.0.config
new file mode 100644
index 0000000..8808fd2
--- /dev/null
+++ b/tooldata/data/crosstool-ng-1.19.0.config
@@ -0,0 +1,538 @@
+#
+# Automatically generated make config: don't edit
+# crosstool-NG 1.19.0 Configuration
+# Sat Jul 12 19:46:11 2014
+#
+CT_CONFIGURE_has_xz=y
+CT_CONFIGURE_has_cvs=y
+CT_CONFIGURE_has_svn=y
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR=""
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_PREFIX_DIR="/usr/local/vanadium/xgcc/${CT_TARGET}"
+CT_INSTALL_DIR="${CT_PREFIX_DIR}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_DIR_RO=y
+CT_STRIP_ALL_TOOLCHAIN_EXECUTABLES=y
+
+#
+# Downloading
+#
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+# CT_ONLY_DOWNLOAD is not set
+# CT_USE_MIRROR is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+CT_PATCH_BUNDLED=y
+# CT_PATCH_LOCAL is not set
+# CT_PATCH_BUNDLED_LOCAL is not set
+# CT_PATCH_LOCAL_BUNDLED is not set
+# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
+# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
+# CT_PATCH_NONE is not set
+CT_PATCH_ORDER="bundled"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+CT_LOG_INFO=y
+# CT_LOG_EXTRA is not set
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="INFO"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+CT_ARCH="arm"
+CT_ARCH_SUPPORTS_BOTH_MMU=y
+CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_CPU=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_SUPPORTS_WITH_FPU=y
+CT_ARCH_SUPPORTS_SOFTFP=y
+CT_ARCH_DEFAULT_HAS_MMU=y
+CT_ARCH_DEFAULT_LE=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_ARCH=""
+CT_ARCH_CPU=""
+CT_ARCH_TUNE=""
+CT_ARCH_FPU=""
+# CT_ARCH_BE is not set
+CT_ARCH_LE=y
+CT_ARCH_32=y
+CT_ARCH_BITNESS=32
+CT_ARCH_FLOAT_HW=y
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+# CT_ARCH_alpha is not set
+CT_ARCH_arm=y
+# CT_ARCH_avr32 is not set
+# CT_ARCH_blackfin is not set
+# CT_ARCH_m68k is not set
+# CT_ARCH_mips is not set
+# CT_ARCH_powerpc is not set
+# CT_ARCH_s390 is not set
+# CT_ARCH_sh is not set
+# CT_ARCH_sparc is not set
+# CT_ARCH_x86 is not set
+CT_ARCH_alpha_AVAILABLE=y
+CT_ARCH_arm_AVAILABLE=y
+CT_ARCH_avr32_AVAILABLE=y
+CT_ARCH_blackfin_AVAILABLE=y
+CT_ARCH_m68k_AVAILABLE=y
+CT_ARCH_microblaze_AVAILABLE=y
+CT_ARCH_mips_AVAILABLE=y
+CT_ARCH_powerpc_AVAILABLE=y
+CT_ARCH_s390_AVAILABLE=y
+CT_ARCH_sh_AVAILABLE=y
+CT_ARCH_sparc_AVAILABLE=y
+CT_ARCH_x86_AVAILABLE=y
+CT_ARCH_SUFFIX=""
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_ARCH_USE_MMU=y
+CT_ARCH_ENDIAN="little"
+
+#
+# Target optimisations
+#
+# CT_ARCH_FLOAT_SOFTFP is not set
+CT_ARCH_FLOAT="hard"
+
+#
+# arm other options
+#
+CT_ARCH_ARM_MODE="arm"
+CT_ARCH_ARM_MODE_ARM=y
+# CT_ARCH_ARM_MODE_THUMB is not set
+# CT_ARCH_ARM_INTERWORKING is not set
+CT_ARCH_ARM_EABI_FORCE=y
+CT_ARCH_ARM_EABI=y
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+CT_KERNEL="linux"
+CT_KERNEL_VERSION="3.10.2"
+# CT_KERNEL_bare_metal is not set
+CT_KERNEL_linux=y
+CT_KERNEL_bare_metal_AVAILABLE=y
+CT_KERNEL_linux_AVAILABLE=y
+CT_KERNEL_V_3_10=y
+# CT_KERNEL_V_3_9 is not set
+# CT_KERNEL_V_3_8 is not set
+# CT_KERNEL_V_3_7 is not set
+# CT_KERNEL_V_3_6 is not set
+# CT_KERNEL_V_3_5 is not set
+# CT_KERNEL_V_3_4 is not set
+# CT_KERNEL_V_3_3 is not set
+# CT_KERNEL_V_3_2 is not set
+# CT_KERNEL_V_3_1 is not set
+# CT_KERNEL_V_3_0 is not set
+# CT_KERNEL_V_2_6_39 is not set
+# CT_KERNEL_V_2_6_38 is not set
+# CT_KERNEL_V_2_6_37 is not set
+# CT_KERNEL_V_2_6_36 is not set
+# CT_KERNEL_V_2_6_33 is not set
+# CT_KERNEL_V_2_6_32 is not set
+# CT_KERNEL_V_2_6_31 is not set
+# CT_KERNEL_V_2_6_27 is not set
+# CT_KERNEL_LINUX_CUSTOM is not set
+CT_KERNEL_windows_AVAILABLE=y
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# linux other options
+#
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_binutils=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_V_2_22=y
+# CT_BINUTILS_V_2_21_53 is not set
+# CT_BINUTILS_V_2_21_1a is not set
+# CT_BINUTILS_V_2_20_1a is not set
+# CT_BINUTILS_V_2_19_1a is not set
+# CT_BINUTILS_V_2_18a is not set
+CT_BINUTILS_VERSION="2.22"
+CT_BINUTILS_2_22_or_later=y
+CT_BINUTILS_2_21_or_later=y
+CT_BINUTILS_2_20_or_later=y
+CT_BINUTILS_2_19_or_later=y
+CT_BINUTILS_2_18_or_later=y
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD=y
+CT_BINUTILS_LINKER_LD=y
+# CT_BINUTILS_LINKER_LD_GOLD is not set
+# CT_BINUTILS_LINKER_GOLD_LD is not set
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+
+#
+# binutils other options
+#
+
+#
+# C compiler
+#
+CT_CC="gcc"
+CT_CC_VERSION="4.8.1"
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_gcc=y
+# CT_CC_GCC_SHOW_LINARO is not set
+CT_CC_V_4_8_1=y
+# CT_CC_V_4_8_0 is not set
+# CT_CC_V_4_7_3 is not set
+# CT_CC_V_4_7_2 is not set
+# CT_CC_V_4_7_1 is not set
+# CT_CC_V_4_7_0 is not set
+# CT_CC_V_4_6_4 is not set
+# CT_CC_V_4_6_3 is not set
+# CT_CC_V_4_6_2 is not set
+# CT_CC_V_4_6_1 is not set
+# CT_CC_V_4_6_0 is not set
+# CT_CC_V_4_5_3 is not set
+# CT_CC_V_4_5_2 is not set
+# CT_CC_V_4_5_1 is not set
+# CT_CC_V_4_5_0 is not set
+# CT_CC_V_4_4_7 is not set
+# CT_CC_V_4_4_6 is not set
+# CT_CC_V_4_4_5 is not set
+# CT_CC_V_4_4_4 is not set
+# CT_CC_V_4_4_3 is not set
+# CT_CC_V_4_4_2 is not set
+# CT_CC_V_4_4_1 is not set
+# CT_CC_V_4_4_0 is not set
+# CT_CC_V_4_3_6 is not set
+# CT_CC_V_4_3_5 is not set
+# CT_CC_V_4_3_4 is not set
+# CT_CC_V_4_3_3 is not set
+# CT_CC_V_4_3_2 is not set
+# CT_CC_V_4_3_1 is not set
+# CT_CC_V_4_2_4 is not set
+# CT_CC_V_4_2_2 is not set
+CT_CC_GCC_4_2_or_later=y
+CT_CC_GCC_4_3_or_later=y
+CT_CC_GCC_4_4_or_later=y
+CT_CC_GCC_4_5_or_later=y
+CT_CC_GCC_4_6_or_later=y
+CT_CC_GCC_4_7_or_later=y
+CT_CC_GCC_4_8=y
+CT_CC_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_GRAPHITE=y
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_HAS_LTO=y
+CT_CC_GCC_USE_LTO=y
+CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
+CT_CC_GCC_HAS_BUILD_ID=y
+CT_CC_GCC_HAS_LNK_HASH_STYLE=y
+CT_CC_GCC_USE_GMP_MPFR=y
+CT_CC_GCC_USE_MPC=y
+CT_CC_GCC_HAS_LIBQUADMATH=y
+# CT_CC_LANG_FORTRAN is not set
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_JAVA=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_JAVA is not set
+
+#
+# gcc other options
+#
+CT_CC_ENABLE_CXX_FLAGS=""
+CT_CC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_EXTRA_CONFIG_ARRAY=""
+CT_CC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+
+#
+# Optimisation features
+#
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+
+#
+# C-library
+#
+CT_LIBC="eglibc"
+CT_LIBC_VERSION="2_17"
+CT_LIBC_eglibc=y
+# CT_LIBC_glibc is not set
+# CT_LIBC_uClibc is not set
+CT_LIBC_eglibc_AVAILABLE=y
+CT_LIBC_EGLIBC_V_2_17=y
+# CT_LIBC_EGLIBC_V_2_16 is not set
+# CT_LIBC_EGLIBC_V_2_15 is not set
+# CT_LIBC_EGLIBC_V_2_14 is not set
+# CT_LIBC_EGLIBC_V_2_13 is not set
+# CT_LIBC_EGLIBC_V_2_12 is not set
+# CT_LIBC_EGLIBC_V_2_11 is not set
+# CT_LIBC_EGLIBC_V_2_10 is not set
+# CT_LIBC_EGLIBC_V_2_9 is not set
+# CT_LIBC_EGLIBC_V_TRUNK is not set
+CT_LIBC_EGLIBC_2_16_or_later=y
+CT_EGLIBC_REVISION="HEAD"
+# CT_EGLIBC_HTTP is not set
+# CT_EGLIBC_CHECKOUT is not set
+# CT_EGLIBC_OPT_SIZE is not set
+# CT_EGLIBC_CUSTOM_CONFIG is not set
+CT_LIBC_glibc_AVAILABLE=y
+CT_LIBC_mingw_AVAILABLE=y
+CT_LIBC_newlib_AVAILABLE=y
+CT_LIBC_none_AVAILABLE=y
+CT_LIBC_uClibc_AVAILABLE=y
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_NPTL=y
+CT_LIBC_SUPPORT_LINUXTHREADS=y
+CT_THREADS="nptl"
+
+#
+# Common C library options
+#
+CT_THREADS_NPTL=y
+# CT_THREADS_LINUXTHREADS is not set
+CT_LIBC_XLDD=y
+
+#
+# eglibc other options
+#
+CT_LIBC_GLIBC_MAY_FORCE_PORTS=y
+CT_LIBC_glibc_familly=y
+CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_LIBC_GLIBC_CONFIGPARMS=""
+CT_LIBC_GLIBC_EXTRA_CFLAGS=""
+CT_LIBC_EXTRA_CC_ARGS=""
+# CT_LIBC_DISABLE_VERSIONING is not set
+CT_LIBC_OLDEST_ABI=""
+CT_LIBC_GLIBC_FORCE_UNWIND=y
+CT_LIBC_GLIBC_USE_PORTS=y
+CT_LIBC_ADDONS_LIST=""
+
+#
+# WARNING !!!
+#
+
+#
+#   For glibc >= 2.8, it can happen that the tarballs
+#
+
+#
+#   for the addons are not available for download.
+#
+
+#
+#   If that happens, bad luck... Try a previous version
+#
+
+#
+#   or try again later... :-(
+#
+# CT_LIBC_LOCALES is not set
+# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
+CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_LIBC_GLIBC_MIN_KERNEL="3.10.2"
+
+#
+# Debug facilities
+#
+# CT_DEBUG_dmalloc is not set
+# CT_DEBUG_duma is not set
+# CT_DEBUG_gdb is not set
+# CT_DEBUG_ltrace is not set
+# CT_DEBUG_strace is not set
+
+#
+# Companion libraries
+#
+CT_COMPLIBS_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_CLOOG_NEEDED=y
+CT_MPC_NEEDED=y
+CT_COMPLIBS=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_CLOOG=y
+CT_MPC=y
+CT_GMP_V_5_1_1=y
+# CT_GMP_V_5_0_2 is not set
+# CT_GMP_V_5_0_1 is not set
+# CT_GMP_V_4_3_2 is not set
+# CT_GMP_V_4_3_1 is not set
+# CT_GMP_V_4_3_0 is not set
+CT_GMP_VERSION="5.1.1"
+CT_MPFR_V_3_1_2=y
+# CT_MPFR_V_3_1_0 is not set
+# CT_MPFR_V_3_0_1 is not set
+# CT_MPFR_V_3_0_0 is not set
+# CT_MPFR_V_2_4_2 is not set
+# CT_MPFR_V_2_4_1 is not set
+# CT_MPFR_V_2_4_0 is not set
+CT_MPFR_VERSION="3.1.2"
+CT_ISL_V_0_11_1=y
+CT_ISL_VERSION="0.11.1"
+CT_CLOOG_V_0_18_0=y
+CT_CLOOG_VERSION="0.18.0"
+CT_CLOOG_0_18_or_later=y
+CT_MPC_V_1_0_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_V_0_9 is not set
+# CT_MPC_V_0_8_2 is not set
+# CT_MPC_V_0_8_1 is not set
+# CT_MPC_V_0_7 is not set
+CT_MPC_VERSION="1.0.1"
+
+#
+# Companion libraries common options
+#
+# CT_COMPLIBS_CHECK is not set
diff --git a/tooldata/data/crosstool-ng-1.20.0.config b/tooldata/data/crosstool-ng-1.20.0.config
new file mode 100644
index 0000000..191cfb5
--- /dev/null
+++ b/tooldata/data/crosstool-ng-1.20.0.config
@@ -0,0 +1,633 @@
+#
+# Automatically generated make config: don't edit
+# crosstool-NG 1.20.0 Configuration
+# Wed Apr 29 23:28:05 2015
+#
+CT_CONFIGURE_has_make381=y
+CT_CONFIGURE_has_xz=y
+CT_CONFIGURE_has_cvs=y
+CT_CONFIGURE_has_svn=y
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR=""
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_PREFIX_DIR="/usr/local/vanadium/xgcc/${CT_TARGET}"
+CT_INSTALL_DIR="${CT_PREFIX_DIR}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_DIR_RO=y
+CT_STRIP_ALL_TOOLCHAIN_EXECUTABLES=y
+
+#
+# Downloading
+#
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+# CT_ONLY_DOWNLOAD is not set
+# CT_USE_MIRROR is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+CT_PATCH_BUNDLED=y
+# CT_PATCH_LOCAL is not set
+# CT_PATCH_BUNDLED_LOCAL is not set
+# CT_PATCH_LOCAL_BUNDLED is not set
+# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
+# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
+# CT_PATCH_NONE is not set
+CT_PATCH_ORDER="bundled"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+# CT_LOG_EXTRA is not set
+CT_LOG_ALL=y
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="ALL"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+CT_ARCH="arm"
+CT_ARCH_SUPPORTS_BOTH_MMU=y
+CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_CPU=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_SUPPORTS_WITH_FPU=y
+CT_ARCH_SUPPORTS_SOFTFP=y
+CT_ARCH_DEFAULT_HAS_MMU=y
+CT_ARCH_DEFAULT_LE=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_ARCH=""
+CT_ARCH_CPU=""
+CT_ARCH_TUNE=""
+CT_ARCH_FPU=""
+# CT_ARCH_BE is not set
+CT_ARCH_LE=y
+CT_ARCH_32=y
+# CT_ARCH_64 is not set
+CT_ARCH_BITNESS=32
+CT_ARCH_FLOAT_HW=y
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+# CT_ARCH_alpha is not set
+CT_ARCH_arm=y
+# CT_ARCH_avr32 is not set
+# CT_ARCH_blackfin is not set
+# CT_ARCH_m68k is not set
+# CT_ARCH_mips is not set
+# CT_ARCH_powerpc is not set
+# CT_ARCH_s390 is not set
+# CT_ARCH_sh is not set
+# CT_ARCH_sparc is not set
+# CT_ARCH_x86 is not set
+CT_ARCH_alpha_AVAILABLE=y
+CT_ARCH_arm_AVAILABLE=y
+CT_ARCH_avr32_AVAILABLE=y
+CT_ARCH_blackfin_AVAILABLE=y
+CT_ARCH_m68k_AVAILABLE=y
+CT_ARCH_microblaze_AVAILABLE=y
+CT_ARCH_mips_AVAILABLE=y
+CT_ARCH_powerpc_AVAILABLE=y
+CT_ARCH_s390_AVAILABLE=y
+CT_ARCH_sh_AVAILABLE=y
+CT_ARCH_sparc_AVAILABLE=y
+CT_ARCH_x86_AVAILABLE=y
+CT_ARCH_SUFFIX=""
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_ARCH_USE_MMU=y
+CT_ARCH_ENDIAN="little"
+
+#
+# Target optimisations
+#
+# CT_ARCH_FLOAT_AUTO is not set
+# CT_ARCH_FLOAT_SOFTFP is not set
+CT_ARCH_FLOAT="hard"
+
+#
+# arm other options
+#
+CT_ARCH_ARM_MODE="arm"
+CT_ARCH_ARM_MODE_ARM=y
+# CT_ARCH_ARM_MODE_THUMB is not set
+# CT_ARCH_ARM_INTERWORKING is not set
+CT_ARCH_ARM_EABI_FORCE=y
+CT_ARCH_ARM_EABI=y
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+CT_KERNEL="linux"
+CT_KERNEL_VERSION="3.10.47"
+# CT_KERNEL_bare_metal is not set
+CT_KERNEL_linux=y
+CT_KERNEL_bare_metal_AVAILABLE=y
+CT_KERNEL_linux_AVAILABLE=y
+# CT_KERNEL_V_3_15 is not set
+# CT_KERNEL_V_3_14 is not set
+# CT_KERNEL_V_3_13 is not set
+# CT_KERNEL_V_3_12 is not set
+# CT_KERNEL_V_3_11 is not set
+CT_KERNEL_V_3_10=y
+# CT_KERNEL_V_3_9 is not set
+# CT_KERNEL_V_3_8 is not set
+# CT_KERNEL_V_3_7 is not set
+# CT_KERNEL_V_3_6 is not set
+# CT_KERNEL_V_3_5 is not set
+# CT_KERNEL_V_3_4 is not set
+# CT_KERNEL_V_3_3 is not set
+# CT_KERNEL_V_3_2 is not set
+# CT_KERNEL_V_3_1 is not set
+# CT_KERNEL_V_3_0 is not set
+# CT_KERNEL_V_2_6_39 is not set
+# CT_KERNEL_V_2_6_38 is not set
+# CT_KERNEL_V_2_6_37 is not set
+# CT_KERNEL_V_2_6_36 is not set
+# CT_KERNEL_V_2_6_33 is not set
+# CT_KERNEL_V_2_6_32 is not set
+# CT_KERNEL_V_2_6_31 is not set
+# CT_KERNEL_V_2_6_27 is not set
+# CT_KERNEL_LINUX_CUSTOM is not set
+CT_KERNEL_windows_AVAILABLE=y
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# linux other options
+#
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_binutils=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_V_2_22=y
+# CT_BINUTILS_V_2_21_53 is not set
+# CT_BINUTILS_V_2_21_1a is not set
+# CT_BINUTILS_V_2_20_1a is not set
+# CT_BINUTILS_V_2_19_1a is not set
+# CT_BINUTILS_V_2_18a is not set
+CT_BINUTILS_VERSION="2.22"
+CT_BINUTILS_2_22_or_later=y
+CT_BINUTILS_2_21_or_later=y
+CT_BINUTILS_2_20_or_later=y
+CT_BINUTILS_2_19_or_later=y
+CT_BINUTILS_2_18_or_later=y
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD=y
+CT_BINUTILS_LINKER_LD=y
+# CT_BINUTILS_LINKER_LD_GOLD is not set
+# CT_BINUTILS_LINKER_GOLD_LD is not set
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+
+#
+# binutils other options
+#
+
+#
+# C-library
+#
+CT_LIBC="glibc"
+CT_LIBC_VERSION="2.19"
+# CT_LIBC_eglibc is not set
+CT_LIBC_glibc=y
+# CT_LIBC_musl is not set
+# CT_LIBC_uClibc is not set
+CT_LIBC_eglibc_AVAILABLE=y
+CT_THREADS="nptl"
+CT_LIBC_glibc_AVAILABLE=y
+CT_LIBC_GLIBC_V_2_19=y
+# CT_LIBC_GLIBC_V_2_18 is not set
+# CT_LIBC_GLIBC_V_2_17 is not set
+# CT_LIBC_GLIBC_V_2_16_0 is not set
+# CT_LIBC_GLIBC_V_2_15 is not set
+# CT_LIBC_GLIBC_V_2_14_1 is not set
+# CT_LIBC_GLIBC_V_2_14 is not set
+# CT_LIBC_GLIBC_V_2_13 is not set
+# CT_LIBC_GLIBC_V_2_12_2 is not set
+# CT_LIBC_GLIBC_V_2_12_1 is not set
+# CT_LIBC_GLIBC_V_2_11_1 is not set
+# CT_LIBC_GLIBC_V_2_11 is not set
+# CT_LIBC_GLIBC_V_2_10_1 is not set
+# CT_LIBC_GLIBC_V_2_9 is not set
+# CT_LIBC_GLIBC_V_2_8 is not set
+CT_LIBC_mingw_AVAILABLE=y
+CT_LIBC_musl_AVAILABLE=y
+CT_LIBC_newlib_AVAILABLE=y
+CT_LIBC_none_AVAILABLE=y
+CT_LIBC_uClibc_AVAILABLE=y
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+CT_LIBC_XLDD=y
+# CT_LIBC_GLIBC_PORTS_EXTERNAL is not set
+CT_LIBC_GLIBC_MAY_FORCE_PORTS=y
+CT_LIBC_glibc_familly=y
+CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_LIBC_GLIBC_CONFIGPARMS=""
+CT_LIBC_GLIBC_EXTRA_CFLAGS=""
+CT_LIBC_EXTRA_CC_ARGS=""
+# CT_LIBC_DISABLE_VERSIONING is not set
+CT_LIBC_OLDEST_ABI=""
+CT_LIBC_GLIBC_FORCE_UNWIND=y
+CT_LIBC_GLIBC_USE_PORTS=y
+CT_LIBC_ADDONS_LIST=""
+# CT_LIBC_LOCALES is not set
+# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
+CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_LIBC_GLIBC_MIN_KERNEL="3.10.47"
+
+#
+# glibc other options
+#
+
+#
+# WARNING !!!                                            
+#
+
+#
+#   For glibc >= 2.8, it can happen that the tarballs    
+#
+
+#
+#   for the addons are not available for download.       
+#
+
+#
+#   If that happens, bad luck... Try a previous version  
+#
+
+#
+#   or try again later... :-(                            
+#
+
+#
+# C compiler
+#
+CT_CC="gcc"
+CT_CC_VERSION="4.8.1"
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_gcc=y
+# CT_CC_GCC_SHOW_LINARO is not set
+# CT_CC_V_4_9_1 is not set
+# CT_CC_V_4_9_0 is not set
+# CT_CC_V_4_8_3 is not set
+# CT_CC_V_4_8_2 is not set
+CT_CC_V_4_8_1=y
+# CT_CC_V_4_8_0 is not set
+# CT_CC_V_4_7_4 is not set
+# CT_CC_V_4_7_3 is not set
+# CT_CC_V_4_7_2 is not set
+# CT_CC_V_4_7_1 is not set
+# CT_CC_V_4_7_0 is not set
+# CT_CC_V_4_6_4 is not set
+# CT_CC_V_4_6_3 is not set
+# CT_CC_V_4_6_2 is not set
+# CT_CC_V_4_6_1 is not set
+# CT_CC_V_4_6_0 is not set
+# CT_CC_V_4_5_3 is not set
+# CT_CC_V_4_5_2 is not set
+# CT_CC_V_4_5_1 is not set
+# CT_CC_V_4_5_0 is not set
+# CT_CC_V_4_4_7 is not set
+# CT_CC_V_4_4_6 is not set
+# CT_CC_V_4_4_5 is not set
+# CT_CC_V_4_4_4 is not set
+# CT_CC_V_4_4_3 is not set
+# CT_CC_V_4_4_2 is not set
+# CT_CC_V_4_4_1 is not set
+# CT_CC_V_4_4_0 is not set
+# CT_CC_V_4_3_6 is not set
+# CT_CC_V_4_3_5 is not set
+# CT_CC_V_4_3_4 is not set
+# CT_CC_V_4_3_3 is not set
+# CT_CC_V_4_3_2 is not set
+# CT_CC_V_4_3_1 is not set
+# CT_CC_V_4_2_4 is not set
+# CT_CC_V_4_2_2 is not set
+CT_CC_GCC_4_2_or_later=y
+CT_CC_GCC_4_3_or_later=y
+CT_CC_GCC_4_4_or_later=y
+CT_CC_GCC_4_5_or_later=y
+CT_CC_GCC_4_6_or_later=y
+CT_CC_GCC_4_7_or_later=y
+CT_CC_GCC_4_8=y
+CT_CC_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_GRAPHITE=y
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_HAS_LTO=y
+CT_CC_GCC_USE_LTO=y
+CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
+CT_CC_GCC_HAS_BUILD_ID=y
+CT_CC_GCC_HAS_LNK_HASH_STYLE=y
+CT_CC_GCC_USE_GMP_MPFR=y
+CT_CC_GCC_USE_MPC=y
+CT_CC_GCC_HAS_LIBQUADMATH=y
+CT_CC_GCC_HAS_LIBSANITIZER=y
+# CT_CC_LANG_FORTRAN is not set
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_JAVA=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_JAVA is not set
+
+#
+# gcc other options
+#
+CT_CC_ENABLE_CXX_FLAGS=""
+CT_CC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_EXTRA_CONFIG_ARRAY=""
+CT_CC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+
+#
+# Optimisation features
+#
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+
+#
+# Debug facilities
+#
+CT_DEBUG_dmalloc=y
+CT_DMALLOC_V_5_5_2=y
+CT_DMALLOC_VERSION="5.5.2"
+CT_DEBUG_duma=y
+CT_DUMA_A=y
+CT_DUMA_SO=y
+CT_DUMA_V_2_5_15=y
+CT_DUMA_VERSION="2_5_15"
+CT_DEBUG_gdb=y
+CT_GDB_CROSS=y
+# CT_GDB_CROSS_STATIC is not set
+# CT_GDB_CROSS_SIM is not set
+# CT_GDB_CROSS_PYTHON is not set
+CT_GDB_CROSS_EXTRA_CONFIG_ARRAY=""
+CT_GDB_NATIVE=y
+# CT_GDB_NATIVE_STATIC is not set
+CT_GDB_GDBSERVER=y
+CT_GDB_GDBSERVER_HAS_IPA_LIB=y
+CT_GDB_GDBSERVER_STATIC=y
+
+#
+# gdb version
+#
+# CT_DEBUG_GDB_SHOW_LINARO is not set
+CT_GDB_V_7_8=y
+# CT_GDB_V_7_7_1 is not set
+# CT_GDB_V_7_7 is not set
+# CT_GDB_V_7_6_1 is not set
+# CT_GDB_V_7_5_1 is not set
+# CT_GDB_V_7_4_1 is not set
+# CT_GDB_V_7_4 is not set
+# CT_GDB_V_7_3_1 is not set
+# CT_GDB_V_7_3a is not set
+# CT_GDB_V_7_2a is not set
+# CT_GDB_V_7_1a is not set
+# CT_GDB_V_7_0_1a is not set
+# CT_GDB_V_7_0a is not set
+# CT_GDB_V_6_8a is not set
+CT_GDB_7_2_or_later=y
+CT_GDB_7_0_or_later=y
+CT_GDB_HAS_PKGVERSION_BUGURL=y
+CT_GDB_HAS_PYTHON=y
+CT_GDB_INSTALL_GDBINIT=y
+CT_GDB_VERSION="7.8"
+CT_DEBUG_ltrace=y
+CT_LTRACE_V_0_7_3=y
+# CT_LTRACE_V_0_5_3 is not set
+# CT_LTRACE_V_0_5_2 is not set
+CT_LTRACE_VERSION="0.7.3"
+CT_DEBUG_strace=y
+CT_STRACE_V_4_8=y
+# CT_STRACE_V_4_7 is not set
+# CT_STRACE_V_4_6 is not set
+# CT_STRACE_V_4_5_20 is not set
+# CT_STRACE_V_4_5_19 is not set
+# CT_STRACE_V_4_5_18 is not set
+CT_STRACE_VERSION="4.8"
+
+#
+# Companion libraries
+#
+CT_COMPLIBS_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_CLOOG_NEEDED=y
+CT_MPC_NEEDED=y
+CT_COMPLIBS=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_CLOOG=y
+CT_MPC=y
+CT_LIBELF_TARGET=y
+# CT_GMP_V_5_1_3 is not set
+CT_GMP_V_5_1_1=y
+# CT_GMP_V_5_0_2 is not set
+# CT_GMP_V_5_0_1 is not set
+# CT_GMP_V_4_3_2 is not set
+# CT_GMP_V_4_3_1 is not set
+# CT_GMP_V_4_3_0 is not set
+CT_GMP_VERSION="5.1.1"
+CT_MPFR_V_3_1_2=y
+# CT_MPFR_V_3_1_0 is not set
+# CT_MPFR_V_3_0_1 is not set
+# CT_MPFR_V_3_0_0 is not set
+# CT_MPFR_V_2_4_2 is not set
+# CT_MPFR_V_2_4_1 is not set
+# CT_MPFR_V_2_4_0 is not set
+CT_MPFR_VERSION="3.1.2"
+# CT_ISL_V_0_12_2 is not set
+CT_ISL_V_0_11_1=y
+CT_ISL_VERSION="0.11.1"
+# CT_CLOOG_V_0_18_1 is not set
+CT_CLOOG_V_0_18_0=y
+CT_CLOOG_VERSION="0.18.0"
+CT_CLOOG_0_18_or_later=y
+# CT_MPC_V_1_0_2 is not set
+CT_MPC_V_1_0_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_V_0_9 is not set
+# CT_MPC_V_0_8_2 is not set
+# CT_MPC_V_0_8_1 is not set
+# CT_MPC_V_0_7 is not set
+CT_MPC_VERSION="1.0.1"
+
+#
+# libelf version needed to build for target
+#
+CT_LIBELF_V_0_8_13=y
+# CT_LIBELF_V_0_8_12 is not set
+CT_LIBELF_VERSION="0.8.13"
+
+#
+# Companion libraries common options
+#
+# CT_COMPLIBS_CHECK is not set
+
+#
+# Companion tools
+#
+
+#
+# READ HELP before you say 'Y' below !!!
+#
+# CT_COMP_TOOLS is not set
diff --git a/tooldata/data/oncall.v1.xml b/tooldata/data/oncall.v1.xml
new file mode 100644
index 0000000..087f553
--- /dev/null
+++ b/tooldata/data/oncall.v1.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" ?>
+<!--
+  This file has been auto generated. Please don't edit manually.
+-->
+<rotation>
+  <shift>
+    <primary>jlodhia</primary>
+    <secondary>herbertc</secondary>
+    <startDate>Mar 07, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>razvanm</primary>
+    <secondary>hpucha</secondary>
+    <startDate>Mar 14, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>mattr</primary>
+    <secondary>jasoncampbell</secondary>
+    <startDate>Mar 21, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>afergan</primary>
+    <secondary>alexfandrianto</secondary>
+    <startDate>Mar 28, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>kash</primary>
+    <secondary>jingjin</secondary>
+    <startDate>Apr 04, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>herbertc</primary>
+    <secondary>razvanm</secondary>
+    <startDate>Apr 11, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>ivanpi</primary>
+    <secondary>kash</secondary>
+    <startDate>Apr 18, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>jasoncampbell</primary>
+    <secondary>m3b</secondary>
+    <startDate>Apr 25, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>caprita</primary>
+    <secondary>jlodhia</secondary>
+    <startDate>May 02, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>nlacasse</primary>
+    <secondary>suharshs</secondary>
+    <startDate>May 09, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>suharshs</primary>
+    <secondary>nlacasse</secondary>
+    <startDate>May 16, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>rdaoud</primary>
+    <secondary>ribrdb</secondary>
+    <startDate>May 23, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>cnicolaou</primary>
+    <secondary>caprita</secondary>
+    <startDate>May 30, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>ashankar</primary>
+    <secondary>mattr</secondary>
+    <startDate>Jun 06, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>jhahn</primary>
+    <secondary>rdaoud</secondary>
+    <startDate>Jun 13, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>ribrdb</primary>
+    <secondary>aghassemi</secondary>
+    <startDate>Jun 20, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>afergan</primary>
+    <secondary>cierniak</secondary>
+    <startDate>Jun 27, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>gauthamt</primary>
+    <secondary>jyh</secondary>
+    <startDate>Jul 04, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>rosswang</primary>
+    <secondary>rthellend</secondary>
+    <startDate>Jul 11, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>hpucha</primary>
+    <secondary>ivanpi</secondary>
+    <startDate>Jul 18, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>rthellend</primary>
+    <secondary>rosswang</secondary>
+    <startDate>Jul 25, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>sadovsky</primary>
+    <secondary>aghassemi</secondary>
+    <startDate>Aug 01, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>bprosnitz</primary>
+    <secondary>sadovsky</secondary>
+    <startDate>Aug 08, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>spetrovic</primary>
+    <secondary>suharshs</secondary>
+    <startDate>Aug 15, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>suharshs</primary>
+    <secondary>spetrovic</secondary>
+    <startDate>Aug 22, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>toddw</primary>
+    <secondary>youngseokyoon</secondary>
+    <startDate>Aug 29, 2016 08:00:00 AM</startDate>
+  </shift>
+  <shift>
+    <primary>youngseokyoon</primary>
+    <secondary>toddw</secondary>
+    <startDate>Sep 05, 2016 08:00:00 AM</startDate>
+  </shift>
+</rotation>
\ No newline at end of file
diff --git a/tooldata/datadir.go b/tooldata/datadir.go
new file mode 100644
index 0000000..edada0b
--- /dev/null
+++ b/tooldata/datadir.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tooldata
+
+import (
+	"path/filepath"
+
+	"v.io/jiri"
+)
+
+// DataDirPath returns the path to the data directory of the given tool.
+func DataDirPath(jirix *jiri.X, toolName string) (string, error) {
+	return filepath.Join(jirix.Root, "release", "go", "src", "v.io", "x", "devtools", "tooldata", "data"), nil
+}
diff --git a/tooldata/doc.go b/tooldata/doc.go
new file mode 100644
index 0000000..aa20543
--- /dev/null
+++ b/tooldata/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// package tooldata provides routines for locating and reading tool
+// specific data.
+package tooldata
diff --git a/tooldata/oncall.go b/tooldata/oncall.go
new file mode 100644
index 0000000..b1dd61b
--- /dev/null
+++ b/tooldata/oncall.go
@@ -0,0 +1,66 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tooldata
+
+import (
+	"encoding/xml"
+	"fmt"
+	"io/ioutil"
+	"time"
+
+	"v.io/jiri"
+)
+
+type OncallRotation struct {
+	Shifts  []OncallShift `xml:"shift"`
+	XMLName xml.Name      `xml:"rotation"`
+}
+
+type OncallShift struct {
+	Primary   string `xml:"primary"`
+	Secondary string `xml:"secondary"`
+	Date      string `xml:"startDate"`
+}
+
+// LoadOncallRotation parses the default oncall schedule file.
+func LoadOncallRotation(jirix *jiri.X) (*OncallRotation, error) {
+	oncallRotationsFile, err := OncallRotationPath(jirix)
+	if err != nil {
+		return nil, err
+	}
+	content, err := ioutil.ReadFile(oncallRotationsFile)
+	if err != nil {
+		return nil, fmt.Errorf("ReadFile(%q) failed: %v", oncallRotationsFile, err)
+	}
+	rotation := OncallRotation{}
+	if err := xml.Unmarshal(content, &rotation); err != nil {
+		return nil, fmt.Errorf("Unmarshal(%q) failed: %v", string(content), err)
+	}
+	return &rotation, nil
+}
+
+// Oncall finds the oncall shift at the given time from the
+// oncall configuration file by comparing timestamps.
+func Oncall(jirix *jiri.X, targetTime time.Time) (*OncallShift, error) {
+	// Parse oncall configuration file.
+	rotation, err := LoadOncallRotation(jirix)
+	if err != nil {
+		return nil, err
+	}
+
+	// Find the oncall at targetTime.
+	layout := "Jan 2, 2006 3:04:05 PM"
+	for i := len(rotation.Shifts) - 1; i >= 0; i-- {
+		shift := rotation.Shifts[i]
+		t, err := time.ParseInLocation(layout, shift.Date, targetTime.Location())
+		if err != nil {
+			return nil, fmt.Errorf("Parse(%q, %v) failed: %v", layout, shift.Date, err)
+		}
+		if targetTime.Unix() >= t.Unix() {
+			return &shift, nil
+		}
+	}
+	return nil, nil
+}
diff --git a/tooldata/oncall_test.go b/tooldata/oncall_test.go
new file mode 100644
index 0000000..32c1e56
--- /dev/null
+++ b/tooldata/oncall_test.go
@@ -0,0 +1,102 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tooldata_test
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"testing"
+	"time"
+
+	"v.io/jiri"
+	"v.io/jiri/jiritest"
+	"v.io/x/devtools/tooldata"
+)
+
+func createOncallFile(t *testing.T, jirix *jiri.X) {
+	content := `<?xml version="1.0" ?>
+<rotation>
+  <shift>
+    <primary>spetrovic</primary>
+    <secondary>suharshs</secondary>
+    <startDate>Nov 5, 2014 12:00:00 PM</startDate>
+  </shift>
+  <shift>
+    <primary>suharshs</primary>
+    <secondary>jingjin</secondary>
+    <startDate>Nov 12, 2014 12:00:00 PM</startDate>
+  </shift>
+  <shift>
+    <primary>jsimsa</primary>
+    <secondary>toddw</secondary>
+    <startDate>Nov 19, 2014 12:00:00 PM</startDate>
+  </shift>
+</rotation>`
+	oncallRotationsFile, err := tooldata.OncallRotationPath(jirix)
+	if err != nil {
+		t.Fatalf("%v", err)
+	}
+	dir := filepath.Dir(oncallRotationsFile)
+	dirMode := os.FileMode(0700)
+	if err := jirix.NewSeq().MkdirAll(dir, dirMode).Done(); err != nil {
+		t.Fatalf("MkdirAll(%q, %v) failed: %v", dir, dirMode, err)
+	}
+	fileMode := os.FileMode(0644)
+	if err := ioutil.WriteFile(oncallRotationsFile, []byte(content), fileMode); err != nil {
+		t.Fatalf("WriteFile(%q, %q, %v) failed: %v", oncallRotationsFile, content, fileMode, err)
+	}
+}
+
+func TestOncall(t *testing.T) {
+	fake, cleanup := jiritest.NewFakeJiriRoot(t)
+	defer cleanup()
+
+	// Create a oncall.v1.xml file.
+	createOncallFile(t, fake.X)
+	testCases := []struct {
+		targetTime    time.Time
+		expectedShift *tooldata.OncallShift
+	}{
+		{
+			time.Date(2013, time.November, 5, 12, 0, 0, 0, time.Local),
+			nil,
+		},
+		{
+			time.Date(2014, time.November, 5, 12, 0, 0, 0, time.Local),
+			&tooldata.OncallShift{
+				Primary:   "spetrovic",
+				Secondary: "suharshs",
+				Date:      "Nov 5, 2014 12:00:00 PM",
+			},
+		},
+		{
+			time.Date(2014, time.November, 5, 14, 0, 0, 0, time.Local),
+			&tooldata.OncallShift{
+				Primary:   "spetrovic",
+				Secondary: "suharshs",
+				Date:      "Nov 5, 2014 12:00:00 PM",
+			},
+		},
+		{
+			time.Date(2014, time.November, 20, 14, 0, 0, 0, time.Local),
+			&tooldata.OncallShift{
+				Primary:   "jsimsa",
+				Secondary: "toddw",
+				Date:      "Nov 19, 2014 12:00:00 PM",
+			},
+		},
+	}
+	for _, test := range testCases {
+		got, err := tooldata.Oncall(fake.X, test.targetTime)
+		if err != nil {
+			t.Fatalf("want no errors, got: %v", err)
+		}
+		if !reflect.DeepEqual(test.expectedShift, got) {
+			t.Fatalf("want %#v, got %#v", test.expectedShift, got)
+		}
+	}
+}
diff --git a/tooldata/paths.go b/tooldata/paths.go
new file mode 100644
index 0000000..14fffa3
--- /dev/null
+++ b/tooldata/paths.go
@@ -0,0 +1,49 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tooldata
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"runtime"
+
+	"v.io/jiri"
+	"v.io/jiri/tool"
+	"v.io/x/lib/host"
+)
+
+// ConfigFilePath returns the path to the tools configuration file.
+func ConfigFilePath(jirix *jiri.X) (string, error) {
+	dataDir, err := DataDirPath(jirix, tool.Name)
+	if err != nil {
+		return "", err
+	}
+	return filepath.Join(dataDir, "config.v1.xml"), nil
+}
+
+// OncallRotationPath returns the path to the oncall rotation file.
+func OncallRotationPath(jirix *jiri.X) (string, error) {
+	dataDir, err := DataDirPath(jirix, tool.Name)
+	if err != nil {
+		return "", err
+	}
+	return filepath.Join(dataDir, "oncall.v1.xml"), nil
+}
+
+// ThirdPartyBinPath returns the path to the given third-party tool
+// taking into account the host and the target Go architecture.
+func ThirdPartyBinPath(jirix *jiri.X, name string) (string, error) {
+	bin := filepath.Join(jirix.Root, "third_party", "go", "bin", name)
+	goArch := os.Getenv("GOARCH")
+	machineArch, err := host.Arch()
+	if err != nil {
+		return "", err
+	}
+	if goArch != "" && goArch != machineArch {
+		bin = filepath.Join(jirix.Root, "third_party", "go", "bin", fmt.Sprintf("%s_%s", runtime.GOOS, goArch), name)
+	}
+	return bin, nil
+}