Skip to content

Cannot use generated pgoprofile with coverdata #4385

@EtiennePerot

Description

@EtiennePerot

I am trying to specify pgoprofile in a go_binary that (recursively) depends on @io_bazel_rules_go//go/tools/coverdata. The pgoprofile is a label that points to a generated file. This runs into the following error:

ERROR: .../BUILD:8:11: in go_library rule [...]:
Traceback (most recent call last):
        File "[...]/io_bazel_rules_go/go/private/rules/library.bzl", line 40, column 25, in _go_library_impl
                archive = go.archive(go, source)
        File "[...]/io_bazel_rules_go/go/private/actions/archive.bzl", line 77, column 17, in emit_archive
                fail("Archive mode does not match {} is {} expected {}".format(a.data.label, mode_string(a.source.mode), mode_string(go.mode)))
Error in fail: Archive mode does not match @io_bazel_rules_go//go/tools/coverdata:coverdata is linux_amd64_pure_stripped expected linux_amd64_pure_stripped

I added the following debug messages just above the fail in go/private/actions/archive.bzl's emit_archive to see what was going on:

    files = []
    for a in direct:
        files.append(a.runfiles)
        if a.source.mode != go.mode:
            print("amd64: {} vs {}: eq={}", a.source.mode.amd64, go.mode.amd64, a.source.mode.amd64 == go.mode.amd64)
            print("arm: {} vs {}: eq={}", a.source.mode.arm, go.mode.arm, a.source.mode.arm == go.mode.arm)
            print("cover_format: {} vs {}: eq={}", a.source.mode.cover_format, go.mode.cover_format, a.source.mode.cover_format == go.mode.cover
_format)
            print("debug: {} vs {}: eq={}", a.source.mode.debug, go.mode.debug, a.source.mode.debug == go.mode.debug)
            print("gc_goopts: {} vs {}: eq={}", a.source.mode.gc_goopts, go.mode.gc_goopts, a.source.mode.gc_goopts == go.mode.gc_goopts)
            print("gc_linkopts: {} vs {}: eq={}", a.source.mode.gc_linkopts, go.mode.gc_linkopts, a.source.mode.gc_linkopts == go.mode.gc_linkop
ts)
            print("goarch: {} vs {}: eq={}", a.source.mode.goarch, go.mode.goarch, a.source.mode.goarch == go.mode.goarch)
            print("goos: {} vs {}: eq={}", a.source.mode.goos, go.mode.goos, a.source.mode.goos == go.mode.goos)
            print("link: {} vs {}: eq={}", a.source.mode.link, go.mode.link, a.source.mode.link == go.mode.link)
            print("msan: {} vs {}: eq={}", a.source.mode.msan, go.mode.msan, a.source.mode.msan == go.mode.msan)
            print("pgoprofile: {} vs {}: eq={}", a.source.mode.pgoprofile, go.mode.pgoprofile, a.source.mode.pgoprofile == go.mode.pgoprofile)
            print("pure: {} vs {}: eq={}", a.source.mode.pure, go.mode.pure, a.source.mode.pure == go.mode.pure)
            print("race: {} vs {}: eq={}", a.source.mode.race, go.mode.race, a.source.mode.race == go.mode.race)
            print("stamp: {} vs {}: eq={}", a.source.mode.stamp, go.mode.stamp, a.source.mode.stamp == go.mode.stamp)
            print("static: {} vs {}: eq={}", a.source.mode.static, go.mode.static, a.source.mode.static == go.mode.static)
            print("strip: {} vs {}: eq={}", a.source.mode.strip, go.mode.strip, a.source.mode.strip == go.mode.strip)
            print("tags: {} vs {}: eq={}", a.source.mode.tags, go.mode.tags, a.source.mode.tags == go.mode.tags)
            fail("Archive mode does not match {} is {} expected {}".format(a.data.label, a.source.mode, go.mode))
    runfiles = runfiles.merge_all(files)

Which revealed that the mismatching field of mode was the pgoprofile field:

DEBUG: [...]/go/private/actions/archive.bzl:77:18: amd64: {} vs {}: eq={}   True
DEBUG: [...]/go/private/actions/archive.bzl:78:18: arm: {} vs {}: eq={}   True
DEBUG: [...]/go/private/actions/archive.bzl:79:18: cover_format: {} vs {}: eq={} lcov lcov True
DEBUG: [...]/go/private/actions/archive.bzl:80:18: debug: {} vs {}: eq={} False False True
DEBUG: [...]/go/private/actions/archive.bzl:81:18: gc_goopts: {} vs {}: eq={} [] [] True
DEBUG: [...]/go/private/actions/archive.bzl:82:18: gc_linkopts: {} vs {}: eq={} [] [] True
DEBUG: [...]/go/private/actions/archive.bzl:83:18: goarch: {} vs {}: eq={} amd64 amd64 True
DEBUG: [...]/go/private/actions/archive.bzl:84:18: goos: {} vs {}: eq={} linux linux True
DEBUG: [...]/go/private/actions/archive.bzl:85:18: link: {} vs {}: eq={} normal normal True
DEBUG: [...]/go/private/actions/archive.bzl:86:18: msan: {} vs {}: eq={} False False True
DEBUG: [...]/go/private/actions/archive.bzl:87:18: pgoprofile: {} vs {}: eq={} <generated file profile.pgo.pprof.pb> <generated file profile.pgo.pprof.pb> False
DEBUG: [...]/go/private/actions/archive.bzl:88:18: pure: {} vs {}: eq={} True True True
DEBUG: [...]/go/private/actions/archive.bzl:89:18: race: {} vs {}: eq={} False False True
DEBUG: [...]/go/private/actions/archive.bzl:90:18: stamp: {} vs {}: eq={} True True True
DEBUG: [...]/go/private/actions/archive.bzl:91:18: static: {} vs {}: eq={} False False True
DEBUG: [...]/go/private/actions/archive.bzl:92:18: strip: {} vs {}: eq={} True True True
DEBUG: [...]/go/private/actions/archive.bzl:93:18: tags: {} vs {}: eq={} ["pgo"] ["pgo"] True

... So I believe the check at

if a.source.mode != go.mode:
fail("Archive mode does not match {} is {} expected {}".format(a.data.label, mode_string(a.source.mode), mode_string(go.mode)))
is failing because a.source.mode.pgoprofile and go.mode.pgoprofile are seen as different, even though they are the same auto-generated label.

Workarounds:

  • Passing the PGO profile label as --@io_bazel_rules_go//go/config:pgoprofile works.
  • Removing the dependency on @io_bazel_rules_go//go/tools/coverdata also works.

Metadata

Metadata

Assignees

No one assigned

    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