Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions go/tools/builders/cgo2.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ func cgo2(goenv *env, goSrcs, cgoSrcs, cSrcs, cxxSrcs, objcSrcs, objcxxSrcs, sSr
}
hdrIncludes = append(hdrIncludes, "-iquote", workDir) // for _cgo_export.h

execRoot, err := bazelExecRoot()
// Trim the path in //line comments emitted by cgo.
trimPath, err := createTrimPath()
if err != nil {
return "", nil, nil, err
}
// Trim the execroot from the //line comments emitted by cgo.
args := goenv.goTool("cgo", "-srcdir", srcDir, "-objdir", workDir, "-trimpath", execRoot)
args := goenv.goTool("cgo", "-srcdir", srcDir, "-objdir", workDir, "-trimpath", trimPath)
if ldflagsFile != nil {
// The "@" prefix tells cgo to read arguments from the file.
args = append(args, "-ldflags", "@"+ldflagsFile.Name())
Expand Down Expand Up @@ -421,18 +421,6 @@ func gatherSrcs(dir string, srcs []string) ([]string, error) {
return copiedBases, nil
}

func bazelExecRoot() (string, error) {
// Bazel executes the builder with a working directory of the form
// .../execroot/<workspace name>. By stripping the last segment, we obtain a
// prefix of all possible source files, even when contained in external
// repositories.
cwd, err := os.Getwd()
if err != nil {
return "", err
}
return filepath.Dir(cwd), nil
}

type cgoError []string

func (e cgoError) Error() string {
Expand Down
43 changes: 33 additions & 10 deletions go/tools/builders/compilepkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,14 +353,35 @@ func compileArchive(
return err
}
}
gcFlags = append(gcFlags, createTrimPath(gcFlags, srcDir))
gcFlags = append(gcFlags, "-trimpath="+srcDir)
} else {
if cgoExportHPath != "" {
if err := os.WriteFile(cgoExportHPath, nil, 0o666); err != nil {
return err
}
}
gcFlags = append(gcFlags, createTrimPath(gcFlags, "."))
trimPath, err := createTrimPath()
if err != nil {
return err
}
// Preserve an existing -trimpath argument, applying abs() to each prefix.
for i, flag := range gcFlags {
if strings.HasPrefix(flag, "-trimpath=") {
gcFlags = append(gcFlags[:i], gcFlags[i+1:]...)
rewrites := strings.Split(flag[len("-trimpath="):], ";")
for j, rewrite := range rewrites {
prefix, replace := rewrite, ""
if p := strings.LastIndex(rewrite, "=>"); p >= 0 {
prefix, replace = rewrite[:p], rewrite[p:]
}
rewrites[j] = abs(prefix) + replace
}
rewrites = append(rewrites, trimPath)
trimPath = strings.Join(rewrites, ";")
break
}
}
gcFlags = append(gcFlags, "-trimpath="+trimPath)
}

importcfgPath, err := checkImportsAndBuildCfg(goenv, importPath, srcs, deps, packageListPath, recompileInternalDeps, compilingWithCgo, coverMode, workDir)
Expand Down Expand Up @@ -531,7 +552,7 @@ func compileGo(goenv *env, srcs []string, packagePath, importcfgPath, embedcfgPa
args = append(args, "-linkobj", outLinkobjPath)
args = append(args, "--")
args = append(args, srcs...)
absArgs(args, []string{"-I", "-o", "-trimpath", "-importcfg"})
absArgs(args, []string{"-I", "-o", "-importcfg"})
return goenv.runCommand(args)
}

Expand All @@ -542,14 +563,16 @@ func appendToArchive(goenv *env, pack, outPath string, objFiles []string) error
return goenv.runCommand(args)
}

