Example #1
0
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
}
Example #2
0
File: build.go Project: minux/llgo
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)
}