示例#1
0
    def classify(
        targets: Sequence[Target],
        members: Sequence[type[ClasspathEntryRequest]],
        generators: FrozenDict[type[ClasspathEntryRequest], frozenset[type[SourcesField]]],
    ) -> tuple[type[ClasspathEntryRequest], type[ClasspathEntryRequest] | None]:

        factory = ClasspathEntryRequestFactory(tuple(members), generators)

        req = factory.for_targets(
            CoarsenedTarget(targets, ()),
            CoursierResolveKey("example", "path", EMPTY_DIGEST),
        )
        return (type(req), type(req.prerequisite) if req.prerequisite else None)
示例#2
0
async def kotlinc_check(
    request: KotlincCheckRequest,
    classpath_entry_request: ClasspathEntryRequestFactory,
) -> CheckResults:
    coarsened_targets = await Get(
        CoarsenedTargets, Addresses(field_set.address for field_set in request.field_sets)
    )

    # NB: Each root can have an independent resolve, because there is no inherent relation
    # between them other than that they were on the commandline together.
    resolves = await MultiGet(
        Get(CoursierResolveKey, CoarsenedTargets([t])) for t in coarsened_targets
    )

    results = await MultiGet(
        Get(
            FallibleClasspathEntry,
            ClasspathEntryRequest,
            classpath_entry_request.for_targets(component=target, resolve=resolve),
        )
        for target, resolve in zip(coarsened_targets, resolves)
    )

    # NB: We don't pass stdout/stderr as it will have already been rendered as streaming.
    exit_code = next((result.exit_code for result in results if result.exit_code != 0), 0)
    return CheckResults([CheckResult(exit_code, "", "")], checker_name=request.name)
示例#3
0
async def bsp_scala_compile_request(
    request: ScalaBSPCompileFieldSet,
    classpath_entry_request: ClasspathEntryRequestFactory,
) -> BSPCompileResult:
    coarsened_targets = await Get(CoarsenedTargets,
                                  Addresses([request.source.address]))
    assert len(coarsened_targets) == 1
    coarsened_target = coarsened_targets[0]
    resolve = await Get(CoursierResolveKey,
                        CoarsenedTargets([coarsened_target]))

    result = await Get(
        FallibleClasspathEntry,
        ClasspathEntryRequest,
        classpath_entry_request.for_targets(component=coarsened_target,
                                            resolve=resolve),
    )
    _logger.info(f"scala compile result = {result}")
    output_digest = EMPTY_DIGEST
    if result.exit_code == 0 and result.output:
        entries = await Get(DigestEntries, Digest, result.output.digest)
        new_entires = [
            dataclasses.replace(entry, path=os.path.basename(entry.path))
            for entry in entries
        ]
        flat_digest = await Get(Digest, CreateDigest(new_entires))
        output_digest = await Get(
            Digest, AddPrefix(flat_digest, f"jvm/resolves/{resolve.name}/lib"))

    return BSPCompileResult(
        status=StatusCode.ERROR if result.exit_code != 0 else StatusCode.OK,
        output_digest=output_digest,
    )
