• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 19015773527

02 Nov 2025 05:33PM UTC coverage: 17.872% (-62.4%) from 80.3%
19015773527

Pull #22816

github

web-flow
Merge a12d75757 into 6c024e162
Pull Request #22816: Update Pants internal Python to 3.14

4 of 5 new or added lines in 3 files covered. (80.0%)

28452 existing lines in 683 files now uncovered.

9831 of 55007 relevant lines covered (17.87%)

0.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/python/pants/backend/go/util_rules/assembly.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

UNCOV
4
from __future__ import annotations
×
5

UNCOV
6
import os.path
×
UNCOV
7
from collections.abc import Iterable
×
UNCOV
8
from dataclasses import dataclass
×
UNCOV
9
from pathlib import PurePath
×
10

UNCOV
11
from pants.backend.go.util_rules.goroot import GoRoot
×
UNCOV
12
from pants.backend.go.util_rules.sdk import GoSdkProcess, GoSdkToolIDRequest, compute_go_tool_id
×
UNCOV
13
from pants.engine.fs import CreateDigest, Digest, FileContent, MergeDigests
×
UNCOV
14
from pants.engine.intrinsics import create_digest, execute_process, merge_digests
×
UNCOV
15
from pants.engine.rules import collect_rules, concurrently, implicitly, rule
×
16

17

UNCOV
18
@dataclass(frozen=True)
×
UNCOV
19
class GenerateAssemblySymabisRequest:
×
20
    """Generate a `symabis` file with metadata about the assembly files for consumption by Go
21
    compiler.
22

23
    See https://github.com/bazelbuild/rules_go/issues/1893.
24
    """
25

UNCOV
26
    compilation_input: Digest
×
UNCOV
27
    s_files: tuple[str, ...]
×
UNCOV
28
    import_path: str
×
UNCOV
29
    dir_path: str
×
UNCOV
30
    extra_assembler_flags: tuple[str, ...]
×
31

32

UNCOV
33
@dataclass(frozen=True)
×
UNCOV
34
class GenerateAssemblySymabisResult:
×
UNCOV
35
    symabis_digest: Digest
×
UNCOV
36
    symabis_path: str
×
37

38

UNCOV
39
@dataclass(frozen=True)
×
UNCOV
40
class FallibleGenerateAssemblySymabisResult:
×
UNCOV
41
    result: GenerateAssemblySymabisResult | None
×
UNCOV
42
    exit_code: int = 0
×
UNCOV
43
    stdout: str | None = None
×
UNCOV
44
    stderr: str | None = None
×
45

46

UNCOV
47
@dataclass(frozen=True)
×
UNCOV
48
class AssembleGoAssemblyFilesRequest:
×
49
    """Assemble Go assembly files to object files."""
50

UNCOV
51
    input_digest: Digest
×
UNCOV
52
    s_files: tuple[str, ...]
×
UNCOV
53
    dir_path: str
×
UNCOV
54
    import_path: str
×
UNCOV
55
    extra_assembler_flags: tuple[str, ...]
×
56

57

UNCOV
58
@dataclass(frozen=True)
×
UNCOV
59
class AssembleGoAssemblyFilesResult:
×
UNCOV
60
    assembly_outputs: tuple[tuple[str, Digest], ...]
×
61

62

UNCOV
63
@dataclass(frozen=True)
×
UNCOV
64
class FallibleAssembleGoAssemblyFilesResult:
×
UNCOV
65
    result: AssembleGoAssemblyFilesResult | None
×
UNCOV
66
    exit_code: int = 0
×
UNCOV
67
    stdout: str | None = None
×
UNCOV
68
    stderr: str | None = None
×
69

70

71
# Adapted from https://github.com/golang/go/blob/cb07765045aed5104a3df31507564ac99e6ddce8/src/cmd/go/internal/work/gc.go#L358-L410
72
#
73
# Note: Architecture-specific flags have not been adapted nor the flags added when compiling Go SDK packages
74
# themselves.
UNCOV
75
def _asm_args(
×
76
    import_path: str, dir_path: str, goroot: GoRoot, extra_flags: Iterable[str]
77
) -> tuple[str, ...]:
78
    # On Go 1.19+, the import path must be supplied via the `-p` option to `go tool asm`.
79
    # See https://go.dev/doc/go1.19#assembler and
80
    # https://github.com/bazelbuild/rules_go/commit/cde7d7bc27a34547c014369790ddaa95b932d08d (Bazel rules_go).
81
    maybe_package_import_path_args = (
×
82
        ["-p", import_path] if goroot.is_compatible_version("1.19") else []
83
    )
84

85
    # Add special argument if assembling files in certain packages in the standard library.
86
    # See:
87
    # - https://github.com/golang/go/blob/245e95dfabd77f337373bf2d6bb47cd353ad8d74/src/cmd/go/internal/work/gc.go#L370-L372
88
    # - https://github.com/golang/go/blob/245e95dfabd77f337373bf2d6bb47cd353ad8d74/src/cmd/internal/objabi/path.go#L43-L67
89
    # From Go 1.22+ this flag has been removed, since we're already passing the package path, asm can make that determination,
90
    # and there's no need to pass the flag anymore.
91
    # See:
92
    # - https://cs.opensource.google/go/go/+/72946ae8674a295e7485982fe57c65c7142b2c14
93
    maybe_assembling_stdlib_runtime_args = (
×
94
        ["-compiling-runtime"]
95
        if not goroot.is_compatible_version("1.22")
96
        and (
97
            import_path in ("runtime", "reflect", "syscall", "internal/bytealg")
98
            or import_path.startswith("runtime/internal")
99
        )
100
        else []
101
    )
102

