Skip to content

Commit

Permalink
go: introduce _go_sdk and _go_sdk_package target types for SDK analys…
Browse files Browse the repository at this point in the history
…is (pantsbuild#17973)

Introduce the `_go_sdk` and `_go_sdk_package` target types to allow the build graph to represent the structure of a Go SDK.

- The `_go_sdk` target type is used to create a synthetic target `//:default_go_sdk` to represent the Go SDK found using the `[golang].go_search_paths` option. This target type is a target generator and generates a `_go_sdk_package` target for each SDK package.
  * This target type could be made visible to users in the future if we decide to support multiple Go SDKs in a repository, but for now it is an implementation detail to provide a place to use target generation when analyzing the Go SDK. 
- The `_go_sdk_package` target type is used as the target type for each target representing a SDK package.

This is part of fixing pantsbuild#17950 and was extracted from pantsbuild#17914.
  • Loading branch information
tdyas authored Jan 12, 2023
1 parent 361be6d commit 217c39c
Show file tree
Hide file tree
Showing 22 changed files with 311 additions and 40 deletions.
11 changes: 11 additions & 0 deletions src/python/pants/backend/codegen/protobuf/go/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
)
from pants.backend.go.util_rules.first_party_pkg import FallibleFirstPartyPkgAnalysis
from pants.backend.go.util_rules.go_mod import OwningGoMod, OwningGoModRequest
from pants.backend.go.util_rules.import_analysis import GoStdLibPackages, GoStdLibPackagesRequest
from pants.backend.go.util_rules.pkg_analyzer import PackageAnalyzerSetup
from pants.backend.go.util_rules.sdk import GoSdkProcess
from pants.backend.python.util_rules import pex
Expand Down Expand Up @@ -352,10 +353,20 @@ async def setup_full_package_build_request(
)
analysis = fallible_analysis.analysis

stdlib_packages = await Get(
GoStdLibPackages,
GoStdLibPackagesRequest(with_race_detector=request.build_opts.with_race_detector),
)

# Obtain build requests for third-party dependencies.
# TODO: Consider how to merge this code with existing dependency inference code.
dep_build_request_addrs: list[Address] = []
for dep_import_path in (*analysis.imports, *analysis.test_imports, *analysis.xtest_imports):
# Skip inference for stdlib packages.
# TODO: This check is deprecated and will be removed once support for building SDK packages lands.
if dep_import_path in stdlib_packages:
continue

# Infer dependencies on other Go packages.
candidate_addresses = package_mapping.mapping.get(dep_import_path)
if candidate_addresses:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from pants.backend.go import target_type_rules
from pants.backend.go.goals import test
from pants.backend.go.goals.test import GoTestFieldSet, GoTestRequest
from pants.backend.go.target_types import GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand Down Expand Up @@ -79,6 +79,7 @@ def rule_runner() -> RuleRunner:
target_types=[
GoModTarget,
GoPackageTarget,
GoSdkTarget,
ProtobufSourceTarget,
ProtobufSourcesGeneratorTarget,
],
Expand Down
4 changes: 4 additions & 0 deletions src/python/pants/backend/experimental/go/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
GoModTarget,
GoPackageSourcesField,
GoPackageTarget,
GoSdkPackageTarget,
GoSdkTarget,
GoThirdPartyPackageTarget,
)
from pants.backend.go.util_rules import (
Expand Down Expand Up @@ -45,6 +47,8 @@ def target_types():
GoThirdPartyPackageTarget,
GoBinaryTarget,
*wrap_golang.target_types,
GoSdkTarget,
GoSdkPackageTarget,
]


