Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

language/go: merge new Go naming convention to master #863

Merged
merged 9 commits into from
Aug 19, 2020

Conversation

jayconrod
Copy link
Contributor

What type of PR is this?

Feature

What package or component does this PR mostly affect?

//language/go

What does this PR do? Why is it needed?

  • Adds a configurable naming convention for the the //language/go extension.
    • In import mode, libraries and tests will be named based on the last component of their import paths.
    • In go_default_library mode, libraries and tests will be named go_default_library and go_default_test.
    • In import_alias mode, targets are generated with the import mode, but aliases are generated with the go_default_library mode. This should be used in repositories that other projects may depend on. go_repository uses this mode by default.
  • If no naming convention is specified, Gazelle will attempt to detect one by reading build files in the root directory and subdirectories (non-recursively). If no naming convention is detected (as in a new project), Gazelle defaults to import.
  • To simplify migration, Gazelle can rename targets previously generated in a different naming convention. This happens for both fix and update.
  • Gazelle itself now uses the import_alias naming convention.

Credit to @tomlu for implementing most of this.

Which issues(s) does this PR fix?

Fixes #5

Other notes for review

cc @linzhp @blico: Please take a look and see if this will cause any issues for you. My expectation is that it should auto-detect the go_default_library mode, and then very little should change until you explicitly specify another mode.

cc @tomlu: I think you've been using this branch for a while, but please confirm this final version works for you.

tomlu and others added 6 commits July 15, 2020 13:20
Add directive 'go_naming_convention' to control the name of
generated Go rules.

go_default_library: Legacy behaviour.
import: Name targets after their import path.
import_alias: Same as import, but generate alias targets to
  maintain backwards compatibility with go_default_library.

We also add a `build_naming_convention` attribute to
`go_repository` rules, allowing per-external control over
the naming convention.

gazelle fix is augmented to migrate between the different
styles, both forwards and backwards.