func createTrimPath(gcFlags []string, path string) string {
for _, flag := range gcFlags {
if strings.HasPrefix(flag, "-trimpath=") {
return flag + ":" + path
}
func createTrimPath() (string, error) {
trimPath, err := os.Getwd()
if err != nil {
return "", err
}

return "-trimpath=" + path
// Create a trim path to make paths relative to the working directory.
// First, attempt to trim the working directory, and if this fails, replace
// the parent of the working directory with "..".
trimPath = fmt.Sprintf("%s;%s=>..", trimPath, filepath.Dir(trimPath))
return trimPath, nil
}

func sanitizePathForIdentifier(path string) string {
Expand Down
5 changes: 5 additions & 0 deletions tests/core/go_library/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,8 @@ go_library(
"//tests/core/go_test:__pkg__",
],
)

go_bazel_test(
name = "trimpath_test",
srcs = ["trimpath_test.go"],
)
8 changes: 7 additions & 1 deletion tests/core/go_library/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Basic go_library functionality
.. _#1772: https://github.com/bazelbuild/rules_go/issues/1772
.. _#2058: https://github.com/bazelbuild/rules_go/issues/2058
.. _#3558: https://github.com/bazelbuild/rules_go/issues/3558
.. _#4434: https://github.com/bazel-contrib/rules_go/issues/4434

empty
-----
Expand Down Expand Up @@ -54,4 +55,9 @@ no_srcs_test
------------

Verifies that `go_library`_ targets without Go source files build concurrently,
even unsandboxed, and reproducibly. Verifies `#3558`_.
even unsandboxed, and reproducibly. Verifies `#3558`_.

trimpath_test
-------------

Verifies that trimpath has the expected effect on paths. Verifies `#4434`_.
163 changes: 163 additions & 0 deletions tests/core/go_library/trimpath_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// Copyright 2025 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package trimpath_test

import (
"testing"

"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
)

func TestMain(m *testing.M) {
bazel_testing.TestMain(m, bazel_testing.Args{
Main: `
-- BUILD.bazel --
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "maincgo",
srcs = ["maincgo.go"],
cgo = True,
importpath = "example.com/main_repo/maincgo",
visibility = ["//visibility:private"],
)

go_library(
name = "main_lib",
srcs = ["main.go"],
deps = [":maincgo", "@other_repo//:other", "@other_repo//:othercgo"],
importpath = "example.com/main_repo/main",
visibility = ["//visibility:private"],
)

go_binary(
name = "main",
embed = [":main_lib"],
visibility = ["//visibility:public"],
)
-- main.go --
package main

import "runtime"
import "fmt"
import "example.com/main_repo/maincgo"
import "example.com/other_repo/other"
import "example.com/other_repo/othercgo"

func File() string {
_, file, _, _ := runtime.Caller(0)
return file
}

func main() {
fmt.Println(File())
fmt.Println(maincgo.File())
fmt.Println(other.File())
fmt.Println(othercgo.File())
}
-- maincgo.go --
package maincgo

import "C"
import "runtime"

func File() string {
_, file, _, _ := runtime.Caller(0)
return file
}
-- other_repo/WORKSPACE --
-- other_repo/BUILD.bazel --
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "other",
srcs = ["other.go"],
importpath = "example.com/other_repo/other",
visibility = ["//visibility:public"],
)

go_library(
name = "othercgo",
srcs = ["othercgo.go"],
cgo = True,
importpath = "example.com/other_repo/othercgo",
visibility = ["//visibility:public"],
)
-- other_repo/other.go --
package other

import "runtime"

func File() string {
_, file, _, _ := runtime.Caller(0)
return file
}
-- other_repo/othercgo.go --
package othercgo

import "C"
import "runtime"

func File() string {
_, file, _, _ := runtime.Caller(0)
return file
}
`,
WorkspaceSuffix: `
local_repository(
name = "other_repo",
path = "other_repo",
)
`,
})
}

// These are the expected paths after applying trimpath.
var expectedDefault = `
main.go
maincgo.go
external/other_repo/other.go
external/other_repo/othercgo.go
`

var expectedSibling = `
main.go
maincgo.go
../other_repo/other.go
../other_repo/othercgo.go
`

func TestTrimpath(t *testing.T) {
t.Run("default", func(t *testing.T) {
out, err := bazel_testing.BazelOutput("run", "//:main")
if err != nil {
t.Fatal(err)
}
outStr := "\n" + string(out)
if outStr != expectedDefault {
t.Fatal("actual", outStr, "vs expected", expectedDefault)
}
})
t.Run("experimental_sibling_repository_layout", func(t *testing.T) {
out, err := bazel_testing.BazelOutput("run", "--experimental_sibling_repository_layout", "//:main")
if err != nil {
t.Fatal(err)
}
outStr := "\n" + string(out)
if outStr != expectedSibling {
t.Fatal("actual", outStr, "vs expected", expectedSibling)
}
})
}
2 changes: 1 addition & 1 deletion tests/core/go_plugin_with_proto_library/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ proto_library(

go_proto_library(
name = "validate",
gc_goopts = ["-trimpath=$(BINDIR)=>."],
gc_goopts = ["-trimpath=$(BINDIR)"],
importpath = "go_plugin_with_proto_library/validate",
proto = ":validate_proto",
)