func getPackage(pkgpath string) (*build.Package, error) { var err error var pkg *build.Package pkg, err = build.Import(pkgpath, "", 0) if err != nil { return nil, err } else { for i, filename := range pkg.GoFiles { pkg.GoFiles[i] = path.Join(pkg.Dir, filename) } for i, filename := range pkg.CFiles { pkg.CFiles[i] = path.Join(pkg.Dir, filename) } // Look for .ll files, treat them the same as .s. // TODO look for build tags in the .ll file, check filename // for GOOS/GOARCH, etc. var llfiles []string llfiles, err = filepath.Glob(pkg.Dir + "/*.ll") for _, file := range llfiles { pkg.SFiles = append(pkg.SFiles, file) } } return pkg, nil }
func buildPackage(pkg *build.Package, output string) error { args := []string{"-c", "-triple", triple} dir, file := path.Split(pkg.ImportPath) if pkg.IsCommand() || test { if output == "" { output = file } } else { dir = filepath.Join(pkgroot, dir) err := os.MkdirAll(dir, os.FileMode(0755)) if err != nil { return err } if output == "" { output = path.Join(dir, file+".bc") } } if !pkg.IsCommand() || test { args = append(args, "-importpath", pkg.ImportPath) } var cgoCFLAGS, cgoCPPFLAGS, cgoLDFLAGS []string if len(pkg.CFiles) > 0 || len(pkg.CgoFiles) > 0 { // TODO(axw) process pkg-config cgoCFLAGS = append(envFields("CGO_CFLAGS"), pkg.CgoCFLAGS...) cgoCPPFLAGS = append(envFields("CGO_CPPFLAGS"), pkg.CgoCPPFLAGS...) //cgoCXXFLAGS = append(envFields("CGO_CXXFLAGS"), pkg.CgoCXXFLAGS...) cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", workdir, "-I", pkg.Dir) cgoLDFLAGS = append(envFields("CGO_LDFLAGS"), pkg.CgoLDFLAGS...) // Get the library dir in which to find libgcc, libstdc++, etc. // We need to do this because we rely on clang to link; in Ubuntu 14.04 // beta 1, there is no g++-4.9, but there is gccgo-4.9. Clang sees the // partial 4.9 lib directory and uses it instead of 4.8, which is what // should be used. if gcclib, err := findGcclib(); err != nil { return fmt.Errorf("failed to locate gcc lib dir: %v", err) } else if gcclib != "." { cgoLDFLAGS = append(cgoLDFLAGS, "-L", gcclib) } } var gofiles, cfiles []string if len(pkg.CgoFiles) > 0 { var err error gofiles, cfiles, err = runCgo(pkg.ImportPath, pkg.CgoFiles, cgoCPPFLAGS, cgoCFLAGS) if err != nil { return err } } gofiles = append(gofiles, pkg.GoFiles...) cfiles = append(cfiles, pkg.CFiles...) _, file = path.Split(output) tempfile := path.Join(workdir, file+".bc") args = append(args, fmt.Sprintf("-g=%v", generateDebug)) args = append(args, "-o", tempfile) args = append(args, gofiles...) if test { args = append(args, pkg.TestGoFiles...) } cmd := exec.Command(llgobin, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := runCmd(cmd); err != nil { return err } // Remove the .S files and add them to cfiles. for i := 0; i < len(pkg.SFiles); i++ { sfile := pkg.SFiles[i] if strings.HasSuffix(sfile, ".S") { cfiles = append(cfiles, sfile) pkg.SFiles = append(pkg.SFiles[:i], pkg.SFiles[i+1:]...) i-- } } // Compile and link .c files in. llvmlink := filepath.Join(llvmbindir, "llvm-link") for _, cfile := range cfiles { bcfile := filepath.Join(workdir, filepath.Base(cfile+".bc")) args = []string{"-c", "-o", bcfile} if triple != "pnacl" { args = append(args, "-target", triple, "-emit-llvm") } args = append(args, cgoCFLAGS...) args = append(args, cgoCPPFLAGS...) args = append(args, cfile) cmd := exec.Command(clang, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := runCmd(cmd) if err != nil { os.Remove(bcfile) return err } cmd = exec.Command(llvmlink, "-o", tempfile, tempfile, bcfile) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = runCmd(cmd) os.Remove(bcfile) if err != nil { return err } } // Link .ll files in. if len(pkg.SFiles) > 0 { args = []string{"-o", tempfile, tempfile} args = append(args, pkg.SFiles...) cmd := exec.Command(llvmlink, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := runCmd(cmd); err != nil { return err } } // If it's a command, link in the dependencies. if pkg.IsCommand() { if err := linkdeps(pkg, tempfile); err != nil { return err } if run { cmd := exec.Command(tempfile) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return runCmd(cmd) } } else if test { if err := linktest(pkg, tempfile); err != nil { return err } } else { if output != "-" && len(cgoLDFLAGS) > 0 { if err := writeLdflags(pkg.ImportPath, cgoLDFLAGS); err != nil { return err } } } return moveFile(tempfile, output) }