func (cl *CLib) Build(c *build.Context) error { params := []string{"-c"} params = append(params, cl.CompilerOptions...) params = append(params, cl.LinkerOptions...) params = append(params, cl.Sources...) params = append(params, cl.Includes.Includes()...) if err := c.Exec(Compiler(), CCENV, params); err != nil { c.Println(err.Error()) return fmt.Errorf(cl.buf.String()) } libName := fmt.Sprintf("%s.a", cl.Name) params = []string{"-rs", libName} params = append(params, cl.LinkerOptions...) // This is done under the assumption that each src file put in this thing // here will comeout as a .o file for _, f := range cl.Sources { _, filename := filepath.Split(f) params = append(params, fmt.Sprintf("%s.o", filename[:strings.LastIndex(filename, ".")])) } if err := c.Exec(Archiver(), CCENV, params); err != nil { c.Println(err.Error()) return fmt.Errorf(cl.buf.String()) } return nil }
func (g *GenRule) Build(c *build.Context) error { for _, cmd := range g.Commands { strs := strings.Split(cmd, " ") if err := c.Exec(strs[0], nil, strs[1:]); err != nil { c.Println(err.Error()) return err } } return nil }
func (y *Yacc) Build(c *build.Context) error { params := []string{} params = append(params, y.YaccOptions...) params = append(params, y.Sources...) c.Println(strings.Join(append([]string{"yacc"}, params...), " ")) if err := c.Exec("yacc", nil, params); err != nil { c.Println(err.Error()) return fmt.Errorf(y.buf.String()) } return nil }
func (mp *ManPage) Build(c *build.Context) error { for _, m := range mp.Sources { params := []string{"<"} params = append(params, m) params = append(params, ">") params = append(params, fmt.Sprintf("%s.html", m)) c.Println(strings.Join(append([]string{"man2html"}, params...), " ")) if err := c.Exec("man2html", nil, params); err != nil { return err } } return nil }
func (npm *NpmPackage) Build(c *build.Context) error { if npm.Version == "" { return fmt.Errorf("NPM package %s failed to install, no version string") } params := []string{} params = append(params, "install") params = append(params, fmt.Sprintf("%s@%s", npm.Name, npm.Version)) c.Println(strings.Join(append([]string{"npm"}, params...), " ")) if err := c.Exec("npm", nil, params); err != nil { c.Println(err.Error()) return fmt.Errorf(err.Error()) } return nil }
func (cb *CBin) Build(c *build.Context) error { c.Println(prettyprint.AsJSON(cb)) params := []string{} params = append(params, cb.CompilerOptions...) params = append(params, cb.Sources...) params = append(params, cb.Includes.Includes()...) if err := c.Exec(Compiler(), CCENV, params); err != nil { return fmt.Errorf(err.Error()) } ldparams := []string{"-o", cb.Name} ldparams = append(ldparams, cb.LinkerOptions...) if cb.LinkerFile != "" { ldparams = append(ldparams, cb.LinkerFile) } // This is done under the assumption that each src file put in this thing // here will comeout as a .o file for _, f := range cb.Sources { _, fname := filepath.Split(f) ldparams = append(ldparams, fmt.Sprintf("%s.o", fname[:strings.LastIndex(fname, ".")])) } ldparams = append(ldparams, "-L", "lib") for _, dep := range cb.Dependencies { d := split(dep, ":") if len(d) < 3 { continue } if d[:3] == "lib" { ldparams = append(ldparams, fmt.Sprintf("-l%s", d[3:])) } } if err := c.Exec(Linker(), CCENV, ldparams); err != nil { return fmt.Errorf(err.Error()) } return nil }
func (mkSys *MkSys) Build(c *build.Context) error { c.Println(prettyprint.AsJSON(mkSys)) sysconf, err := mkSys.readSysconf() if err != nil { return err } syscalls := sysconf.Syscalls syserrors := sysconf.Syserrors bootmethods := sysconf.Bootmethods for i := range syscalls { if syscalls[i].Define == "" { syscalls[i].Define = strings.ToUpper(syscalls[i].Name) } if syscalls[i].Sysname == "" { syscalls[i].Sysname = "sys" + syscalls[i].Name } if syscalls[i].Libname == "" { syscalls[i].Libname = syscalls[i].Name } } outfile, err := c.Create(mkSys.Mode) if err != nil { return err } switch mkSys.Mode { case "sys_harvey.s": if mkSys.ARCH != "amd64" { c.Println("ARCH unsupported or not set") } syscallargs := []string{"DI", "SI", "DX", "R10", "R8", "R9"} //funcallregs := []string{ "DI", "SI", "DX", "CX", "R8", "R9" }; for i := range syscalls { goargs := []string{} fpoff := 0 for k := range syscalls[i].Args { switch syscalls[i].Args[k] { case "int32_t", "uint32_t": goargs = append(goargs, fmt.Sprintf("MOVL arg%d+%d(FP), %s", k, fpoff, syscallargs[k])) fpoff += 4 case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t": fpoff = (fpoff + 7) & ^7 goargs = append(goargs, fmt.Sprintf("MOVQ arg%d+%d(FP), %s", k, fpoff, syscallargs[k])) fpoff += 8 default: return fmt.Errorf("unsupported arg %s in syscall: %v", syscalls[i].Args[k], syscalls[i]) } } syscalls[i].GoArgs = goargs switch syscalls[i].Ret[0] { case "int32_t", "uint32_t": syscalls[i].Ret0 = fmt.Sprintf("MOVL AX, ret+%d(FP)", fpoff) fpoff += 4 case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t": fpoff = (fpoff + 7) & ^7 syscalls[i].Ret0 = fmt.Sprintf("MOVQ AX, ret+%d(FP)", fpoff) fpoff += 8 default: return fmt.Errorf("unsupported Ret[0] in syscall: %v", syscalls[i]) } } tmpl, err := template.New("sys_harvey.s").Parse(`/* automatically generated by mksys */ /* System calls for AMD64, Harvey */ #include "go_asm.h" #include "go_tls.h" #include "textflag.h" {{ range . }} TEXT runtime·{{ .Libname }}(SB),NOSPLIT,$0 {{ range .GoArgs }} {{ . }} {{ end }} MOVQ ${{ .Id }}, AX SYSCALL {{ .Ret0 }} RET {{ end }} `) if err != nil { return err } err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "syscallfiles": if mkSys.ARCH != "amd64" { return fmt.Errorf("ARCH unsupported or not set") } tmpl, err := template.New("syscall.s").Parse(`/* automatically generated by mksys */ .globl {{ .Libname }} {{ .Libname }}: movq %rcx, %r10 /* rcx gets smashed by systenter. Use r10.*/ movq ${{ .Id }},%rax /* Put the system call into rax, just like linux. */ syscall ret `) if err != nil { return err } for i := range syscalls { file, err := c.Create(syscalls[i].Libname + ".s") if err != nil { return err } err = tmpl.Execute(file, syscalls[i]) if err != nil { return err } err = file.Close() if err != nil { return err } } case "sysnum.go": tmpl, err := template.New("sysnum.go").Parse(`// automatically generated by mksys package syscall const( {{ range . }} SYS_{{ .Define }} = {{ .Id }} {{ end }} ) `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "sys.h": tmpl, err := template.New("sys.h").Parse(`/* automatically generated by mksys */ {{ range . }}#define {{ .Define }} {{ .Id }} {{ end }} `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "sysdecl.h": tmpl, err := template.New("sysdecl.h").Parse(`/* automatically generated by mksys */ {{ range . }}extern {{ .Ret0 }} {{ .Libname }}({{ range $i, $e := .Args }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}); {{ end }} `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "systab.c": for i := range syscalls { var fudge string switch syscalls[i].Ret[0] { case "int32_t": fudge = "{ .i = -1 }" case "int64_t": fudge = "{ .vl = -1ll }" case "void*", "char*": fudge = "{ .v = (void*)-1ll }" default: return fmt.Errorf("unsupported Ret[0] in syscall: %v", syscalls[i]) } if syscalls[i].Fudge == "" { syscalls[i].Fudge = fudge } syscalls[i].Ret0 = syscalls[i].Ret[0] } tmpl, err := template.New("systab.c").Parse(`/* automatically generated by mksys */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include <sys.h> {{ range . }}extern void {{ .Sysname }}(Ar0*, ...); {{ end }} Systab systab[] = { {{ range . }}[{{ .Define }}] { "{{ .Name }}", {{ .Sysname }}, {{ .Fudge }} }, {{ end }} }; int nsyscall = nelem(systab); `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "error.h": tmpl, err := template.New("error.h").Parse(`/* automatically generated by mksys */ {{ range . }}extern char {{ .Name }}[]; /* {{ .String }} */ {{ end }} `) err = tmpl.Execute(outfile, syserrors) if err != nil { return err } case "errstr.h": tmpl, err := template.New("errstr.h").Parse(`/* automatically generated by mksys */ {{ range . }}char {{ .Name }}[] = "{{ .String }}"; {{ end }} `) err = tmpl.Execute(outfile, syserrors) if err != nil { return err } case "bootamd64cpu.c": tmpl, err := template.New("bootamd64cpu.c").Parse(`/* automatically generated by mksys */ #include <u.h> #include <libc.h> #include <boot.h> Method method[] = { {{ range . }}{ "{{.Name}}", {{.Config}}, {{.Connect}}, "{{.Arg}}", }, {{ end }} { nil }, }; int cpuflag = 1; char* rootdir = "/root"; char* bootdisk = "#S/sdE0/"; extern void boot(int, char**); void main(int argc, char **argv) { boot(argc, argv); } int (*cfs)(int) = 0; `) err = tmpl.Execute(outfile, bootmethods) if err != nil { log.Fatal(err) } } return nil }
func (etc *ElfToC) Build(c *build.Context) error { fileName := "" if xf, err := c.Open(etc.Elf); err != nil { return fmt.Errorf("open :%s", err.Error()) } else { fileName = xf.Name() xf.Close() } f, err := elf.Open(fileName) if err != nil { return err } var dataend, codeend, end uint64 var datastart, codestart, start uint64 datastart, codestart, start = math.MaxUint64, math.MaxUint64, math.MaxUint64 mem := []byte{} for _, v := range f.Progs { if v.Type != elf.PT_LOAD { continue } c.Printf("processing %v\n", v) // MUST alignt to 2M page boundary. // then MUST allocate a []byte that // is the right size. And MUST // see if by some off chance it // joins to a pre-existing segment. // It's easier than it seems. We produce ONE text // array and ONE data array. So it's a matter of creating // a virtual memory space with an assumed starting point of // 0x200000, and filling it. We just grow that as needed. curstart := v.Vaddr & ^uint64(0xfff) // 0x1fffff) curend := v.Vaddr + v.Memsz c.Printf("s %x e %x\n", curstart, curend) if curend > end { nmem := make([]byte, curend) copy(nmem, mem) mem = nmem } if curstart < start { start = curstart } if v.Flags&elf.PF_X == elf.PF_X { if curstart < codestart { codestart = curstart } if curend > codeend { codeend = curend } c.Printf("code s %v e %v\n", codestart, codeend) } else { if curstart < datastart { datastart = curstart } if curend > dataend { dataend = curend } c.Printf("data s %v e %v\n", datastart, dataend) } for i := uint64(0); i < v.Filesz; i++ { if amt, err := v.ReadAt(mem[v.Vaddr+i:], int64(i)); err != nil && err != io.EOF { err := fmt.Errorf("%v: %v\n", amt, err) c.Println(err) return err } else if amt == 0 { if i < v.Filesz { err := fmt.Errorf("%v: Short read: %v of %v\n", v, i, v.Filesz) c.Println(err) return err } break } else { i = i + uint64(amt) c.Printf("i now %d\n", i) } } c.Printf("Processed %v\n", v) } c.Printf("gencode\n") // Gen code to stdout. For each file, create an array, a start, and an end variable. outfile, err := c.Create(fmt.Sprintf("%s.h", etc.Name)) if err != nil { return err } _, file := path.Split(etc.Elf) gencode(outfile, file, "code", mem, codestart, codeend) gencode(outfile, file, "data", mem, datastart, dataend) return nil }