in go/tools/builders/embedcfg.go [44:119]
func buildEmbedcfgFile(goSrcs []fileInfo, embedSrcs, embedRootDirs []string, workDir string) (string, error) {
// Check whether this package uses embedding and whether the toolchain
// supports it (Go 1.16+). With Go 1.15 and lower, we'll try to compile
// without an embedcfg file, and the compiler will complain the "embed"
// package is missing.
var major, minor int
if n, err := fmt.Sscanf(runtime.Version(), "go%d.%d", &major, &minor); n != 2 || err != nil {
// Can't parse go version. Maybe it's a development version; fall through.
} else if major < 1 || (major == 1 && minor < 16) {
return "", nil
}
importEmbed := false
haveEmbed := false
for _, src := range goSrcs {
if len(src.embeds) > 0 {
haveEmbed = true
rootDir := findInRootDirs(src.filename, embedRootDirs)
if rootDir == "" || strings.Contains(src.filename[len(rootDir)+1:], string(filepath.Separator)) {
// Report an error if a source files appears in a subdirectory of
// another source directory. In this situation, the same file could be
// referenced with different paths.
return "", fmt.Errorf("%s: source files with //go:embed should be in same directory. Allowed directories are:\n\t%s",
src.filename,
strings.Join(embedRootDirs, "\n\t"))
}
}
for _, imp := range src.imports {
if imp.path == "embed" {
importEmbed = true
}
}
}
if !importEmbed || !haveEmbed {
return "", nil
}
// Build a tree of embeddable files. This includes paths listed with
// -embedsrc. If one of those paths is a directory, the tree includes
// its files and subdirectories. Paths in the tree are relative to the
// path in embedRootDirs that contains them.
root, err := buildEmbedTree(embedSrcs, embedRootDirs)
if err != nil {
return "", err
}
// Resolve patterns to sets of files.
var embedcfg struct {
Patterns map[string][]string
Files map[string]string
}
embedcfg.Patterns = make(map[string][]string)
embedcfg.Files = make(map[string]string)
for _, src := range goSrcs {
for _, embed := range src.embeds {
matchedPaths, matchedFiles, err := resolveEmbed(embed, root)
if err != nil {
return "", err
}
embedcfg.Patterns[embed.pattern] = matchedPaths
for i, rel := range matchedPaths {
embedcfg.Files[rel] = matchedFiles[i]
}
}
}
// Write the configuration to a JSON file.
embedcfgData, err := json.MarshalIndent(&embedcfg, "", "\t")
if err != nil {
return "", err
}
embedcfgName := filepath.Join(workDir, "embedcfg")
if err := ioutil.WriteFile(embedcfgName, embedcfgData, 0666); err != nil {
return "", err
}
return embedcfgName, nil
}