示例#4
0
async def _jvm_bsp_compile(
        request: BSPCompileRequest,
        classpath_entry_request: ClasspathEntryRequestFactory
) -> BSPCompileResult:
    """Generically handles a BSPCompileRequest (subclass).

    This is a `@rule_helper` rather than a `@rule`, because BSP backends like `java` and `scala`
    independently declare their `BSPCompileRequest` union members. We can't register a single shared
    `BSPCompileRequest` @union member for all JVM because their FieldSets are also declared via
    @unions, and we can't forward the implementation of a @union to another the way we might with
    an abstract class.
    """
    coarsened_targets = await Get(
        CoarsenedTargets, Addresses([fs.address for fs in request.field_sets]))
    resolve = await Get(CoursierResolveKey, CoarsenedTargets,
                        coarsened_targets)

    # TODO: We include the (non-3rdparty) transitive dependencies here, because each project
    # currently only has a single BuildTarget. This has the effect of including `resources` targets,
    # which are referenced by BuildTargets (via `buildTarget/resources`), rather than necessarily
    # being owned by any particular BuildTarget.
    #
    # To resolve #15051, this will no longer be transitive, and so `resources` will need to be
    # attached-to/referenced-by nearby BuildTarget(s) instead (most likely: direct dependent(s)).
    results = await MultiGet(
        Get(
            FallibleClasspathEntry,
            BSPClasspathEntryRequest(
                classpath_entry_request.for_targets(component=coarsened_target,
                                                    resolve=resolve),
                task_id=request.task_id,
            ),
        ) for coarsened_target in coarsened_targets.coarsened_closure()
        if not any(
            JvmArtifactFieldSet.is_applicable(t)
            for t in coarsened_target.members))

    entries = FallibleClasspathEntry.if_all_succeeded(results)
    if entries is None:
        return BSPCompileResult(
            status=StatusCode.ERROR,
            output_digest=EMPTY_DIGEST,
        )

    loose_classfiles = await MultiGet(
        Get(LooseClassfiles, ClasspathEntry, entry) for entry in entries)
    merged_loose_classfiles = await Get(
        Digest, MergeDigests(lc.digest for lc in loose_classfiles))
    output_digest = await Get(
        Digest,
        AddPrefix(merged_loose_classfiles,
                  jvm_classes_directory(request.bsp_target.bsp_target_id)),
    )

    return BSPCompileResult(
        status=StatusCode.OK,
        output_digest=output_digest,
    )
示例#5
0
async def collect_thirdparty_modules(
    request: ThirdpartyModulesRequest,
    classpath_entry_request: ClasspathEntryRequestFactory,
) -> ThirdpartyModules:
    coarsened_targets = await Get(CoarsenedTargets, Addresses,
                                  request.addresses)
    resolve = await Get(CoursierResolveKey, CoarsenedTargets,
                        coarsened_targets)
    lockfile = await Get(CoursierResolvedLockfile, CoursierResolveKey, resolve)

    applicable_lockfile_entries: dict[CoursierLockfileEntry,
                                      CoarsenedTarget] = {}
    for ct in coarsened_targets.coarsened_closure():
        for tgt in ct.members:
            if not JvmArtifactFieldSet.is_applicable(tgt):
                continue

            artifact_requirement = ArtifactRequirement.from_jvm_artifact_target(
                tgt)
            entry = get_entry_for_coord(lockfile,
                                        artifact_requirement.coordinate)
            if not entry:
                _logger.warning(
                    f"No lockfile entry for {artifact_requirement.coordinate} in resolve {resolve.name}."
                )
                continue
            applicable_lockfile_entries[entry] = ct

    classpath_entries = await MultiGet(
        Get(
            ClasspathEntry,
            ClasspathEntryRequest,
            classpath_entry_request.for_targets(component=target,
                                                resolve=resolve),
        ) for target in applicable_lockfile_entries.values())

    resolve_digest = await Get(
        Digest, MergeDigests(cpe.digest for cpe in classpath_entries))

    return ThirdpartyModules(
        resolve,
        dict(zip(applicable_lockfile_entries, classpath_entries)),
        resolve_digest,
    )
示例#6
0
async def classpath(
    coarsened_targets: CoarsenedTargets,
    classpath_entry_request: ClasspathEntryRequestFactory,
) -> Classpath:
    # Compute a single shared resolve for all of the roots, which will validate that they
    # are compatible with one another.
    resolve = await Get(CoursierResolveKey, CoarsenedTargets,
                        coarsened_targets)

    # Then request classpath entries for each root.
    classpath_entries = await MultiGet(
        Get(
            ClasspathEntry,
            ClasspathEntryRequest,
            classpath_entry_request.for_targets(
                component=t, resolve=resolve, root=True),
        ) for t in coarsened_targets)

    return Classpath(classpath_entries, resolve)