github.com/goplus/igop@v0.25.0/pkg/gen.go (about)

     1  //go:build ignore
     2  // +build ignore
     3  
     4  /*
     5   * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
     6   *
     7   * Licensed under the Apache License, Version 2.0 (the "License");
     8   * you may not use this file except in compliance with the License.
     9   * You may obtain a copy of the License at
    10   *
    11   *     http://www.apache.org/licenses/LICENSE-2.0
    12   *
    13   * Unless required by applicable law or agreed to in writing, software
    14   * distributed under the License is distributed on an "AS IS" BASIS,
    15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16   * See the License for the specific language governing permissions and
    17   * limitations under the License.
    18   */
    19  
    20  package main
    21  
    22  import (
    23  	"fmt"
    24  	"go/format"
    25  	"io/ioutil"
    26  	"log"
    27  	"os"
    28  	"os/exec"
    29  	"runtime"
    30  	"strings"
    31  )
    32  
    33  func main() {
    34  	ver := runtime.Version()[:6]
    35  	var tags string
    36  	var name string
    37  	var fname string
    38  	switch ver {
    39  	case "go1.21":
    40  		tags = "//+build go1.21"
    41  		name = "go121_export"
    42  		fname = "go121_pkgs.go"
    43  	case "go1.20":
    44  		tags = "//+build go1.20,!go1.21"
    45  		name = "go120_export"
    46  		fname = "go120_pkgs.go"
    47  	case "go1.19":
    48  		tags = "//+build go1.19,!go1.20"
    49  		name = "go119_export"
    50  		fname = "go119_pkgs.go"
    51  	case "go1.18":
    52  		tags = "//+build go1.18,!go1.19"
    53  		name = "go118_export"
    54  		fname = "go118_pkgs.go"
    55  	case "go1.17":
    56  		tags = "//+build go1.17,!go1.18"
    57  		name = "go117_export"
    58  		fname = "go117_pkgs.go"
    59  	case "go1.16":
    60  		tags = "//+build go1.16,!go1.17"
    61  		name = "go116_export"
    62  		fname = "go116_pkgs.go"
    63  	case "go1.15":
    64  		tags = "//+build go1.15,!go1.16"
    65  		name = "go115_export"
    66  		fname = "go115_pkgs.go"
    67  	case "go1.14":
    68  		tags = "//+build go1.14,!go1.15"
    69  		name = "go114_export"
    70  		fname = "go114_pkgs.go"
    71  	}
    72  
    73  	pkgs := stdList()
    74  
    75  	log.Println(ver, name, tags)
    76  	log.Println(pkgs)
    77  
    78  	cmd := exec.Command("qexp", "-outdir", ".", "-addtags", tags, "-filename", name)
    79  	cmd.Args = append(cmd.Args, pkgs...)
    80  	cmd.Stderr = os.Stderr
    81  	cmd.Stdout = os.Stdout
    82  	err := cmd.Run()
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  
    87  	gpkgs := genericPkgs(pkgs)
    88  	// sync/atomic
    89  	cmd = exec.Command("qexp", "-outdir", ".", "-addtags", tags, "-filename", name, "-src")
    90  	cmd.Args = append(cmd.Args, gpkgs...)
    91  	cmd.Stderr = os.Stderr
    92  	cmd.Stdout = os.Stdout
    93  	err = cmd.Run()
    94  	if err != nil {
    95  		panic(err)
    96  	}
    97  
    98  	list := osarchList()
    99  	log.Println(list)
   100  	for _, osarch := range list {
   101  		ar := strings.Split(osarch, "_")
   102  		if len(ar) != 2 {
   103  			continue
   104  		}
   105  		cmd := exec.Command("qexp", "-outdir", ".", "-addtags", tags, "-filename", name, "-contexts", osarch, "syscall")
   106  		cmd.Stderr = os.Stderr
   107  		cmd.Stdout = os.Stdout
   108  		cmd.Env = os.Environ()
   109  		cmd.Env = append(cmd.Env, "GOOS="+ar[0])
   110  		cmd.Env = append(cmd.Env, "GOARCH="+ar[1])
   111  		cmd.Env = append(cmd.Env, "GOEXPERIMENT=noregabi")
   112  		err := cmd.Run()
   113  		if err != nil {
   114  			panic(err)
   115  		}
   116  		err = makepkg("./"+fname, []string{tags}, pkgs)
   117  		if err != nil {
   118  			panic(err)
   119  		}
   120  	}
   121  }
   122  
   123  var genericList = []string{
   124  	"sync/atomic",
   125  	"maps",
   126  	"slices",
   127  	"cmp",
   128  }
   129  
   130  func genericPkgs(std []string) (pkgs []string) {
   131  	for _, pkg := range std {
   132  		for _, v := range genericList {
   133  			if pkg == v {
   134  				pkgs = append(pkgs, v)
   135  			}
   136  		}
   137  	}
   138  	return
   139  }
   140  
   141  func makepkg(fname string, tags []string, std []string) error {
   142  	//_ github.com/goplus/igop/pkg
   143  	var pkgs []string
   144  	for _, v := range std {
   145  		if strings.HasPrefix(v, "testing/") {
   146  			continue
   147  		}
   148  		if v == "log/syslog" || v == "net/rpc" || v == "net/rpc/jsonrpc" {
   149  			continue
   150  		}
   151  		pkgs = append(pkgs, fmt.Sprintf(`_ "github.com/goplus/igop/pkg/%v"`, v))
   152  	}
   153  	pkgs = append(pkgs, fmt.Sprintf(`_ "github.com/goplus/igop/pkg/syscall"`))
   154  	r := strings.NewReplacer("$TAGS", strings.Join(tags, "\n"), "$PKGS", strings.Join(pkgs, "\t\n"))
   155  	src := r.Replace(tmpl)
   156  	data, err := format.Source([]byte(src))
   157  	if err != nil {
   158  		return err
   159  	}
   160  	return ioutil.WriteFile(fname, []byte(data), 0644)
   161  }
   162  
   163  var tmpl = `$TAGS
   164  
   165  package pkg
   166  
   167  import (
   168  	$PKGS
   169  )
   170  `
   171  
   172  // skip syscall
   173  func stdList() []string {
   174  	cmd := exec.Command("go", "list", "std")
   175  	data, err := cmd.Output()
   176  	if err != nil {
   177  		panic(err)
   178  	}
   179  	var ar []string
   180  	for _, v := range strings.Split(string(data), "\n") {
   181  		if v == "" {
   182  			continue
   183  		}
   184  		if isSkipPkg(v) {
   185  			continue
   186  		}
   187  		ar = append(ar, v)
   188  	}
   189  	return ar
   190  }
   191  
   192  func isSkipPkg(pkg string) bool {
   193  	switch pkg {
   194  	case "syscall", "unsafe":
   195  		return true
   196  	case "runtime/cgo", "runtime/race":
   197  		return true
   198  	default:
   199  		if strings.HasPrefix(pkg, "vendor/") {
   200  			return true
   201  		}
   202  		for _, v := range strings.Split(pkg, "/") {
   203  			if v == "internal" {
   204  				return true
   205  			}
   206  		}
   207  	}
   208  	return false
   209  }
   210  
   211  // aix_ppc64 android_386 android_amd64
   212  func checkRegAbi(list []string, ver string) (regabi []string, noregabi []string) {
   213  	for _, v := range list {
   214  		ar := strings.Split(v, "_")
   215  		if len(ar) != 2 {
   216  			continue
   217  		}
   218  		switch ver {
   219  		case "go1.17":
   220  			if ar[1] == "amd64" {
   221  				regabi = append(regabi, v)
   222  				continue
   223  			}
   224  		case "go1.18":
   225  			switch ar[1] {
   226  			case "amd64", "arm64", "ppc64", "ppc64le":
   227  				regabi = append(regabi, v)
   228  				continue
   229  			}
   230  		case "go1.19":
   231  			switch ar[1] {
   232  			case "amd64", "arm64", "ppc64", "ppc64le", "riscv64":
   233  				regabi = append(regabi, v)
   234  				continue
   235  			}
   236  		}
   237  		noregabi = append(noregabi, v)
   238  	}
   239  	return
   240  }
   241  
   242  func osarchList() []string {
   243  	//go tool dist list
   244  	cmd := exec.Command("go", "tool", "dist", "list")
   245  	data, err := cmd.Output()
   246  	if err != nil {
   247  		panic(err)
   248  	}
   249  	var ar []string
   250  	for _, v := range strings.Split(string(data), "\n") {
   251  		if v == "" {
   252  			continue
   253  		}
   254  		ar = append(ar, strings.Replace(v, "/", "_", 1))
   255  	}
   256  	return ar
   257  }