Skip to content

Provide a better way to handle ambiguous headers in BCR indexer #173

@mateusz-olczyk

Description

@mateusz-olczyk

Problem

Module.WithAmbiguousTargetsResolved() silently drops ambiguous headers without allowing gazelle to decide what to do with them. The headers won't be included in bzldep-index.json.

@jayconrod @WojciechMazur , I'm interested in your opinions about the problem.

Real-world example

E.g., every source in grpc/examples/cpp/helloworld contains #include <grpcpp/grpcpp.h>.

Unfortunately, this header is exposed by two targets in grpc module:

$ bazel query --keep_going 2>/dev/null '
  rdeps(//..., "//:include/grpcpp/grpcpp.h", 1)
  intersect kind(cc_library, //...)
  intersect attr(visibility, //visibility:public, //...)
  except attr(testonly, True, //...)
'

//:grpc++
//:grpc++_unsecure

Core differences are as follows:

//:grpc++ //:grpc++_unsecure
extra hdrs //:src/cpp/client/secure_credentials.h
//:src/cpp/common/secure_auth_context.h
//:src/cpp/server/secure_server_credentials.h
🚫
extra deps //:gpr_public_hdrs
//:grpc++_base
//:grpc++_xds_client
//:grpc++_xds_server
//:ref_counted_ptr
//src/core:slice
@com_google_absl//absl/base:core_headers
@com_google_absl//absl/types:span
@com_google_protobuf//:protobuf
@com_google_protobuf//src/google/protobuf/io:io
//:channel_arg_names
//:gpr
//:grpc++_base_unsecure
//:grpc++_codegen_proto
//:grpc_security_base
//:grpc_unsecure
//src/core:grpc_insecure_credentials

In this particular case, we can assume that the user might prefer //:grpc++ over //:grpc++_unsecure because //:grpc++ is more generic. And usually, insecure transport is used only during the prototyping phase, quickly evolving later to some encryption method. Sometimes the choice is less obvious.

Anyway, something should be chosen, because almost always the user wants to set up a server and/or a client. Putting appopriate cc_grpc_library in deps won't be sufficient then.

Solution

  1. BCR indexer should include ambiguous headers in the output JSON file.
  2. Gazelle should later react somehow to this.

Questions

File format

The current file format is:

{
  "hdr1.h": "@repo1//:target1",
  "hdr2.h": "@repo2//:target2"
}

cannot be simply extended and has to be changed.

I see 2 approaches to achieve this.

Lists instead of single values

{
  "hdr1.h": ["@repo1//:target1"],
  "hdr2.h": ["@repo2//:target2"],
  "ambiguous_header.h": ["@other_repo//:target1", "@other_repo//:target2"]
}

Root-level distinction

{
  "unique" : {
    "hdr1.h": ["@repo1//:target1"],
    "hdr2.h": ["@repo2//:target2"]
  },
  "ambiguous": {
    "ambiguous_header.h": ["@other_repo//:target1", "@other_repo//:target2"]
  }
}

Gazelle behavior

How should the gazelle react in case of ambiguity? Should we provide some heuristics for automatic choice? We should consider 2 scenarios:

Dependency already specified

Referring to the example above, we should respect the user's decision when one of //:grpc++ or //:grpc++_unsecure is already put in deps of a rule. Whatever was chosen, we should not modify the deps, requiring the user to use # keep directive. No warnings should be displayed.

No dependency specified yet

It happens usually when there's no rule, and we generate it from scratch for the first time. Or, less often, the rule exists, but none of the ambiguous dependencies are specified.

What should we do? I think we should at least display a warning.

Should we additionally put one of arbitrarily chosen dependencies into the deps list?

  • pros: increasing the chance that the project will be ready to build, minimizing the amount of work required to make everything buildable after the gazelle run
  • cons: the user may ignore the displayed warning and forget to think more about the decision; in the opposite approach, the linking error could not be ignored

Cross-module ambiguity

Should we consider only ambiguities within a single module? Or should cross-module ambiguities also be displayed as warnings?

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions