Esempio n. 1
0
// NewBuilder creates a Builder from a list of file names or directories
func NewBuilder(fnames ...string) (*Builder, error) {
	var err error

	b := &Builder{
		fset:  token.NewFileSet(),
		files: make(map[string]*file, len(fnames)),
		funcs: make([]string, 0),
		Usage: `Usage: %[1]s [options] <input> <output>

ex:
 $ %[1]s -l=INFO -evtmax=-1 input.dat output.dat

options:
`,
	}

	for _, fname := range fnames {
		fi, err := os.Stat(fname)
		if err != nil {
			return nil, fwk.Error(err)
		}
		fm := fi.Mode()
		if fm.IsRegular() {
			src, err := ioutil.ReadFile(fname)
			if err != nil {
				return nil, fwk.Error(err)
			}
			f, err := parser.ParseFile(b.fset, fname, src, parser.ParseComments)
			if err != nil {
				return nil, fwk.Error(err)
			}
			b.files[fname] = &file{
				app:  b,
				f:    f,
				fset: b.fset,
				src:  src,
				name: fname,
			}
		}
		if fm.IsDir() {
			return nil, fwk.Errorf("directories not (yet) handled (got=%q)", fname)
		}
	}
	return b, err
}
Esempio n. 2
0
// Build applies some type-checking, collects setup functions and generates the sources of the fwk-based application.
func (b *Builder) Build() error {
	var err error

	if b.Name == "" {
		pwd, err := os.Getwd()
		if err != nil {
			return fwk.Error(err)
		}
		b.Name = filepath.Base(pwd)
	}

	err = b.doTypeCheck()
	if err != nil {
		return err
	}

	// check we build a 'main' package
	if !b.isMain() {
		return fwk.Errorf("not a 'main' package")
	}

	err = b.scanSetupFuncs()
	if err != nil {
		return err
	}

	if len(b.funcs) <= 0 {
		return fwk.Errorf("no setup function found")
	}

	err = b.genSources()
	if err != nil {
		return err
	}

	return err
}
Esempio n. 3
0
func (b *Builder) genSources() error {
	var err error
	tmpdir, err := ioutil.TempDir("", "fwk-builder-")
	if err != nil {
		return fwk.Error(err)
	}
	defer os.RemoveAll(tmpdir)
	// fmt.Fprintf(os.Stderr, "tmpdir=[%s]...\n", tmpdir)

	// copy sources to dst
	for _, f := range b.files {
		// FIXME(sbinet)
		// only take base. watch out for duplicates!
		fname := filepath.Base(f.name)
		dstname := filepath.Join(tmpdir, fname)
		dst, err := os.Create(dstname)
		if err != nil {
			return fwk.Error(err)
		}
		defer dst.Close()

		_, err = dst.Write(f.src)
		if err != nil {
			return fwk.Error(err)
		}

		err = dst.Close()
		if err != nil {
			return fwk.Error(err)
		}
	}

	// add main.
	f, err := os.Create(filepath.Join(tmpdir, "main.go"))
	if err != nil {
		return fwk.Error(err)
	}
	defer f.Close()

	data := struct {
		Usage      string
		Name       string
		SetupFuncs []string
	}{
		Usage:      b.Usage,
		Name:       b.Name,
		SetupFuncs: b.funcs,
	}

	err = render(f, tmpl, data)
	if err != nil {
		return fwk.Error(err)
	}

	build := exec.Command(
		"go", "build", "-o", b.Name, ".",
	)
	build.Stdout = os.Stdout
	build.Stderr = os.Stderr
	build.Dir = tmpdir
	err = build.Run()
	if err != nil {
		return fwk.Error(err)
	}

	// copy final binary.
	{
		src, err := os.Open(filepath.Join(tmpdir, b.Name))
		if err != nil {
			return fwk.Error(err)
		}
		defer src.Close()
		fi, err := src.Stat()
		if err != nil {
			return fwk.Error(err)
		}

		dst, err := os.OpenFile(b.Name, os.O_CREATE|os.O_WRONLY, fi.Mode())
		if err != nil {
			return fwk.Error(err)
		}
		defer dst.Close()

		_, err = io.Copy(dst, src)
		if err != nil {
			return fwk.Error(err)
		}

		err = dst.Close()
		if err != nil {
			return fwk.Error(err)
		}
	}

	return err
}