1//go:generate go build
2
3/*
4extract generates wrappers of stdlib package exported symbols. This command
5is reserved for internal use in yaegi project.
6
7For a similar purpose with third party packages, see the yaegi extract subcommand,
8based on the same code.
9
10Output files are written in the current directory, and prefixed with the go version.
11
12Usage:
13
14    extract package...
15
16The same program is used for all target operating systems and architectures.
17The GOOS and GOARCH environment variables set the desired target.
18*/
19package main
20
21import (
22	"bytes"
23	"flag"
24	"io"
25	"log"
26	"os"
27	"path"
28	"runtime"
29	"strings"
30
31	"github.com/traefik/yaegi/extract"
32)
33
34var (
35	exclude = flag.String("exclude", "", "comma separated list of regexp matching symbols to exclude")
36	include = flag.String("include", "", "comma separated list of regexp matching symbols to include")
37)
38
39func main() {
40	flag.Parse()
41
42	if flag.NArg() == 0 {
43		flag.Usage()
44		log.Fatalf("missing package path")
45	}
46
47	wd, err := os.Getwd()
48	if err != nil {
49		log.Fatal(err)
50	}
51
52	ext := extract.Extractor{
53		Dest: path.Base(wd),
54	}
55
56	goos, goarch := os.Getenv("GOOS"), os.Getenv("GOARCH")
57
58	if *exclude != "" {
59		ext.Exclude = strings.Split(*exclude, ",")
60	}
61
62	if *include != "" {
63		ext.Include = strings.Split(*include, ",")
64	}
65
66	for _, pkgIdent := range flag.Args() {
67		var buf bytes.Buffer
68
69		if pkgIdent == "syscall" && goos == "solaris" {
70			// Syscall6 is broken on solaris (https://github.com/golang/go/issues/24357),
71			// it breaks build, skip related symbols.
72			ext.Exclude = append(ext.Exclude, "Syscall6")
73		}
74
75		importPath, err := ext.Extract(pkgIdent, "", &buf)
76		if err != nil {
77			log.Fatal(err)
78		}
79
80		var oFile string
81		if pkgIdent == "syscall" {
82			oFile = strings.ReplaceAll(importPath, "/", "_") + "_" + goos + "_" + goarch + ".go"
83		} else {
84			oFile = strings.ReplaceAll(importPath, "/", "_") + ".go"
85		}
86
87		version := runtime.Version()
88		if strings.HasPrefix(version, "devel") {
89			log.Fatalf("extracting only supported with stable releases of Go, not %v", version)
90		}
91		parts := strings.Split(version, ".")
92		prefix := parts[0] + "_" + extract.GetMinor(parts[1])
93
94		f, err := os.Create(prefix + "_" + oFile)
95		if err != nil {
96			log.Fatal(err)
97		}
98
99		if _, err := io.Copy(f, &buf); err != nil {
100			_ = f.Close()
101			log.Fatal(err)
102		}
103
104		if err := f.Close(); err != nil {
105			log.Fatal(err)
106		}
107	}
108}
109