Skip to content

Commit

Permalink
Merge 4659064 into a5f40c8
Browse files Browse the repository at this point in the history
  • Loading branch information
zchee committed Sep 29, 2020
2 parents a5f40c8 + 4659064 commit a86e614
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 41 deletions.
20 changes: 12 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ cache:
git:
depth: 10

matrix:
fast_finish: true
allow_failures:
- go: master

addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5
- llvm-toolchain-trusty-3.9
packages:
- llvm-3.5
- clang-3.5
- libclang1-3.5
- libclang-3.5-dev
- llvm-3.9
- clang-3.9
- libclang-3.9-dev

env:
global:
Expand All @@ -32,9 +36,9 @@ env:

install:
- mkdir -p /home/travis/bin
- sudo ln -s /usr/bin/clang-3.5 /home/travis/bin/clang
- sudo ln -s /usr/bin/clang++-3.5 /home/travis/bin/clang++
- sudo ln -s /usr/bin/llvm-config-3.5 /home/travis/bin/llvm-config
- sudo ln -s /usr/bin/clang-3.9 /home/travis/bin/clang
- sudo ln -s /usr/bin/clang++-3.9 /home/travis/bin/clang++
- sudo ln -s /usr/bin/llvm-config-3.9 /home/travis/bin/llvm-config
- sudo ldconfig

- llvm-config --version
Expand Down
5 changes: 3 additions & 2 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gen

