diff --git a/go/private/rules/binary.bzl b/go/private/rules/binary.bzl index 78e74e26af..3481f1fe43 100644 --- a/go/private/rules/binary.bzl +++ b/go/private/rules/binary.bzl @@ -46,6 +46,19 @@ load( _EMPTY_DEPSET = depset([]) +def _include_path(hdr): + if not hdr.root.path: + fail("Expected hdr to be a generated file, got source file: " + hdr.path) + + root_relative_path = hdr.path[len(hdr.root.path + "/"):] + if not root_relative_path.startswith("external/"): + return hdr.root.path + + # All headers should be includeable via a path relative to their repository + # root, regardless of whether the repository is external or not. If it is, + # we thus need to append "external/" to the path. + return "/".join([hdr.root.path] + root_relative_path.split("/")[0:2]) + def new_cc_import( go, hdrs = _EMPTY_DEPSET, @@ -62,7 +75,7 @@ def new_cc_import( defines = defines, local_defines = local_defines, headers = hdrs, - includes = depset([hdr.root.path for hdr in hdrs.to_list()]), + includes = depset([_include_path(hdr) for hdr in hdrs.to_list()]), ), linking_context = cc_common.create_linking_context( linker_inputs = depset([ diff --git a/tests/core/cgo/BUILD.bazel b/tests/core/cgo/BUILD.bazel index a9c9c7656e..7f39f6b29a 100644 --- a/tests/core/cgo/BUILD.bazel +++ b/tests/core/cgo/BUILD.bazel @@ -1,4 +1,5 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test") +load("@io_bazel_rules_go//go/tools/bazel_testing:def.bzl", "go_bazel_test") go_test( name = "opts_test", @@ -408,3 +409,8 @@ cc_library( srcs = ["split_import_c.c"], hdrs = ["split_import_c.h"], ) + +go_bazel_test( + name = "external_includes_test", + srcs = ["external_includes_test.go"], +) diff --git a/tests/core/cgo/external_includes_test.go b/tests/core/cgo/external_includes_test.go new file mode 100644 index 0000000000..0e1ba06afe --- /dev/null +++ b/tests/core/cgo/external_includes_test.go @@ -0,0 +1,85 @@ +// Copyright 2020 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 external_includes_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: ` +-- other_repo/WORKSPACE -- +-- other_repo/cc/BUILD.bazel -- +cc_binary( + name = "main", + srcs = ["main.c"], + deps = ["//cgo"], +) +-- other_repo/cc/main.c -- +#include "cgo/cgo.h" + +int main() {} +-- other_repo/cgo/BUILD.bazel -- +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") + +go_binary( + name = "cgo", + embed = [":cgo_lib"], + importpath = "example.com/rules_go/cgo", + linkmode = "c-archive", + visibility = ["//visibility:public"], +) + +go_library( + name = "cgo_lib", + srcs = ["cgo.go"], + cgo = True, + importpath = "example.com/rules_go/cgo", + visibility = ["//visibility:private"], +) +-- other_repo/cgo/cgo.go -- +package main + +import "C" + +//export HelloCgo +func HelloCgo() {} + +func main() {} +`, + WorkspaceSuffix: ` +local_repository( + name = "other_repo", + path = "other_repo", +) +`, + }) +} + +func TestExternalIncludes(t *testing.T) { + t.Run("default", func(t *testing.T) { + if err := bazel_testing.RunBazel("build", "@other_repo//cc:main"); err != nil { + t.Fatalf("Did not expect error:\n%+v", err) + } + }) + t.Run("experimental_sibling_repository_layout", func(t *testing.T) { + if err := bazel_testing.RunBazel("build", "--experimental_sibling_repository_layout", "@other_repo//cc:main"); err != nil { + t.Fatalf("Did not expect error:\n%+v", err) + } + }) +}