func buildEmbedcfgFile()

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
}