Repository: cilium/ebpf
Pull request #162 (2020-11-13 15:39:56)

cmd/bpf2go: output ELF .o next to the .go file
Go 1.16 will add file embedding via magic comments, which we can use to
store the .o file instead of stuffing it into a global. Move the
compiled object file next to the .go to simplify this in the future.


Patch:
diff --git a/cmd/bpf2go/main.go b/cmd/bpf2go/main.go
index d616960..066cfac 100644
--- a/cmd/bpf2go/main.go
+++ b/cmd/bpf2go/main.go
@@ -143,8 +143,8 @@ func run(stdout io.Writer, pkg, outputDir string, args []string) (err error) {
 
 	cFlags = cFlags[:len(cFlags):len(cFlags)]
 	for _, target := range targets {
-		objFileName := fmt.Sprintf("%s_%s.o", stripExtension(inputFile), target)
-		objFileName = filepath.Join(inputDir, objFileName)
+		objFileName := fmt.Sprintf("%s_%s.o", strings.ToLower(ident), target)
+		objFileName = filepath.Join(outputDir, objFileName)
 
 		var dep bytes.Buffer
 		err = compile(compileArgs{
diff --git a/cmd/bpf2go/output.go b/cmd/bpf2go/output.go
index e97a328..642793f 100644
--- a/cmd/bpf2go/output.go
+++ b/cmd/bpf2go/output.go
@@ -14,6 +14,8 @@ import (
 	"github.com/cilium/ebpf"
 )
 
+const ebpfModule = "github.com/cilium/ebpf"
+
 const commonRaw = `// Code generated by bpf2go; DO NOT EDIT.
 {{- range .Tags }}
 // +build {{ . }}
@@ -26,7 +28,7 @@ import (
 	"fmt"
 	"io"
 
-	"github.com/cilium/ebpf"
+	"{{ .Module }}"
 )
 
 type {{ .Name.Specs }} struct {
@@ -210,6 +212,7 @@ func writeCommon(args writeArgs) error {
 	}
 
 	ctx := struct {
+		Module   string
 		Package  string
 		Tags     []string
 		Name     templateName
@@ -218,6 +221,7 @@ func writeCommon(args writeArgs) error {
 		Programs map[string]*ebpf.ProgramSpec
 		Bytes    string
 	}{
+		ebpfModule,
 		args.pkg,
 		args.tags,
 		templateName(args.ident),


Test patch:
diff --git a/cmd/bpf2go/compile_test.go b/cmd/bpf2go/compile_test.go
index b70da70..0876fd8 100644
--- a/cmd/bpf2go/compile_test.go
+++ b/cmd/bpf2go/compile_test.go
@@ -13,8 +13,7 @@ import (
 const minimalSocketFilter = `__attribute__((section("socket"), used)) int main() { return 0; }`
 
 func TestCompile(t *testing.T) {
-	dir, cleanup := mustWriteTempFile(t, "test.c", minimalSocketFilter)
-	defer cleanup()
+	dir := mustWriteTempFile(t, "test.c", minimalSocketFilter)
 
 	var dep bytes.Buffer
 	err := compile(compileArgs{
@@ -47,8 +46,7 @@ func TestCompile(t *testing.T) {
 }
 
 func TestReproducibleCompile(t *testing.T) {
-	dir, cleanup := mustWriteTempFile(t, "test.c", minimalSocketFilter)
-	defer cleanup()
+	dir := mustWriteTempFile(t, "test.c", minimalSocketFilter)
 
 	err := compile(compileArgs{
 		cc:     "clang-9",
@@ -135,21 +133,19 @@ nothing:
 	}
 }
 
-func mustWriteTempFile(t *testing.T, name, contents string) (string, func()) {
+func mustWriteTempFile(t *testing.T, name, contents string) string {
 	t.Helper()
 
 	tmp, err := ioutil.TempDir("", "bpf2go")
 	if err != nil {
 		t.Fatal(err)
 	}
-
-	cleanup := func() { os.RemoveAll(tmp) }
+	t.Cleanup(func() { os.RemoveAll(tmp) })
 
 	tmpFile := filepath.Join(tmp, name)
 	if err := ioutil.WriteFile(tmpFile, []byte(contents), 0660); err != nil {
-		cleanup()
 		t.Fatal(err)
 	}
 
-	return tmp, cleanup
+	return tmp
 }
diff --git a/cmd/bpf2go/main_test.go b/cmd/bpf2go/main_test.go
index ea4d216..4f9b23c 100644
--- a/cmd/bpf2go/main_test.go
+++ b/cmd/bpf2go/main_test.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"bytes"
+	"fmt"
 	"io/ioutil"
 	"os"
 	"os/exec"
@@ -10,22 +11,47 @@ import (
 )
 
 func TestRun(t *testing.T) {
-	dir, cleanup := mustWriteTempFile(t, "test.c", minimalSocketFilter)
-	defer cleanup()
+	dir := mustWriteTempFile(t, "test.c", minimalSocketFilter)
 
 	cwd, err := os.Getwd()
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	// The temporary package has to be in the same module, otherwise
-	// we can't test against unreleased versions of the package.
-	tmpDir, err := ioutil.TempDir(cwd, "bpf2go-module-*")
+	modRoot := filepath.Clean(filepath.Join(cwd, "../.."))
+	if _, err := os.Stat(filepath.Join(modRoot, "go.mod")); os.IsNotExist(err) {
+		t.Fatal("No go.mod file in", modRoot)
+	}
+
+	tmpDir, err := ioutil.TempDir("", "bpf2go-module-*")
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer os.RemoveAll(tmpDir)
 
+	execInModule := func(name string, args ...string) {
+		t.Helper()
+
+		cmd := exec.Command(name, args...)
+		cmd.Dir = tmpDir
+		if out, err := cmd.CombinedOutput(); err != nil {
+			if out := string(out); out != "" {
+				t.Log(out)
+			}
+			t.Fatalf("Can't execute %s: %v", name, args)
+		}
+	}
+
+	execInModule("go", "mod", "init", "bpf2go-test")
+
+	execInModule("go", "mod", "edit",
+		// Require the module. The version doesn't matter due to the replace
+		// below.
+		fmt.Sprintf("-require=%s@v0.0.0", ebpfModule),
+		// Replace the module with the current version.
+		fmt.Sprintf("-replace=%s=%s", ebpfModule, modRoot),
+	)
+
 	err = run(ioutil.Discard, "foo", tmpDir, []string{
 		"-cc", "clang-9",
 		"bar",
@@ -40,18 +66,21 @@ func TestRun(t *testing.T) {
 		"amd64", // little-endian
 		"s390x", // big-endian
 	} {
-		goBin := exec.Command("go", "build", tmpDir)
-		goBin.Env = append(os.Environ(),
-			"GOOS=linux",
-			"GOARCH="+arch,
-		)
-		out, err := goBin.CombinedOutput()
-		if err != nil {
-			if out := string(out); out != "" {
-				t.Log(out)
+		t.Run(arch, func(t *testing.T) {
+			goBin := exec.Command("go", "build", "-mod=mod")
+			goBin.Dir = tmpDir
+			goBin.Env = append(os.Environ(),
+				"GOOS=linux",
+				"GOARCH="+arch,
+			)
+			out, err := goBin.CombinedOutput()
+			if err != nil {
+				if out := string(out); out != "" {
+					t.Log(out)
+				}
+				t.Error("Can't compile package:", err)
 			}
-			t.Errorf("Can't compile resulting package for arch %s: %s", arch, err)
-		}
+		})
 	}
 }
 
diff --git a/run-tests.sh b/run-tests.sh
index 0e85c63..bd349f9 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -12,7 +12,8 @@ if [[ "${1:-}" = "--in-vm" ]]; then
   export CGO_ENABLED=0
   export GOFLAGS=-mod=readonly
   export GOPATH=/run/go-path
-  export GOPROXY=file:///run/go-root/pkg/mod/cache/download
+  export GOPROXY=file:///run/go-path/pkg/mod/cache/download
+  export GOSUMDB=off
   export GOCACHE=/run/go-cache
 
   elfs=""