github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/_dev/gen_import_report.go (about)

     1  // TamaGo import report
     2  // Based on https://github.com/trashhalo/tinygo-import-report.git
     3  
     4  package main
     5  
     6  import (
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"sort"
    12  	"strings"
    13  	"sync"
    14  	"text/template"
    15  )
    16  
    17  const mainTemplate = `
    18  package main
    19  
    20  import (
    21  	_ "unsafe"
    22  	_ "{{.}}"
    23  )
    24  
    25  //go:linkname getRandomData runtime.getRandomData
    26  func getRandomData(b []byte) {
    27  }
    28  
    29  //go:linkname printk runtime.printk
    30  func printk(byte) {
    31  	return
    32  }
    33  
    34  //go:linkname hwinit runtime.hwinit
    35  func hwinit() {
    36  	return
    37  }
    38  
    39  //go:linkname initRNG runtime.initRNG
    40  func initRNG() {
    41  	return
    42  }
    43  
    44  //go:linkname nanotime1 runtime.nanotime1
    45  func nanotime1() (ns int64) {
    46  	return
    47  }
    48  
    49  //go:linkname stackOffset runtime.stackOffset
    50  var stackOffset uint32
    51  
    52  func main() {
    53  }
    54  `
    55  
    56  const readmeTemplate = `
    57  # Tamago Import Report
    58  This project imports each package in the stdlib and reports if it imports cleanly in tamago.
    59  A package with a check may work a package with a x will definately not currently work.
    60  
    61  | Package | Imported? | 
    62  | --- | --- |{{ range $key, $value := .}}
    63  | {{$value.Name}} | {{if $value.Imported}} ok {{else}} [failed](#{{$value.Link}}) {{end}} | {{ end }}
    64  
    65  
    66  {{ range $key, $value := .}}
    67  ## {{$value.Name}}
    68  
    69  BTBTBT
    70  {{$value.Output}}
    71  BTBTBT
    72  
    73  {{ end }}
    74  `
    75  
    76  type Result struct {
    77  	Name     string
    78  	Imported bool
    79  	Output   string
    80  	Link     string
    81  }
    82  
    83  func main() {
    84  	tamagoGo := os.Getenv("TAMAGO")
    85  
    86  	if tamagoGo == "" {
    87  		panic("You need to set the TAMAGO variable to a compiled version of https://github.com/f-secure-foundry/tamago-go")
    88  	}
    89  
    90  	content, err := ioutil.ReadFile("imports")
    91  
    92  	if err != nil {
    93  		panic(err)
    94  	}
    95  
    96  	lines := strings.Split(string(content), "\n")
    97  	maint := template.Must(template.New("main").Parse(mainTemplate))
    98  	readmet := template.Must(template.New("readme").Parse(strings.Replace(readmeTemplate, "BTBTBT", "```", -1)))
    99  	results := make(chan Result)
   100  
   101  	wg := &sync.WaitGroup{}
   102  	resultsArr := []Result{}
   103  
   104  	sem := make(chan struct{}, 4)
   105  
   106  	go func() {
   107  		for r := range results {
   108  			resultsArr = append(resultsArr, r)
   109  			println(r.Name)
   110  
   111  			wg.Done()
   112  		}
   113  	}()
   114  
   115  	for _, line := range lines {
   116  		wg.Add(1)
   117  
   118  		go func(line string) {
   119  			sem <- struct{}{}
   120  			defer func() {
   121  				<-sem
   122  			}()
   123  
   124  			noslash := strings.Replace(line, "/", "_", -1)
   125  			dirsafe := fmt.Sprintf("tests/%v", noslash)
   126  			os.Mkdir(dirsafe, 0755)
   127  			f, err := os.Create(fmt.Sprintf("%v/main.go", dirsafe))
   128  
   129  			if err != nil {
   130  				panic(err)
   131  			}
   132  			defer f.Close()
   133  
   134  			err = maint.Execute(f, line)
   135  
   136  			if err != nil {
   137  				panic(err)
   138  			}
   139  
   140  			cmd := exec.Command(tamagoGo, "build", fmt.Sprintf("tests/%v/main.go", noslash))
   141  			stdoutStderr, err := cmd.CombinedOutput()
   142  
   143  			results <- Result{
   144  				line,
   145  				err == nil,
   146  				string(stdoutStderr),
   147  				strings.Replace(line, "/", "", -1),
   148  			}
   149  		}(line)
   150  	}
   151  
   152  	wg.Wait()
   153  	close(results)
   154  
   155  	sort.Slice(resultsArr, func(i, j int) bool {
   156  		return resultsArr[i].Name < resultsArr[j].Name
   157  	})
   158  
   159  	f, err := os.Create("import_report.md")
   160  
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  	defer f.Close()
   165  
   166  	err = readmet.Execute(f, resultsArr)
   167  
   168  	if err != nil {
   169  		panic(err)
   170  	}
   171  }