Expand Down
4 changes: 2 additions & 2 deletions src/python/pants/backend/go/dependency_inference_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pants.backend.go import target_type_rules
from pants.backend.go.goals.test import GoTestFieldSet, GoTestRequest
from pants.backend.go.goals.test import rules as test_rules
from pants.backend.go.target_types import GoBinaryTarget, GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoBinaryTarget, GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand Down Expand Up @@ -50,7 +50,7 @@ def rule_runner() -> RuleRunner:
QueryRule(TestResult, (GoTestRequest.Batch,)),
QueryRule(ProcessResult, (GoSdkProcess,)),
],
target_types=[GoModTarget, GoPackageTarget, GoBinaryTarget],
target_types=[GoModTarget, GoPackageTarget, GoBinaryTarget, GoSdkTarget],
)
rule_runner.set_options(["--go-test-args=-v"], env_inherit={"PATH"})
return rule_runner
Expand Down
4 changes: 2 additions & 2 deletions src/python/pants/backend/go/goals/check_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pants.backend.go import target_type_rules
from pants.backend.go.goals import check
from pants.backend.go.goals.check import GoCheckFieldSet, GoCheckRequest
from pants.backend.go.target_types import GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand Down Expand Up @@ -44,7 +44,7 @@ def rule_runner() -> RuleRunner:
*target_type_rules.rules(),
QueryRule(CheckResults, [GoCheckRequest]),
],
target_types=[GoModTarget, GoPackageTarget],
target_types=[GoModTarget, GoPackageTarget, GoSdkTarget],
)
rule_runner.set_options([], env_inherit={"PATH"})
return rule_runner
Expand Down
4 changes: 2 additions & 2 deletions src/python/pants/backend/go/goals/generate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pants.backend.go import target_type_rules
from pants.backend.go.goals import generate
from pants.backend.go.goals.generate import GoGenerateGoal, OverwriteMergeDigests, _expand_env
from pants.backend.go.target_types import GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand Down Expand Up @@ -50,7 +50,7 @@ def rule_runner() -> RuleRunner:
get_filtered_environment,
QueryRule(DigestContents, (OverwriteMergeDigests,)),
],
target_types=[GoModTarget, GoPackageTarget],
target_types=[GoModTarget, GoPackageTarget, GoSdkTarget],
preserve_tmpdirs=True,
)
rule_runner.set_options([], env_inherit=PYTHON_BOOTSTRAP_ENV)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pants.backend.go import target_type_rules
from pants.backend.go.goals import package_binary
from pants.backend.go.goals.package_binary import GoBinaryFieldSet
from pants.backend.go.target_types import GoBinaryTarget, GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoBinaryTarget, GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand Down Expand Up @@ -48,7 +48,12 @@ def rule_runner() -> RuleRunner:
*sdk.rules(),
QueryRule(BuiltPackage, (GoBinaryFieldSet,)),
],
target_types=[GoBinaryTarget, GoModTarget, GoPackageTarget],
target_types=[
GoBinaryTarget,
GoModTarget,
GoPackageTarget,
GoSdkTarget,
],
)
rule_runner.set_options([], env_inherit={"PATH"})
return rule_runner
Expand Down
9 changes: 7 additions & 2 deletions src/python/pants/backend/go/goals/tailor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
has_package_main,
)
from pants.backend.go.goals.tailor import rules as go_tailor_rules
from pants.backend.go.target_types import GoBinaryTarget, GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoBinaryTarget, GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand Down Expand Up @@ -46,7 +46,12 @@ def rule_runner() -> RuleRunner:
*link.rules(),
QueryRule(PutativeTargets, [PutativeGoTargetsRequest, AllOwnedSources]),
],
target_types=[GoModTarget, GoBinaryTarget, GoPackageTarget],
target_types=[
GoModTarget,
GoBinaryTarget,
GoPackageTarget,
GoSdkTarget,
],
)
rule_runner.set_options([], env_inherit={"PATH"})
return rule_runner
Expand Down
4 changes: 2 additions & 2 deletions src/python/pants/backend/go/goals/test_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pants.backend.go.goals.test import GoTestFieldSet, GoTestRequest
from pants.backend.go.goals.test import rules as test_rules
from pants.backend.go.goals.test import transform_test_args
from pants.backend.go.target_types import GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand Down Expand Up @@ -52,7 +52,7 @@ def rule_runner() -> RuleRunner:
QueryRule(TestResult, [GoTestRequest.Batch]),
QueryRule(ProcessResult, [GoSdkProcess]),
],
target_types=[GoModTarget, GoPackageTarget, FileTarget],
target_types=[GoModTarget, GoPackageTarget, GoSdkTarget, FileTarget],
)
rule_runner.set_options(["--go-test-args=-v -bench=."], env_inherit={"PATH"})
return rule_runner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pants.backend.go.lint.golangci_lint.rules import GolangciLintFieldSet, GolangciLintRequest
from pants.backend.go.lint.golangci_lint.rules import rules as golangci_lint_rules
from pants.backend.go.lint.golangci_lint.subsystem import GolangciLint
from pants.backend.go.target_types import GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand All @@ -35,7 +35,7 @@
@pytest.fixture()
def rule_runner() -> RuleRunner:
rule_runner = RuleRunner(
target_types=[GoModTarget, GoPackageTarget],
target_types=[GoModTarget, GoPackageTarget, GoSdkTarget],
rules=[
*assembly.rules(),
*build_pkg.rules(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pants.backend.go.lint.vet.rules import GoVetFieldSet, GoVetRequest
from pants.backend.go.lint.vet.rules import rules as go_vet_rules
from pants.backend.go.lint.vet.subsystem import GoVetSubsystem
from pants.backend.go.target_types import GoModTarget, GoPackageTarget
from pants.backend.go.target_types import GoModTarget, GoPackageTarget, GoSdkTarget
from pants.backend.go.util_rules import (
assembly,
build_pkg,
Expand All @@ -36,7 +36,7 @@
@pytest.fixture()
def rule_runner() -> RuleRunner:
rule_runner = RuleRunner(
target_types=[GoModTarget, GoPackageTarget],
target_types=[GoModTarget, GoPackageTarget, GoSdkTarget],
rules=[
*skip_field.rules(),
*go_vet_rules(),
Expand Down
100 changes: 93 additions & 7 deletions src/python/pants/backend/go/target_type_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
GoModuleImportPathsMappingsHook,
)
from pants.backend.go.target_types import (
DEFAULT_GO_SDK_ADDR,
GoImportPathField,
GoModSourcesField,
GoModTarget,
GoPackageSourcesField,
GoSdkImportPathField,
GoSdkPackageTarget,
GoSdkTarget,
GoThirdPartyPackageDependenciesField,
GoThirdPartyPackageTarget,
)
Expand All @@ -36,7 +40,11 @@
OwningGoMod,
OwningGoModRequest,
)
from pants.backend.go.util_rules.import_analysis import GoStdLibPackages, GoStdLibPackagesRequest
from pants.backend.go.util_rules.import_analysis import (
GoStdLibPackage,
GoStdLibPackages,
GoStdLibPackagesRequest,
)
from pants.backend.go.util_rules.third_party_pkg import (
AllThirdPartyPackages,
AllThirdPartyPackagesRequest,
Expand All @@ -50,6 +58,8 @@
from pants.engine.addresses import Address
from pants.engine.engine_aware import EngineAwareParameter
from pants.engine.fs import Digest, Snapshot
from pants.engine.internals.synthetic_targets import SyntheticAddressMaps, SyntheticTargetsRequest
from pants.engine.internals.target_adaptor import TargetAdaptor
from pants.engine.rules import Get, MultiGet, collect_rules, rule
from pants.engine.target import (
AllTargets,
Expand Down Expand Up @@ -91,7 +101,8 @@ async def go_map_import_paths_by_module(
candidate_go_source_targets = [
tgt
for tgt in all_targets
if tgt.has_field(GoImportPathField) or tgt.has_field(GoPackageSourcesField)
if (tgt.has_field(GoImportPathField) or tgt.has_field(GoPackageSourcesField))
and not tgt.has_field(GoSdkImportPathField)
]

owning_go_mod_targets = await MultiGet(
Expand Down Expand Up @@ -225,7 +236,7 @@ async def infer_go_dependencies(
)

addr = request.field_set.address
maybe_pkg_analysis, std_lib_imports = await MultiGet(
maybe_pkg_analysis, stdlib_packages = await MultiGet(
Get(
FallibleFirstPartyPkgAnalysis, FirstPartyPkgAnalysisRequest(addr, build_opts=build_opts)
),
Expand All @@ -249,7 +260,9 @@ async def infer_go_dependencies(
*pkg_analysis.test_imports,
*pkg_analysis.xtest_imports,
):
if import_path in std_lib_imports:
# Skip inference for stdlib packages.
# TODO: This check is deprecated and will be removed once support for building SDK packages lands.
if import_path in stdlib_packages:
continue
# Avoid a dependency cycle caused by external test imports of this package (i.e., "xtest").
if import_path == pkg_analysis.import_path:
Expand Down Expand Up @@ -305,7 +318,7 @@ async def infer_go_third_party_package_dependencies(
Get(GoBuildOptions, GoBuildOptionsFromTargetRequest(go_mod_address)),
)

pkg_info, std_lib_imports = await MultiGet(
pkg_info, stdlib_packages = await MultiGet(
Get(
ThirdPartyPkgAnalysis,
ThirdPartyPkgAnalysisRequest(
Expand All @@ -324,9 +337,10 @@ async def infer_go_third_party_package_dependencies(

inferred_dependencies: list[Address] = []
for import_path in pkg_info.imports:
if import_path in std_lib_imports:
# Skip inference for stdlib packages.
# TODO: This check is deprecated and will be removed once support for building SDK packages lands.
if import_path in stdlib_packages:
continue

candidate_packages = package_mapping.mapping.get(import_path, ())
if candidate_packages:
if candidate_packages.infer_all:
Expand Down Expand Up @@ -414,6 +428,76 @@ def create_tgt(pkg_info: ThirdPartyPkgAnalysis) -> GoThirdPartyPackageTarget:
return GeneratedTargets(request.generator, result)


# -----------------------------------------------------------------------------------------------
# `go_sdk` and `go_sdk_package` target types
# -----------------------------------------------------------------------------------------------


@dataclass(frozen=True)
class GoSdkSyntheticTargetsRequest(SyntheticTargetsRequest):
path: str = SyntheticTargetsRequest.SINGLE_REQUEST_FOR_ALL_TARGETS


@rule
async def generate_go_sdk_synthetic_targets(
request: GoSdkSyntheticTargetsRequest,
) -> SyntheticAddressMaps:
return SyntheticAddressMaps.for_targets_request(
request,
[
(
"BUILD._go_sdk",
[TargetAdaptor(GoSdkTarget.alias, name=DEFAULT_GO_SDK_ADDR.target_name)],
)
],
)


class GenerateTargetsFromGoSdkRequest(GenerateTargetsRequest):
generate_from = GoSdkTarget


@rule(desc="Generate `_go_sdk_package` targets from `_go_sdk` target", level=LogLevel.DEBUG)
async def generate_targets_from_go_sdk(
request: GenerateTargetsFromGoSdkRequest,
union_membership: UnionMembership,
) -> GeneratedTargets:
generator_addr = request.generator.address

stdlib_packages, stdlib_packages_race = await MultiGet(
Get(
GoStdLibPackages,
GoStdLibPackagesRequest(with_race_detector=False),
),
Get(
GoStdLibPackages,
GoStdLibPackagesRequest(with_race_detector=True),
),
)

def create_tgt(pkg: GoStdLibPackage) -> GoSdkPackageTarget:
dep_import_paths = sorted(
{*pkg.imports, *stdlib_packages_race[pkg.import_path].imports} - {"C", "unsafe"}
)
return GoSdkPackageTarget(
{
**request.template,
GoSdkImportPathField.alias: pkg.import_path,
Dependencies.alias: [
generator_addr.create_generated(dep_import_path).spec
for dep_import_path in dep_import_paths
],
},
# E.g. `//:default_go_sdk#net/http`.
generator_addr.create_generated(pkg.import_path),
union_membership,
residence_dir=generator_addr.spec_path,
)

result = tuple(create_tgt(pkg_info) for pkg_info in stdlib_packages.values())
return GeneratedTargets(request.generator, result)


def rules():
return (
*collect_rules(),
Expand All @@ -423,5 +507,7 @@ def rules():
UnionRule(InferDependenciesRequest, InferGoPackageDependenciesRequest),
UnionRule(InferDependenciesRequest, InferGoThirdPartyPackageDependenciesRequest),
UnionRule(GenerateTargetsRequest, GenerateTargetsFromGoModRequest),
UnionRule(GenerateTargetsRequest, GenerateTargetsFromGoSdkRequest),
UnionRule(GoModuleImportPathsMappingsHook, FirstPartyGoModuleImportPathsMappingsHook),
UnionRule(SyntheticTargetsRequest, GoSdkSyntheticTargetsRequest),
)
Loading

0 comments on commit 217c39c

Please sign in to comment.