// allow invocation from test func MainArgs(args []string) { //fmt.Println(os.Args) os.Args = args flag.Usage = use if len(os.Args) < 2 { use() } flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) debug := flag.Bool("debug", false, "print lots of debug info as we process.") outdir := flag.String("o", "odir", "specify output directory") pkg := flag.String("p", "main", "specify package for generated code") privs := flag.Bool("X", false, "export private as well as public struct fields") overwrite := flag.Bool("OVERWRITE", false, "replace named .go files with capid tagged versions.") flag.Parse() if debug != nil { bam.Verbose = *debug } if outdir == nil || *outdir == "" { fmt.Fprintf(os.Stderr, "required -o option missing. Use bambam -o <dirname> myfile.go # to specify the output directory.\n") use() } if !bam.DirExists(*outdir) { err := os.MkdirAll(*outdir, 0755) if err != nil { panic(err) } } if pkg == nil || *pkg == "" { fmt.Fprintf(os.Stderr, "required -p option missing. Specify a package name for the generated go code with -p <pkgname>\n") use() } // all the rest are input .go files inputFiles := flag.Args() if len(inputFiles) == 0 { fmt.Fprintf(os.Stderr, "bambam needs at least one .go golang source file to process specified on the command line.\n") os.Exit(1) } for _, fn := range inputFiles { if !strings.HasSuffix(fn, ".go") && !strings.HasSuffix(fn, ".go.txt") { fmt.Fprintf(os.Stderr, "error: bambam input file '%s' did not end in '.go' or '.go.txt'.\n", fn) os.Exit(1) } } x := bam.NewExtractor() x.FieldPrefix = " " x.FieldSuffix = "\n" x.OutDir = *outdir if privs != nil { x.ExtractPrivate = *privs } if overwrite != nil { x.Overwrite = *overwrite } for _, inFile := range inputFiles { _, err := x.ExtractStructsFromOneFile(nil, inFile) if err != nil { panic(err) } } // get rid of default tmp dir x.CompileDir = bam.NewTempDir() x.CompileDir.Cleanup() x.CompileDir.DirPath = *outdir x.PkgName = *pkg schemaFN := x.CompileDir.DirPath + "/schema.capnp" schemaFile, err := os.Create(schemaFN) if err != nil { panic(err) } defer schemaFile.Close() by := x.GenCapnpHeader() schemaFile.Write(by.Bytes()) _, err = x.WriteToSchema(schemaFile) if err != nil { panic(err) } fmt.Fprintf(schemaFile, "\n") fmt.Fprintf(schemaFile, "##compile with:\n\n##\n##\n## capnp compile -ogo %s\n\n", schemaFN) // translator library of go functions is separate from the schema translateFn := x.CompileDir.DirPath + "/translateCapn.go" translatorFile, err := os.Create(translateFn) if err != nil { panic(err) } defer translatorFile.Close() fmt.Fprintf(translatorFile, `package %s import ( capn "github.com/glycerine/go-capnproto" "io" ) `, x.PkgName) _, err = x.WriteToTranslators(translatorFile) if err != nil { panic(err) } err = x.CopySourceFilesAddCapidTag() if err != nil { panic(err) } exec.Command("cp", "-p", "go.capnp", x.CompileDir.DirPath).Run() fmt.Printf("generated files in '%s'\n", x.CompileDir.DirPath) }
func main() { s, err := C.ReadFromStream(os.Stdin, nil) assert(err == nil, "%v\n", err) req := caps.ReadRootCodeGeneratorRequest(s) allfiles := []*node{} for _, ni := range req.Nodes().ToArray() { n := &node{Node: ni, codecs: make(map[uint64]bool)} g_nodes[n.Id()] = n if n.Which() == caps.NODE_FILE { allfiles = append(allfiles, n) } } g_imported = make(map[string]bool) for _, f := range allfiles { for _, a := range f.Annotations().ToArray() { if v := a.Value(); v.Which() == caps.VALUE_TEXT { switch a.Id() { case C.Package: f.pkg = v.Text() case C.Import: f.imp = v.Text() } } else { switch a.Id() { case caps.CodecCapnp: enableCodec(f, caps.CodecCapnp) g_imported["io"] = true g_imported[GO_CAPNP_IMPORT] = true case caps.CodecJson: enableCodec(f, caps.CodecJson) case caps.CodecMsgp: enableCodec(f, caps.CodecMsgp) } } } for _, nn := range f.NestedNodes().ToArray() { if ni := g_nodes[nn.Id()]; ni != nil { ni.resolveName("", nn.Name(), f) } } } for _, reqf := range req.RequestedFiles().ToArray() { x := bam.NewExtractor() x.FieldPrefix = " " x.FieldSuffix = "\n" f := findNode(reqf.Id()) buf := bytes.Buffer{} g_segment = C.NewBuffer([]byte{}) defineConstNodes(&buf, f.nodes) for _, n := range f.nodes { switch n.Which() { case caps.NODE_ANNOTATION: n.defineAnnotation(&buf) case caps.NODE_ENUM: n.defineEnum(&buf, x) case caps.NODE_STRUCT: if !n.Struct().IsGroup() { n.defineStructTypes(&buf, nil, x) // n.defineStructEnums(&buf) } } } // Write translation functions if _, found := f.codecs[caps.CodecCapnp]; found { _, err = x.WriteToTranslators(&buf) assert(err == nil, "%v\n", err) } assert(f.pkg != "", "missing package annotation for %s", reqf.Filename()) x.PkgName = f.pkg if dirPath, _ := filepath.Split(reqf.Filename()); dirPath != "" { err := os.MkdirAll(dirPath, os.ModePerm) assert(err == nil, "%v\n", err) x.OutDir = dirPath } // Create output file filename := strings.TrimSuffix(reqf.Filename(), ".capnp") file, err := os.Create(filename + ".go") assert(err == nil, "%v\n", err) // Write package fmt.Fprintf(file, "package %s\n\n", f.pkg) fmt.Fprintf(file, "// AUTO GENERATED - DO NOT EDIT\n\n") // Write imports f.writeImports(file) // Format sources clean, err := format.Source(buf.Bytes()) assert(err == nil, "%v\n", err) file.Write(clean) defer file.Close() } }