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

pantsbuild / pants / 25443604553

06 May 2026 03:05PM UTC coverage: 92.879% (-0.04%) from 92.915%
25443604553

push

github

web-flow
[pants_ng] Scaffolding for a pants_ng mode. (#23319)

In this mode the command line is parsed as an
NG invocation, and dispatched appropriately.

Of course at the moment there are no
implementations to dispatch to. That will follow.

This does expose a new option, `pants_ng` to users. 
There is a big warning not to set it, but we're not trying
to hide that we're working on a new thing, so I am
comfortable with this.

25 of 76 new or added lines in 9 files covered. (32.89%)

1294 existing lines in 76 files now uncovered.

92234 of 99306 relevant lines covered (92.88%)

4.05 hits per line

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

96.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

4
from __future__ import annotations
11✔
5

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

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

17

18
@dataclass(frozen=True)
11✔
19
class GenerateAssemblySymabisRequest:
11✔
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

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

32

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

38

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

46

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

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

57

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

62

63
@dataclass(frozen=True)
11✔
64
class FallibleAssembleGoAssemblyFilesResult:
11✔
65
    result: AssembleGoAssemblyFilesResult | None
11✔
66
    exit_code: int = 0
11✔
67
    stdout: str | None = None
11✔
68
    stderr: str | None = None
11✔
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.
75
def _asm_args(
11✔
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 = (
10✔
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 = (
10✔
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 (
10✔
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

121
@rule
11✔
122
async def generate_go_assembly_symabisfile(
11✔
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):
10✔
133
        symabis_path = "symabis"
10✔
134
    else:
UNCOV
135
        symabis_path = os.path.join(request.dir_path, "symabis")
1✔
136
    go_asm_h_digest, asm_tool_id = await concurrently(
10✔
137
        create_digest(CreateDigest([FileContent("go_asm.h", b"")])),
138
        compute_go_tool_id(GoSdkToolIDRequest("asm")),
139
    )
140
    symabis_input_digest = await merge_digests(
10✔
141
        MergeDigests([request.compilation_input, go_asm_h_digest])
142
    )
143
    symabis_result = await execute_process(
10✔
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:
10✔
UNCOV
172
        return FallibleGenerateAssemblySymabisResult(
1✔
173
            None, symabis_result.exit_code, symabis_result.stderr.decode("utf-8")
174
        )
175

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

183

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

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

197
    assembly_results = await concurrently(
10✔
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)
10✔
227
    if exit_code != 0:
10✔
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(
10✔
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(
10✔
242
        AssembleGoAssemblyFilesResult(
243
            assembly_outputs=assembly_outputs,
244
        )
245
    )
246

247

248
def rules():
11✔
249
    return collect_rules()
11✔
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

© 2026 Coveralls, Inc