import (
"bytes"
"fmt"
"go/ast"
"go/format"
"go/token"
Expand Down Expand Up @@ -40,7 +41,7 @@ func generateFunctionString(fa *ASTFunc) string {
var b bytes.Buffer
err := format.Node(&b, token.NewFileSet(), []ast.Decl{fa.FuncDecl})
if err != nil {
panic(err)
panic(fmt.Errorf("unexpected error: %w", err))
}

fStr := b.String()
Expand Down Expand Up @@ -234,7 +235,7 @@ func (fa *ASTFunc) generateParameters() []ast.Expr {
} else if p.Type.PointerLevel > 0 && p.Type.IsPrimitive && p.Type.CGoName != CSChar {
hasDeclaration = true

var varType = doCType(p.Type.CGoName)
varType := doCType(p.Type.CGoName)

fa.addStatement(doDeclare(
"cp_"+p.Name,
Expand Down
4 changes: 2 additions & 2 deletions astutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func doDeclare(name string, typ ast.Expr) *ast.DeclStmt {
Specs: []ast.Spec{
&ast.ValueSpec{
Names: []*ast.Ident{
&ast.Ident{
{
Name: name,
},
},
Expand All @@ -68,7 +68,7 @@ func doField(name string, typ Type) *ast.Field {

if name != "" {
f.Names = []*ast.Ident{
&ast.Ident{
{
Name: name,
},
}
Expand Down
20 changes: 13 additions & 7 deletions clang/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/termie/go-shutil"

"github.com/go-clang/gen"
)

Expand All @@ -21,8 +20,8 @@ func cmdFatal(msg string, err error) error {
}

// Cmd executes a generic go-clang-generate command
func Cmd(args []string, api *gen.API) error {
rawLLVMVersion, _, err := execToBuffer("llvm-config", "--version")
func Cmd(llvmConfigPath string, api *gen.API) error {
rawLLVMVersion, _, err := execToBuffer(llvmConfigPath, "--version")
if err != nil {
return cmdFatal("Cannot determine LLVM version", err)
}
Expand All @@ -34,7 +33,7 @@ func Cmd(args []string, api *gen.API) error {

fmt.Println("Found LLVM version", llvmVersion.String())

rawLLVMIncludeDir, _, err := execToBuffer("llvm-config", "--includedir")
rawLLVMIncludeDir, _, err := execToBuffer(llvmConfigPath, "--includedir")
if err != nil {
return cmdFatal("Cannot determine LLVM include directory", err)
}
Expand Down Expand Up @@ -67,15 +66,15 @@ func Cmd(args []string, api *gen.API) error {

api.ClangArguments = append(clangArguments, api.ClangArguments...)

fmt.Printf("Using clang arguments: %v\n", clangArguments)
fmt.Printf("Using clang arguments: %v\n", api.ClangArguments)

fmt.Printf("Will generate go-clang for LLVM version %s into the current directory\n", llvmVersion.String())

clangCDirectory := "./clang-c/"

// Copy the Clang-C include directory into the current directory
_ = os.RemoveAll(clangCDirectory)
if err := shutil.CopyTree(clangCIncludeDir, clangCDirectory, nil); err != nil {
if err := copyTree(clangCIncludeDir, clangCDirectory); err != nil {
return cmdFatal(fmt.Sprintf("Cannot copy Clang-C include directory %q into current directory", clangCIncludeDir), err)
}

Expand All @@ -94,6 +93,13 @@ func Cmd(args []string, api *gen.API) error {
}
}

const doc = `// Package clang-c holds clang binding C header files.
package clang_c
`
if err := ioutil.WriteFile(filepath.Join(clangCDirectory, "doc.go"), []byte(doc), 0o600); err != nil {
return err
}

headerFiles, err := api.HandleDirectory(clangCDirectory)
if err != nil {
return err
Expand Down
170 changes: 170 additions & 0 deletions clang/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package clang

import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"syscall"
)

Expand Down Expand Up @@ -73,3 +77,169 @@ func fileExists(filepath string) error {

return nil
}

func isSymlink(fi os.FileInfo) bool {
return (fi.Mode() & os.ModeSymlink) == os.ModeSymlink
}

func copyFile(src, dst string) error {
srcInfo, _ := os.Stat(src)
dstInfo, _ := os.Stat(dst)
if os.SameFile(srcInfo, dstInfo) {
return fmt.Errorf("%q and %q are the same file", src, dst)
}

srcStat, err := os.Lstat(src)
if err != nil {
return err
}

if _, err := os.Stat(dst); err != nil && !os.IsNotExist(err) {
return err
}

// If we don't follow symlinks and it's a symlink, just link it and be done
if isSymlink(srcStat) {
return os.Symlink(src, dst)
}

// If we are a symlink, follow it
if isSymlink(srcStat) {
src, err = os.Readlink(src)
if err != nil {
return err
}
srcStat, err = os.Stat(src)
if err != nil {
return err
}
}

// Do the actual copy
fsrc, err := os.Open(src)
if err != nil {
return err
}
defer fsrc.Close()

fdst, err := os.Create(dst)
if err != nil {
return err
}
defer fdst.Close()

size, err := io.Copy(fdst, fsrc)
if err != nil {
return err
}

if size != srcStat.Size() {
return fmt.Errorf("%s: %d/%d copied", src, size, srcStat.Size())
}

return nil
}

func copyMode(src, dst string) error {
srcStat, err := os.Lstat(src)
if err != nil {
return err
}

dstStat, err := os.Lstat(dst)
if err != nil {
return err
}

// They are both symlinks and we can't change mode on symlinks.
if isSymlink(srcStat) && isSymlink(dstStat) {
return nil
}

// Atleast one is not a symlink, get the actual file stats
srcStat, _ = os.Stat(src)
err = os.Chmod(dst, srcStat.Mode())
return err
}

func copyFunc(src, dst string) (string, error) {
dstInfo, err := os.Stat(dst)

if err == nil && dstInfo.Mode().IsDir() {
dst = filepath.Join(dst, filepath.Base(src))
}

if err != nil && !os.IsNotExist(err) {
return dst, err
}

if err := copyFile(src, dst); err != nil {
return dst, err
}

if err := copyMode(src, dst); err != nil {
return dst, err
}

return dst, nil
}

func copyTree(src, dst string) error {
srcFileInfo, err := os.Stat(src)
if err != nil {
return err
}

if !srcFileInfo.IsDir() {
return fmt.Errorf("%q is not a directory", src)
}

if _, err := os.Open(dst); !os.IsNotExist(err) {
return fmt.Errorf("%q already exists", dst)
}

entries, err := ioutil.ReadDir(src)
if err != nil {
return err
}

if err := os.MkdirAll(dst, srcFileInfo.Mode()); err != nil {
return err
}

for _, entry := range entries {
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())

entryFileInfo, err := os.Lstat(srcPath)
if err != nil {
return err
}

switch {
case isSymlink(entryFileInfo):
linkTo, err := os.Readlink(srcPath)
if err != nil {
return err
}
// ignore dangling symlink if flag is on
_, err = os.Stat(linkTo)
_, err = copyFunc(srcPath, dstPath)
if err != nil {
return err
}
case entryFileInfo.IsDir():
err = copyTree(srcPath, dstPath)
if err != nil {
return err
}
default:
_, err = copyFunc(srcPath, dstPath)
if err != nil {
return err
}
}
}

return nil
}
29 changes: 28 additions & 1 deletion cmd/go-clang-gen/main.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
package main

import (
"flag"
"fmt"
"os"
"os/exec"
"strings"

"github.com/go-clang/gen"
genclang "github.com/go-clang/gen/clang"
)

var (
flagClangResourceDir string
flagLLVMConfigPath string
)

func init() {
flag.StringVar(&flagClangResourceDir, "clang-resource-dir", "", "Clang resource directory")
flag.StringVar(&flagLLVMConfigPath, "llvm-config", "", "llvm-config binary path")
}

func main() {
flag.Parse()

api := &gen.API{
PrepareFunctionName: prepareFunctionName,
PrepareFunction: prepareFunction,
Expand All @@ -21,7 +35,20 @@ func main() {
FilterStructMemberGetter: filterStructMemberGetter,
}

err := genclang.Cmd(os.Args[1:], api)
if flagClangResourceDir != "" {
if resourceDir, err := os.Stat(flagClangResourceDir); err == nil && resourceDir.IsDir() {
api.ClangArguments = append(api.ClangArguments, "-I"+resourceDir.Name())
}
}

llvmConfig := "llvm-config"
if flagLLVMConfigPath != "" {
if bin, err := exec.LookPath(flagLLVMConfigPath); err == nil {
llvmConfig = bin
}
}

err := genclang.Cmd(llvmConfig, api)
if err != nil {
fmt.Println(err)

Expand Down

0 comments on commit a86e614

Please sign in to comment.