blob: 95bc7f18510082e853df2e8c6025e9d2653230d3 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Command make_builtin_vdlroot runs at jiri go generate time. It emits a Go
// source file called builtin_vdlroot.go containing a gzip'd version of all the
// core VDL types required by the VDL tool. This allows the VDL tool to run
// 'standalone' (i.e. without access to the Vanadium source code).
//
// +build ignored
package main
import (
"archive/tar"
"compress/gzip"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
)
const (
outputPreamble = `// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file is automatically generated, your changes will be lost.
// See make_builtin_vdlroot.go.
package main
//go:generate jiri go run make_builtin_vdlroot.go
const (
// builtinVdlrootData contains a base64-encoded gzip'd tar file. This file
// contains all of the VDL files required to run the VDL tool.
builtinVdlrootData = ` + "`"
outputFooter = "`" + `
)
`
)
// writeBytes writes the given bytes to the given writer, returning an error if
// the underlying Write fails or if the number of bytes written is not equal to
// len(content).
func writeBytes(out io.Writer, content []byte) error {
n, err := out.Write(content)
if err == nil && n != len(content) {
err = fmt.Errorf("wrote an unexpected number of bytes, wanted %d, wrote %d", len(content), n)
}
return err
}
// writeString writes the given string to the given writer, returning an error
// if the underlying Write fails or if the number of bytes written is not equal
// to len(content).
func writeString(out io.Writer, content string) error {
return writeBytes(out, []byte(content))
}
type wrapWriter struct {
writer io.Writer
totalWritten int
}
// Writes b to the underlying writer but inserts a \n every 78 characters. The
// returned bytes-written count includes the \n characters.
func (w *wrapWriter) Write(b []byte) (int, error) {
const max = 78
n := 0
for len(b) > 0 {
newline := true
chunk := max - w.totalWritten%max
if len(b) < chunk {
chunk = len(b)
newline = false
}
if err := writeBytes(w.writer, b[:chunk]); err != nil {
return n, err
}
n += chunk
w.totalWritten += chunk
b = b[chunk:]
if newline {
if err := writeString(w.writer, "\n"); err != nil {
return n, err
}
n++
}
}
return n, nil
}
// writeVdlrootData creates a gzip'd tar file containing all of the VDL files
// in vdlroot. The data is encoded as base64. Does not close out.
func writeVdlrootData(out io.Writer) error {
jiriRoot := os.Getenv("JIRI_ROOT")
if jiriRoot == "" {
return fmt.Errorf("JIRI_ROOT is not set")
}
srcDir := filepath.Join(jiriRoot, "release", "go", "src")
vdlroot := filepath.Join(srcDir, "v.io", "v23", "vdlroot")
wrapWriter := &wrapWriter{
writer: out,
totalWritten: 0,
}
base64writer := base64.NewEncoder(base64.StdEncoding, wrapWriter)
gzipWriter := gzip.NewWriter(base64writer)
tarWriter := tar.NewWriter(gzipWriter)
walkFn := func(path string, info os.FileInfo, err error) error {
if strings.HasSuffix(path, ".vdl") {
content, err := ioutil.ReadFile(path)
if err != nil {
return err
}
relPath, err := filepath.Rel(srcDir, path)
if err != nil {
return err
}
header := tar.Header{
Mode: int64(0644),
Name: relPath,
Size: int64(len(content)),
}
if err := tarWriter.WriteHeader(&header); err != nil {
return err
}
return writeBytes(tarWriter, content)
}
return nil
}
if err := filepath.Walk(vdlroot, walkFn); err != nil {
log.Printf("Walk() failed: %v", err)
}
if err := tarWriter.Close(); err != nil {
log.Printf("Close() of tar file failed: %v", err)
return err
}
if err := gzipWriter.Close(); err != nil {
log.Printf("Close() of gzip file failed: %v", err)
return err
}
if err := base64writer.Close(); err != nil {
log.Printf("Close() of base64 file failed: %v", err)
return err
}
return nil
}
func main() {
filename := "builtin_vdlroot.go"
f, err := os.Create(filename)
if err != nil {
log.Printf("Create(%q) failed: %v", filename, err)
os.Exit(1)
}
defer f.Close()
if err := writeString(f, outputPreamble); err != nil {
os.Exit(1)
}
if err := writeVdlrootData(f); err != nil {
os.Exit(1)
}
if err := writeString(f, outputFooter); err != nil {
os.Exit(1)
}
}