// 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 }
// 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 }
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 }