For #5
* For external dependency resolution, if we don't know what naming
  convention the external repository uses (for example, because
  there's no known repository), we'll now use
  goDefaultLibraryNamingConvention. This avoids assuming that
  repositories with build files fetched with http_archive have been
  updated.
* In migrateNamingConvention, print a warning and avoid renaming if
  there's already a target with the new name.
* Library, test, and alias actuals are now generated based on import
  path instead of package name.
* Added unknownNamingConvention, a new zero value.
* Added detectNamingConvention. It reads the root build file and build
  files in subdirectories one level deep to infer the naming
  convention used if one is not specified in the root build
  file. Defaults to importNamingConvention.
* Delete empty go_library rules in directories with go_binary.
* Fixed tests.

For #5
* Set naming convention in main build file.
* Add gazelle:repository declarations in WORKSPACE for repos in gazelle_dependencies.
* Run 'gazelle fix'.
* Manual fixes for manually written targets.

For #5
@linzhp
Copy link
Contributor

linzhp commented Aug 10, 2020

Checking

@tomlu
Copy link
Contributor

tomlu commented Aug 10, 2020

I ran this on our depot and ran into the issue where local_repository repos are assumed to have go_default_library naming convention. As previously discussed we can go and add directives to the WORKSPACE file (about 60-70 or so at present), but I'd also have to do something to make sure they are added for new go repos. This would be slightly hard because I can't tell locally from a local_repository rule whether it's a Go repo or not.

I don't suppose there could be yet another directive to set the default if there is no info?

Allows the user to set the default Go naming convention used when
resolving imports of packages in external repositories with unknown
naming conventions.

For #5
@blico
Copy link
Contributor

blico commented Aug 12, 2020

My expectation is that we should be able to pull in this change without having to update our naming convention from go_default_library to import mode. Because of the structure of our repo, Gazelle does not auto-detect any naming conventions, meaning it defaults to import mode. To fix, I added -go_naming_convention=go_default_library and -go_naming_convetion_extern=go_default_library to our Gazelle invocation. I also added these directives to all of our go_repository rules to avoid having to update any dep attributes within our repo.

After adding these flags I am still running into some issues:

no such target '@com_github_pmezard_go_difflib//difflib:difflib': target 'difflib' not declared in package 'difflib' (did you mean 'difflib.go'?) defined by /private/var/tmp/_bazel_blico/c2029ca547e9eb006cd11184438b8215/external/com_github_pmezard_go_difflib/difflib/BUILD.bazel and referenced by '@bazel_gazelle//cmd/gazelle:gazelle_lib

The problem here appears to be that Gazelle and our repo share a dependency on com_github_pmezard_go_difflib, and Gazelle depends on the imports version whereas our repo depends on the go_default_library version. I see a similar error for all shared dependencies between Gazelle and our repo.

Gazelle is also adding an unwanted :go_default_library to the embed attr of go_test rules where we have a BUILD.bazel with two go_test rules defined. For example:

go_library(
    name = "go_default_library",
    srcs = [
        "constants.go",
        "handler.go",
    ],
    importpath = "github.com/foo",
    visibility = ["//visibility:public"],
)

EXTERNAL_TEST_SRCS = [
    "open_diff_test.go",
]

go_test(
    name = "go_default_test",
    # Remove once https://github.com/bazelbuild/rules_go/issues/1877 is resolved.
    # keep
    srcs = glob(
        ["*_test.go"],
        exclude = EXTERNAL_TEST_SRCS,
    ),
    embed = [":go_default_library"],
)

go_test(
    name = "go_external_test",
    srcs = ["open_diff_test.go"],
+   embed = [":go_default_library"],
    deps = [
        ":go_default_library",
    ],
)

Finally, Gazelle is giving a warning for the following case with multiple go_library rules defined in a single BUILD.bazel:

genrule(
   name = "gen",
   out = "bar.go",
)

go_library(
    name = "gen",
    srcs = ["bar.go"],
    importpath = "github.com/foo/gen",
    deps = [
        ":go_default_library",
    ],
)

go_library(
    name = "go_default_library",
    srcs = ["foo.go"],
    importpath = "github.com/foo",
)

Warning: Tried to rename gen to go_default_library, but go_default_library already exists.

@jayconrod
Copy link
Contributor Author

Thanks @blico, that feedback is really helpful.

I'm curious why it was necessary to set build_naming_convention = "go_default_library" on go_repository rules. By default, go_repository should use import_alias, which will generate targets with the new names and alias with the old names, so either should work. As of the latest commit in this PR (yesterday afternoon), Gazelle should resolve external dependencies using -go_naming_convention_extern if that's set, or the naming convention in the current directory if not. Either way, I'd expect your deps to follow the go_default_library convention.

I'll put together a PR soon with the following changes:

  • If needed, rewrite deps in the Gazelle repo with -go_naming_convention_external=go_default_library for now.
  • Don't add embed of :go_default_library when multiple go_test targets are present.
  • Narrow the cases where renaming is performed to avoid that warning.
  • Probably change go_naming_convention_extern to go_naming_convention_external. I realized there's no good reason to abbreviate "external".

@blico
Copy link
Contributor

blico commented Aug 13, 2020

I was able to confirm we do not need to set go_naming_convention=go_default_library on all go_repository rules (only the ones with patches to BUILD.bazel files), meaning it is no longer a problem for us to have the Gazelle repo deps with the new convention.

Jay Conrod added 2 commits August 18, 2020 12:50
* Rename goNamingConventionExtern to goNamingConventionExternal,
  together with the flag and directive. No need to abbrev.
* Only migrate go_library if it matches the expected import path for
  the directory. This avoids migrating the wrong target when there are
  multiple go_libraries in the same directory.
* Only migrate go_test if it embeds the library.
* When fixing rules, don't add an embed attribute to go_test.

For #5
@jayconrod
Copy link
Contributor Author

Ok, the issues above are fixed, so I think this is basically ready to go. Let me know if you see any other problems. If not, I'll merge this tomorrow.

@jayconrod jayconrod merged commit 29343aa into master Aug 19, 2020
@jayconrod jayconrod deleted the go_naming_convention branch August 19, 2020 21:30
@achew22
Copy link
Member

achew22 commented Aug 19, 2020

Congrats, @jayconrod and @tomlu! This is a huge step foward for rules_go

jeevatkm pushed a commit to go-resty/resty that referenced this pull request Sep 12, 2021
* Update Bazel build to work with 4.0.0

This includes several updates to the BUILD and WORKSPACE files, so that they now work with Bazel 4.0.0, Gazelle 0.23 and rules_go 0.27.

By default, [Gazelle now uses](bazel-contrib/bazel-gazelle#863) the last component of the Bazel package, rather than `go_default_library` as the `go_library name`.

This causes problems when the naming conventions do not match.
bazel-contrib/bazel-gazelle#890 (comment)

Adding support for the new naming convention should not break anything that depends on using the old naming convention, because the Gazelle option `import_alias` makes aliases to the libraries and this allows the old naming convention to still work.
DomenicoSola pushed a commit to DomenicoSola/resty that referenced this pull request Oct 19, 2022
* Update Bazel build to work with 4.0.0

This includes several updates to the BUILD and WORKSPACE files, so that they now work with Bazel 4.0.0, Gazelle 0.23 and rules_go 0.27.

By default, [Gazelle now uses](bazel-contrib/bazel-gazelle#863) the last component of the Bazel package, rather than `go_default_library` as the `go_library name`.

This causes problems when the naming conventions do not match.
bazel-contrib/bazel-gazelle#890 (comment)

Adding support for the new naming convention should not break anything that depends on using the old naming convention, because the Gazelle option `import_alias` makes aliases to the libraries and this allows the old naming convention to still work.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use package name instead of go_default_library for rules
5 participants