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

pantsbuild / pants / 26342152999

23 May 2026 07:59PM UTC coverage: 91.165% (-1.6%) from 92.792%
26342152999

push

github

web-flow
Run Linux ARM CI on Depot runners (#23363)

RunsOn is deprecating their v2 stack, and rather than migrate
to v3 we should use the resources kindly donated by Depot.

GitHub also now has Linux ARM runners, should we need them.

87305 of 95766 relevant lines covered (91.16%)

3.87 hits per line

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

25.93
/src/python/pants/backend/go/util_rules/cgo_pkgconfig.py
1
# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3
from __future__ import annotations
11✔
4

5
from dataclasses import dataclass
11✔
6

7
from pants.backend.go.util_rules import cgo_binaries
11✔
8
from pants.backend.go.util_rules.cgo_binaries import CGoBinaryPathRequest, find_cgo_binary_path
11✔
9
from pants.backend.go.util_rules.cgo_security import (
11✔
10
    check_compiler_flags,
11
    check_linker_flags,
12
    safe_arg,
13
)
14
from pants.core.util_rules.system_binaries import BinaryPathTest
11✔
15
from pants.engine.internals.selectors import concurrently
11✔
16
from pants.engine.process import Process, fallible_to_exec_result_or_raise
11✔
17
from pants.engine.rules import collect_rules, implicitly, rule
11✔
18

19
# Adapted from the Go toolchain
20
#
21
# Original copyright:
22
#   // Copyright 2011 The Go Authors. All rights reserved.
23
#   // Use of this source code is governed by a BSD-style
24
#   // license that can be found in the LICENSE file.
25

26

27
@dataclass(frozen=True)
11✔
28
class CGoPkgConfigFlagsRequest:
11✔
29
    """Request resolution of pkg-config arguments into CFLAGS and LDFLAGS."""
30

31
    pkg_config_args: tuple[str, ...]
11✔
32

33

34
@dataclass(frozen=True)
11✔
35
class CGoPkgConfigFlagsResult:
11✔
36
    cflags: tuple[str, ...]
11✔
37
    ldflags: tuple[str, ...]
11✔
38

39

40
# _split_pkg_config_output parses the pkg-config output into a tuple of flags. This implements the algorithm from
41
# https://github.com/pkgconf/pkgconf/blob/master/libpkgconf/argvsplit.c
42
# See https://github.com/golang/go/blob/54182ff54a687272dd7632c3a963e036ce03cb7c/src/cmd/go/internal/work/exec.go#L1414-L1473
43
def _split_pkg_config_output(content: bytes) -> tuple[str, ...]:
11✔
44
    if not content:
×
45
        return ()
×
46

47
    flags: list[str] = []
×
48
    flag = bytearray()
×
49
    escaped = False
×
50
    quote = 0
×
51
    for c in content:
×
52
        if escaped:
×
53
            if quote != 0:
×
54
                if c not in b'$`"\\':
×
55
                    flag.extend(b"\\")
×
56
                flag.append(c)
×
57
            else:
58
                flag.append(c)
×
59
            escaped = False
×
60
        elif quote != 0:
×
61
            if c == quote:
×
62
                quote = 0
×
63
            else:
64
                if c == ord("\\"):
×
65
                    escaped = True
×
66
                else:
67
                    flag.append(c)
×
68
        elif c not in b" \t\n\v\f\r":
×
69
            if c == ord(b"\\"):
×
70
                escaped = True
×
71
            elif c in b"'\"":
×
72
                quote = c
×
73
            else:
74
                flag.append(c)
×
75
        elif len(flag) != 0:
×
76
            flags.append(flag.decode())
×
77
            flag = bytearray()
×
78

79
    if escaped:
×
80
        raise ValueError("broken character escaping in pkg-config output")
×
81
    if quote != 0:
×
82
        raise ValueError("unterminated quoted string in pkgconf output")
×
83
    elif len(flag) != 0:
×
84
        flags.append(flag.decode())
×
85

86
    return tuple(flags)
×
87

88

89
@rule
11✔
90
async def resolve_cgo_pkg_config_args(request: CGoPkgConfigFlagsRequest) -> CGoPkgConfigFlagsResult:
11✔
91
    if not request.pkg_config_args:
×
92
        return CGoPkgConfigFlagsResult(cflags=(), ldflags=())
×
93

94
    pkg_config_flags = []
×
95
    pkgs = []
×
96
    for arg in request.pkg_config_args:
×
97
        if arg == "--":
×
98
            # Skip the `--` separator as we will add our own later.
99
            pass
×
100
        elif arg.startswith("--"):
×
101
            pkg_config_flags.append(arg)
×
102
        else:
103
            pkgs.append(arg)
×
104

105
    for pkg in pkgs:
×
106
        if not safe_arg(pkg):
×
107
            raise ValueError(f"invalid pkg-config package name: {pkg}")
×
108

109
    pkg_config_path = await find_cgo_binary_path(
×
110
        CGoBinaryPathRequest(
111
            binary_name="pkg-config",
112
            binary_path_test=BinaryPathTest(["--version"]),
113
        ),
114
        **implicitly(),
115
    )
116

117
    cflags_result, ldflags_result = await concurrently(
×
118
        fallible_to_exec_result_or_raise(
119
            **implicitly(
120
                Process(
121
                    argv=[pkg_config_path.path, "--cflags", *pkg_config_flags, "--", *pkgs],
122
                    description=f"Run pkg-config for CFLAGS for packages: {pkgs}",
123
                )
124
            )
125
        ),
126
        fallible_to_exec_result_or_raise(
127
            **implicitly(
128
                Process(
129
                    argv=[pkg_config_path.path, "--libs", *pkg_config_flags, "--", *pkgs],
130
                    description=f"Run pkg-config for LDFLAGS for packages: {pkgs}",
131
                )
132
            )
133
        ),
134
    )
135

136
    cflags: tuple[str, ...] = ()
×
137
    if cflags_result.stdout:
×
138
        cflags = _split_pkg_config_output(cflags_result.stdout)
×
139
        check_compiler_flags(cflags, "pkg-config --cflags")
×
140

141
    ldflags: tuple[str, ...] = ()
×
142
    if ldflags_result.stdout:
×
143
        # NOTE: we don't attempt to parse quotes and unescapes here. pkg-config
144
        # is typically used within shell backticks, which treats quotes literally.
145
        ldflags = tuple(arg.decode() for arg in ldflags_result.stdout.split())
×
146
        check_linker_flags(ldflags, "pkg-config --libs")
×
147

148
    return CGoPkgConfigFlagsResult(cflags=cflags, ldflags=ldflags)
×
149

150

151
def rules():
11✔
152
    return (
11✔
153
        *collect_rules(),
154
        *cgo_binaries.rules(),
155
    )
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