...

Text file src/github.com/bazelbuild/rules_go/go/private/mode.bzl

Documentation: github.com/bazelbuild/rules_go/go/private

     1# Copyright 2017 The Bazel Authors. All rights reserved.
     2#
     3# Licensed under the Apache License, Version 2.0 (the "License");
     4# you may not use this file except in compliance with the License.
     5# You may obtain a copy of the License at
     6#
     7#    http://www.apache.org/licenses/LICENSE-2.0
     8#
     9# Unless required by applicable law or agreed to in writing, software
    10# distributed under the License is distributed on an "AS IS" BASIS,
    11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12# See the License for the specific language governing permissions and
    13# limitations under the License.
    14
    15# Modes are documented in go/modes.rst#compilation-modes
    16
    17LINKMODE_NORMAL = "normal"
    18
    19LINKMODE_SHARED = "shared"
    20
    21LINKMODE_PIE = "pie"
    22
    23LINKMODE_PLUGIN = "plugin"
    24
    25LINKMODE_C_SHARED = "c-shared"
    26
    27LINKMODE_C_ARCHIVE = "c-archive"
    28
    29LINKMODES = [LINKMODE_NORMAL, LINKMODE_PLUGIN, LINKMODE_C_SHARED, LINKMODE_C_ARCHIVE, LINKMODE_PIE]
    30
    31# All link modes that produce executables to be run with bazel run.
    32LINKMODES_EXECUTABLE = [LINKMODE_NORMAL, LINKMODE_PIE]
    33
    34# All link modes that require external linking and thus a cgo context.
    35LINKMODES_REQUIRING_EXTERNAL_LINKING = [
    36    LINKMODE_PLUGIN,
    37    LINKMODE_C_ARCHIVE,
    38    LINKMODE_C_SHARED,
    39]
    40
    41def mode_string(mode):
    42    result = [mode.goos, mode.goarch]
    43    if mode.static:
    44        result.append("static")
    45    if mode.race:
    46        result.append("race")
    47    if mode.msan:
    48        result.append("msan")
    49    if mode.pure:
    50        result.append("pure")
    51    if mode.debug:
    52        result.append("debug")
    53    if mode.strip:
    54        result.append("stripped")
    55    if not result or not mode.link == LINKMODE_NORMAL:
    56        result.append(mode.link)
    57    if mode.gc_goopts:
    58        result.extend(mode.gc_goopts)
    59    return "_".join(result)
    60
    61def _ternary(*values):
    62    for v in values:
    63        if v == None:
    64            continue
    65        if type(v) == "bool":
    66            return v
    67        if type(v) != "string":
    68            fail("Invalid value type {}".format(type(v)))
    69        v = v.lower()
    70        if v == "on":
    71            return True
    72        if v == "off":
    73            return False
    74        if v == "auto":
    75            continue
    76        fail("Invalid value {}".format(v))
    77    fail("_ternary failed to produce a final result from {}".format(values))
    78
    79def get_mode(ctx, go_toolchain, cgo_context_info, go_config_info):
    80    static = _ternary(go_config_info.static if go_config_info else "off")
    81    if getattr(ctx.attr, "pure", None) == "off" and not cgo_context_info:
    82        fail("{} has pure explicitly set to off, but no C++ toolchain could be found for its platform".format(ctx.label))
    83    pure = _ternary(
    84        "on" if not cgo_context_info else "auto",
    85        go_config_info.pure if go_config_info else "off",
    86    )
    87    race = _ternary(go_config_info.race if go_config_info else "off")
    88    msan = _ternary(go_config_info.msan if go_config_info else "off")
    89    strip = go_config_info.strip if go_config_info else False
    90    stamp = go_config_info.stamp if go_config_info else False
    91    debug = go_config_info.debug if go_config_info else False
    92    linkmode = go_config_info.linkmode if go_config_info else LINKMODE_NORMAL
    93    cover_format = go_config_info and go_config_info.cover_format
    94    amd64 = go_config_info.amd64 if go_config_info else None
    95    arm = go_config_info.arm if go_config_info else None
    96    goos = go_toolchain.default_goos if getattr(ctx.attr, "goos", "auto") == "auto" else ctx.attr.goos
    97    goarch = go_toolchain.default_goarch if getattr(ctx.attr, "goarch", "auto") == "auto" else ctx.attr.goarch
    98    gc_goopts = go_config_info.gc_goopts if go_config_info else []
    99    pgoprofile = None
   100    if go_config_info:
   101        if len(go_config_info.pgoprofile.files.to_list()) > 2:
   102            fail("providing more than one pprof file to pgoprofile is not supported")
   103        elif len(go_config_info.pgoprofile.files.to_list()) == 1:
   104            pgoprofile = go_config_info.pgoprofile.files.to_list()[0]
   105
   106    # TODO(jayconrod): check for more invalid and contradictory settings.
   107    if pure and race:
   108        fail("race instrumentation can't be enabled when cgo is disabled. Check that pure is not set to \"off\" and a C/C++ toolchain is configured.")
   109    if pure and msan:
   110        fail("msan instrumentation can't be enabled when cgo is disabled. Check that pure is not set to \"off\" and a C/C++ toolchain is configured.")
   111    if pure and linkmode in LINKMODES_REQUIRING_EXTERNAL_LINKING:
   112        fail(("linkmode '{}' can't be used when cgo is disabled. Check that pure is not set to \"off\" and that a C/C++ toolchain is configured for " +
   113              "your current platform. If you defined a custom platform, make sure that it has the @io_bazel_rules_go//go/toolchain:cgo_on constraint value.").format(linkmode))
   114
   115    gc_linkopts = list(go_config_info.gc_linkopts) if go_config_info else []
   116    tags = list(go_config_info.tags) if go_config_info else []
   117    if "gotags" in ctx.var:
   118        tags.extend(ctx.var["gotags"].split(","))
   119    if cgo_context_info:
   120        tags.extend(cgo_context_info.tags)
   121    if race:
   122        tags.append("race")
   123    if msan:
   124        tags.append("msan")
   125
   126    return struct(
   127        static = static,
   128        race = race,
   129        msan = msan,
   130        pure = pure,
   131        link = linkmode,
   132        gc_linkopts = gc_linkopts,
   133        strip = strip,
   134        stamp = stamp,
   135        debug = debug,
   136        goos = goos,
   137        goarch = goarch,
   138        tags = tags,
   139        cover_format = cover_format,
   140        amd64 = amd64,
   141        arm = arm,
   142        gc_goopts = gc_goopts,
   143        pgoprofile = pgoprofile,
   144    )
   145
   146def installsuffix(mode):
   147    s = mode.goos + "_" + mode.goarch
   148    if mode.race:
   149        s += "_race"
   150    elif mode.msan:
   151        s += "_msan"
   152    return s
   153
   154def mode_tags_equivalent(l, r):
   155    # Returns whether two modes are equivalent for Go build tags. For example,
   156    # goos and goarch must match, but static doesn't matter.
   157    return (l.goos == r.goos and
   158            l.goarch == r.goarch and
   159            l.race == r.race and
   160            l.msan == r.msan)
   161
   162# Ported from https://github.com/golang/go/blob/master/src/cmd/go/internal/work/init.go#L76
   163_LINK_C_ARCHIVE_PLATFORMS = {
   164    "darwin/arm64": None,
   165    "ios/arm64": None,
   166}
   167
   168_LINK_C_ARCHIVE_GOOS = {
   169    "dragonfly": None,
   170    "freebsd": None,
   171    "linux": None,
   172    "netbsd": None,
   173    "openbsd": None,
   174    "solaris": None,
   175}
   176
   177_LINK_C_SHARED_GOOS = [
   178    "android",
   179    "freebsd",
   180    "linux",
   181]
   182
   183_LINK_PLUGIN_PLATFORMS = {
   184    "linux/amd64": None,
   185    "linux/arm": None,
   186    "linux/arm64": None,
   187    "linux/386": None,
   188    "linux/s390x": None,
   189    "linux/ppc64le": None,
   190    "android/amd64": None,
   191    "android/arm": None,
   192    "android/arm64": None,
   193    "android/386": None,
   194    "darwin/amd64": None,
   195    "darwin/arm64": None,
   196    "ios/arm": None,
   197    "ios/arm64": None,
   198}
   199
   200_LINK_PIE_PLATFORMS = {
   201    "linux/amd64": None,
   202    "linux/arm": None,
   203    "linux/arm64": None,
   204    "linux/386": None,
   205    "linux/s390x": None,
   206    "linux/ppc64le": None,
   207    "android/amd64": None,
   208    "android/arm": None,
   209    "android/arm64": None,
   210    "android/386": None,
   211    "freebsd/amd64": None,
   212}
   213
   214def link_mode_args(mode):
   215    # based on buildModeInit in cmd/go/internal/work/init.go
   216    platform = mode.goos + "/" + mode.goarch
   217    args = []
   218    if mode.link == LINKMODE_C_ARCHIVE:
   219        if (platform in _LINK_C_ARCHIVE_PLATFORMS or
   220            mode.goos in _LINK_C_ARCHIVE_GOOS and platform != "linux/ppc64"):
   221            args.append("-shared")
   222    elif mode.link == LINKMODE_C_SHARED:
   223        if mode.goos in _LINK_C_SHARED_GOOS:
   224            args.append("-shared")
   225    elif mode.link == LINKMODE_PLUGIN:
   226        if platform in _LINK_PLUGIN_PLATFORMS:
   227            args.append("-dynlink")
   228    elif mode.link == LINKMODE_PIE:
   229        if platform in _LINK_PIE_PLATFORMS:
   230            args.append("-shared")
   231    return args
   232
   233def extldflags_from_cc_toolchain(go):
   234    if not go.cgo_tools:
   235        return []
   236    elif go.mode.link in (LINKMODE_SHARED, LINKMODE_PLUGIN, LINKMODE_C_SHARED):
   237        return go.cgo_tools.ld_dynamic_lib_options
   238    else:
   239        # NOTE: in c-archive mode, -extldflags are ignored by the linker.
   240        # However, we still need to set them for cgo, which links a binary
   241        # in each package. We use the executable options for this.
   242        return go.cgo_tools.ld_executable_options
   243
   244def extld_from_cc_toolchain(go):
   245    if not go.cgo_tools:
   246        return []
   247    elif go.mode.link in (LINKMODE_SHARED, LINKMODE_PLUGIN, LINKMODE_C_SHARED, LINKMODE_PIE):
   248        return ["-extld", go.cgo_tools.ld_dynamic_lib_path]
   249    elif go.mode.link == LINKMODE_C_ARCHIVE:
   250        if go.mode.goos in ["darwin", "ios"]:
   251            # TODO(jayconrod): on macOS, set -extar. At this time, wrapped_ar is
   252            # a bash script without a shebang line, so we can't execute it. We
   253            # use /usr/bin/ar (the default) instead.
   254            return []
   255        else:
   256            return ["-extar", go.cgo_tools.ld_static_lib_path]
   257    else:
   258        # NOTE: In c-archive mode, we should probably set -extar. However,
   259        # on macOS, Bazel returns wrapped_ar, which is not executable.
   260        # /usr/bin/ar (the default) should be visible though, and we have a
   261        # hack in link.go to strip out non-reproducible stuff.
   262        return ["-extld", go.cgo_tools.ld_executable_path]

View as plain text