aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2020-03-06 12:40:21 +0100
committerRon Evans <[email protected]>2020-03-17 20:43:28 +0100
commita8da6016723ed83f5148bc2908f990de7ef79ed8 (patch)
treef922bc8e03453bc07f23364c7699b198d12e40d2
parent9cef23c31817f24cadc6ea044123736541dcaa07 (diff)
downloadtinygo-a8da6016723ed83f5148bc2908f990de7ef79ed8.tar.gz
tinygo-a8da6016723ed83f5148bc2908f990de7ef79ed8.zip
cgo: make -I and -L paths absolute
This is very useful for (conditionally) adding extra include paths relative to the package path.
-rw-r--r--cgo/cgo.go39
-rw-r--r--cgo/testdata/flags.go4
-rw-r--r--cgo/testdata/flags.out.go1
-rw-r--r--cgo/testdata/include/foo.h1
4 files changed, 45 insertions, 0 deletions
diff --git a/cgo/cgo.go b/cgo/cgo.go
index 5799b4fa5..58aaed81c 100644
--- a/cgo/cgo.go
+++ b/cgo/cgo.go
@@ -14,7 +14,9 @@ package cgo
import (
"fmt"
"go/ast"
+ "go/scanner"
"go/token"
+ "path/filepath"
"sort"
"strconv"
"strings"
@@ -173,6 +175,18 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
generatedTokenPos.SetLines([]int{0})
p.generatedPos = generatedTokenPos.Pos(0)
+ // Find the absolute path for this package.
+ packagePath, err := filepath.Abs(fset.File(files[0].Pos()).Name())
+ if err != nil {
+ return nil, []error{
+ scanner.Error{
+ Pos: fset.Position(files[0].Pos()),
+ Msg: "cgo: cannot find absolute path: " + err.Error(), // TODO: wrap this error
+ },
+ }
+ }
+ packagePath = filepath.Dir(packagePath)
+
// Construct a new in-memory AST for CGo declarations of this package.
unsafeImport := &ast.ImportSpec{
Path: &ast.BasicLit{
@@ -338,6 +352,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
p.addErrorAfter(comment.Slash, comment.Text[:lineStart+colon+1], err.Error())
continue
}
+ makePathsAbsolute(flags, packagePath)
cflags = append(cflags, flags...)
default:
startPos := strings.LastIndex(line[4:colon], name) + 4
@@ -395,6 +410,30 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
return p.generated, p.errors
}
+// makePathsAbsolute converts some common path compiler flags (-I, -L) from
+// relative flags into absolute flags, if they are relative. This is necessary
+// because the C compiler is usually not invoked from the package path.
+func makePathsAbsolute(args []string, packagePath string) {
+ nextIsPath := false
+ for i, arg := range args {
+ if nextIsPath {
+ if !filepath.IsAbs(arg) {
+ args[i] = filepath.Join(packagePath, arg)
+ }
+ }
+ if arg == "-I" || arg == "-L" {
+ nextIsPath = true
+ continue
+ }
+ if strings.HasPrefix(arg, "-I") || strings.HasPrefix(arg, "-L") {
+ path := arg[2:]
+ if !filepath.IsAbs(path) {
+ args[i] = arg[:2] + filepath.Join(packagePath, path)
+ }
+ }
+ }
+}
+
// addFuncDecls adds the C function declarations found by libclang in the
// comment above the `import "C"` statement.
func (p *cgoPackage) addFuncDecls() {
diff --git a/cgo/testdata/flags.go b/cgo/testdata/flags.go
index bb518e554..d52bbc5b9 100644
--- a/cgo/testdata/flags.go
+++ b/cgo/testdata/flags.go
@@ -9,6 +9,9 @@ package main
#cgo CFLAGS: -DFOO
+#cgo CFLAGS: -Iinclude
+#include "foo.h"
+
#if defined(FOO)
#define BAR 3
#else
@@ -23,4 +26,5 @@ import "C"
var (
_ = C.BAR
+ _ = C.FOO_H
)
diff --git a/cgo/testdata/flags.out.go b/cgo/testdata/flags.out.go
index dba5d1fbe..0bcad0d5a 100644
--- a/cgo/testdata/flags.out.go
+++ b/cgo/testdata/flags.out.go
@@ -9,6 +9,7 @@ import "unsafe"
var _ unsafe.Pointer
const C.BAR = 3
+const C.FOO_H = 1
type C.int16_t = int16
type C.int32_t = int32
diff --git a/cgo/testdata/include/foo.h b/cgo/testdata/include/foo.h
new file mode 100644
index 000000000..8fa2b1e18
--- /dev/null
+++ b/cgo/testdata/include/foo.h
@@ -0,0 +1 @@
+#define FOO_H 1