103
    return (
×
104
        *maybe_package_import_path_args,
105
        "-trimpath",
106
        "__PANTS_SANDBOX_ROOT__",
107
        "-I",
108
        f"__PANTS_SANDBOX_ROOT__/{dir_path}",
109
        # Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
110
        "-I",
111
        os.path.join(goroot.path, "pkg", "include"),
112
        "-D",
113
        f"GOOS_{goroot.goos}",
114
        "-D",
115
        f"GOARCH_{goroot.goarch}",
116
        *maybe_assembling_stdlib_runtime_args,
117
        *extra_flags,
118
    )
119

120

UNCOV
121
@rule
×
UNCOV
122
async def generate_go_assembly_symabisfile(
×
123
    request: GenerateAssemblySymabisRequest,
124
    goroot: GoRoot,
125
) -> FallibleGenerateAssemblySymabisResult:
126
    # From Go tooling comments:
127
    #
128
    #   Supply an empty go_asm.h as if the compiler had been run. -symabis parsing is lax enough
129
    #   that we don't need the actual definitions that would appear in go_asm.h.
130
    #
131
    # See https://go-review.googlesource.com/c/go/+/146999/8/src/cmd/go/internal/work/gc.go
132
    if os.path.isabs(request.dir_path):
×
133
        symabis_path = "symabis"
×
134
    else:
135
        symabis_path = os.path.join(request.dir_path, "symabis")
×
136
    go_asm_h_digest, asm_tool_id = await concurrently(
×
137
        create_digest(CreateDigest([FileContent("go_asm.h", b"")])),
138
        compute_go_tool_id(GoSdkToolIDRequest("asm")),
139
    )
140
    symabis_input_digest = await merge_digests(
×
141
        MergeDigests([request.compilation_input, go_asm_h_digest])
142
    )
143
    symabis_result = await execute_process(
×
144
        **implicitly(
145
            GoSdkProcess(
146
                input_digest=symabis_input_digest,
147
                command=(
148
                    "tool",
149
                    "asm",
150
                    *_asm_args(
151
                        import_path=request.import_path,
152
                        dir_path=request.dir_path,
153
                        goroot=goroot,
154
                        extra_flags=request.extra_assembler_flags,
155
                    ),
156
                    "-gensymabis",
157
                    "-o",
158
                    symabis_path,
159
                    "--",
160
                    *(str(PurePath(request.dir_path, s_file)) for s_file in request.s_files),
161
                ),
162
                env={
163
                    "__PANTS_GO_ASM_TOOL_ID": asm_tool_id.tool_id,
164
                },
165
                description=f"Generate symabis metadata for assembly files for {request.dir_path}",
166
                output_files=(symabis_path,),
167
                replace_sandbox_root_in_args=True,
168
            )
169
        )
170
    )
171
    if symabis_result.exit_code != 0:
×
172
        return FallibleGenerateAssemblySymabisResult(
×
173
            None, symabis_result.exit_code, symabis_result.stderr.decode("utf-8")
174
        )
175

176
    return FallibleGenerateAssemblySymabisResult(
×
177
        result=GenerateAssemblySymabisResult(
178
            symabis_digest=symabis_result.output_digest,
179
            symabis_path=symabis_path,
180
        ),
181
    )
182

183

UNCOV
184
@rule
×
UNCOV
185
async def assemble_go_assembly_files(
×
186
    request: AssembleGoAssemblyFilesRequest,
187
    goroot: GoRoot,
188
) -> FallibleAssembleGoAssemblyFilesResult:
189
    asm_tool_id = await compute_go_tool_id(GoSdkToolIDRequest("asm"))
×
190

191
    def obj_output_path(s_file: str) -> str:
×
192
        if os.path.isabs(request.dir_path):
×
193
            return str(PurePath(s_file).with_suffix(".o"))
×
194
        else:
195
            return str(request.dir_path / PurePath(s_file).with_suffix(".o"))
×
196

197
    assembly_results = await concurrently(
×
198
        execute_process(
199
            **implicitly(
200
                GoSdkProcess(
201
                    input_digest=request.input_digest,
202
                    command=(
203
                        "tool",
204
                        "asm",
205
                        *_asm_args(
206
                            import_path=request.import_path,
207
                            dir_path=request.dir_path,
208
                            goroot=goroot,
209
                            extra_flags=request.extra_assembler_flags,
210
                        ),
211
                        "-o",
212
                        obj_output_path(s_file),
213
                        str(os.path.normpath(PurePath(request.dir_path, s_file))),
214
                    ),
215
                    env={
216
                        "__PANTS_GO_ASM_TOOL_ID": asm_tool_id.tool_id,
217
                    },
218
                    description=f"Assemble {s_file} with Go",
219
                    output_files=(obj_output_path(s_file),),
220
                    replace_sandbox_root_in_args=True,
221
                )
222
            ),
223
        )
224
        for s_file in request.s_files
225
    )
226
    exit_code = max(result.exit_code for result in assembly_results)
×
227
    if exit_code != 0:
×
228
        stdout = "\n\n".join(
×
229
            result.stdout.decode("utf-8") for result in assembly_results if result.stdout
230
        )
231
        stderr = "\n\n".join(
×
232
            result.stderr.decode("utf-8") for result in assembly_results if result.stderr
233
        )
234
        return FallibleAssembleGoAssemblyFilesResult(None, exit_code, stdout, stderr)
×
235

236
    assembly_outputs = tuple(
×
237
        (obj_output_path(s_file), result.output_digest)
238
        for s_file, result in zip(request.s_files, assembly_results)
239
    )
240

241
    return FallibleAssembleGoAssemblyFilesResult(
×
242
        AssembleGoAssemblyFilesResult(
243
            assembly_outputs=assembly_outputs,
244
        )
245
    )
246

247

UNCOV
248
def rules():
×
UNCOV
249
    return collect_rules()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc