Skip to content

Make placeholder PIF construction a type operation - #10436

Open
pmattos wants to merge 2 commits into
release/6.4.xfrom
pmattos/static-pif-placeholder
Open

pmattos wants to merge 2 commits into
release/6.4.xfrom
pmattos/static-pif-placeholder

Conversation

@pmattos

@pmattos pmattos commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Make placeholder PIF construction available on the PackagePIFBuilder type.

Motivation:

buildPlaceholderPIF(id:path:projectDir:name:) was an instance method, but it only used self in two places: to read the package's base build settings, and to store the resulting project in _pifProject. Everything else was constructed from its arguments.

That coupling had two costs:

  1. A placeholder PIF could only be produced once a PackagePIFBuilder had been constructed, which requires a resolved package and a modules graph.
  2. It was effectively untestable, since exercising it meant standing up a full package graph.

An additional motivation is to follow the same three-layer shape buildEmptyPIF already uses:.

Modifications:

Add two helper class functions to build the placeholder PIF.

The instance method keeps its signature and becomes a thin wrapper instead.

I also added some needed unit tests to validate this feature.

Finally, a minor cleanup for the related buildEmptyPIFoperation.

Result:

A placeholder PIF can now be built without a PackagePIFBuilder instance, which makes it usable for a package that failed to load.

Development region. Behavior through the existing instance method is unchanged, with one exception: the placeholder project now carries a development region where it previously carried nil. A placeholder has a single aggregate target with no product, no build phases and no files, so there should be nothing for a base localization to affect.

Note that buildPlaceholderPIF has no callers within SwiftPM — it is API for clients embedding SwiftBuildSupport, like Xcode.

Fixes rdar://185457772

@pmattos pmattos changed the title Pmattos/static pif placeholder Make placeholder PIF construction a type operation Aug 20, 2026
projectDir: projectDir,
name: name,
targetBuildSettings: self.package.underlying.packageBaseBuildSettings,
developmentRegion: self.package.manifest.defaultLocalization

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

developmentRegion wasn't being set before, and looks like it's serialized. Is this going to affect anything by being added?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. The placeholder project now carries a development region where it previously carried nil. A placeholder has a single aggregate target with no product, no build phases and no files, so there should be nothing for a base localization to affect.

@pmattos

pmattos commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

@swift-ci test

…lder

buildPlaceholderPIF(id:path:projectDir:name:) only used the builder instance to read
the package's base build settings and to store the resulting project. That meant a
placeholder PIF could only be built once a PackagePIFBuilder existed, which requires
a resolved package and a modules graph — yet a placeholder is wanted precisely when a
package failed to load, that is, when those inputs are missing and no builder can be
constructed. It also made the placeholder builder untestable without a full package
graph.

Split it into the same three layers buildEmptyPIF already uses: a type-level
buildPlaceholderPIF(id:path:projectDir:name:targetBuildSettings:developmentRegion:)
that needs no instance and returns both the project and the placeholder module, a
buildPlaceholderPIF(package:) convenience, and the existing instance method kept with
its current signature as a thin wrapper, so callers are unaffected.

The settings parameter is named targetBuildSettings because they are applied to the
aggregate target's build configurations rather than to the project's. The placeholder
project now also sets developmentRegion, which it was alone in omitting.

Adds PIFPlaceholderTests, which the refactor is what makes possible: the type-level
entry point needs no package graph to exercise.

rdar://185457772
PackagePIFBuilder is final, so class func and static func are behaviorally
identical here: nothing can override them either way. class func nonetheless
suggests overridability the type has renounced, and it was out of step with
the rest of the project — before this change SwiftPM had exactly four
non-override class func declarations, all of them in this file, against 1049
static func declarations elsewhere.

Applies to both the empty and placeholder PIF builders.

rdar://185457772
@pmattos
pmattos force-pushed the pmattos/static-pif-placeholder branch from 7898fe4 to 0eb681e Compare September 3, 2026 16:41
@pmattos
pmattos changed the base branch from main to release/6.4.x September 3, 2026 16:41
@pmattos

pmattos commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

@swift-ci test

@pmattos

pmattos commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

@swift-ci test Windows

@pmattos
pmattos changed the base branch from release/6.4.x to release/6.4.2 September 17, 2026 18:15
@pmattos

pmattos commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

@swift-ci test

@pmattos
pmattos changed the base branch from release/6.4.2 to release/6.4.x October 14, 2026 20:08
@pmattos

pmattos commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

@swift-ci test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants