OS
iOS
Description
Follow-up to #2026. That issue proposed two options; option A (buildable folders) is nearly complete β #2085 and #2101 converted the tests, Watch App, Widgets and Shared/, and #2102 converts the main tree. This is a concrete proposal for option B, in a form that costs contributors nothing day to day.
The proposal: project.yml becomes the source of truth, and the generated Meshtastic.xcodeproj stays committed to git.
Nobody's clone-and-open workflow changes: git clone, open Meshtastic.xcworkspace, build. XcodeGen is only needed by someone who changes project structure β adds a target, changes build settings, adds an SPM dependency. With buildable folders already in place, adding source files needs nothing at all.
Why this is worth doing now, specifically for how this project works. Contributors and maintainers here lean heavily on AI β Copilot, Codex, CodeRabbit are all over recent PRs. Agents read and edit YAML reliably and can be reviewed doing it. Nobody, human or model, can meaningfully review a project.pbxproj diff: it's a flat plist of opaque 24-character IDs, which is exactly why #1898 could silently delete a test file's registration and why #1827 spent six weeks in conflict limbo. Moving the project definition into ~200 lines of readable YAML puts it inside the review process for the first time, and gives agents a file they can safely operate on.
Verified feasibility (XcodeGen 2.46.0, tested locally before filing):
- Emits the modern format β
objectVersion = 77, newer than the project's current 70.
- Generates real Xcode 16 synchronized folders (
PBXFileSystemSynchronizedRootGroup) via type: syncedFolder, so it preserves and extends the buildable-folder work rather than undoing it.
- Generates
PBXFileSystemSynchronizedBuildFileExceptionSet correctly, which this project needs β Info.plist is excluded automatically, and explicit excludes (like the ~60 SVG exceptions on Resources/images) come through as membershipExceptions. explicitFolders is available to keep Resources/docs and Certificates as folder references so the in-app doc browser keeps its directory structure.
Regeneration is byte-deterministic β generating twice produced an identical SHA. This is what makes the committed-pbxproj model work: the file never churns spuriously, two contributors regenerating produce the same bytes, and a conflict is resolved by taking either side and re-running xcodegen, with no hand-merging of plist fragments ever again.
- Adding a source file produced zero change to the generated pbxproj.
Scope: 4 targets (Meshtastic, WidgetsExtension, MeshtasticTests, Meshtastic Watch App), 9 remote + 1 local SPM package, 3 shared schemes, the Catalyst configuration, and watch/widget embedding.
Suggested acceptance criteria, so this is provable rather than trusted:
xcodebuild -showBuildSettings output is identical between the committed project and the generated one, for every target Γ configuration.
- The built
.app bundle is identical file-for-file (catches any bundling or localization regression).
- All three shared schemes and the full test suite survive unchanged.
- A CI check regenerates and fails if the committed pbxproj has drifted from
project.yml.
Docs that would need updating: README.md (step 4) and CONTRIBUTING.md (step 4) keep "open the workspace" as-is, plus a short new section on when regeneration is required; docs/developer/contributing.md and docs/developer/codebase.md get the same note.
Two caveats worth stating up front. XcodeGen 2.45.0 or newer is required β 2.44.x silently ignores excludes on synced folders, which would quietly bundle files that are currently excluded (I hit this while testing). And this should land only after #2102, since both rewrite the whole pbxproj and would otherwise collide β which would be an ironic way to make the point.
Participation
Additional comments
Deliberately filing this as a proposal first β it's a change to how everyone interacts with the project, and worth agreeing on before any code. If needed can put up a proof-of-concept project.yml with the -showBuildSettings diff attached, so the decision can be made against real output rather than a description.
Code of Conduct
OS
iOS
Description
Follow-up to #2026. That issue proposed two options; option A (buildable folders) is nearly complete β #2085 and #2101 converted the tests, Watch App, Widgets and
Shared/, and #2102 converts the main tree. This is a concrete proposal for option B, in a form that costs contributors nothing day to day.The proposal:
project.ymlbecomes the source of truth, and the generatedMeshtastic.xcodeprojstays committed to git.Nobody's clone-and-open workflow changes:
git clone,open Meshtastic.xcworkspace, build. XcodeGen is only needed by someone who changes project structure β adds a target, changes build settings, adds an SPM dependency. With buildable folders already in place, adding source files needs nothing at all.Why this is worth doing now, specifically for how this project works. Contributors and maintainers here lean heavily on AI β Copilot, Codex, CodeRabbit are all over recent PRs. Agents read and edit YAML reliably and can be reviewed doing it. Nobody, human or model, can meaningfully review a
project.pbxprojdiff: it's a flat plist of opaque 24-character IDs, which is exactly why #1898 could silently delete a test file's registration and why #1827 spent six weeks in conflict limbo. Moving the project definition into ~200 lines of readable YAML puts it inside the review process for the first time, and gives agents a file they can safely operate on.Verified feasibility (XcodeGen 2.46.0, tested locally before filing):
objectVersion = 77, newer than the project's current 70.PBXFileSystemSynchronizedRootGroup) viatype: syncedFolder, so it preserves and extends the buildable-folder work rather than undoing it.PBXFileSystemSynchronizedBuildFileExceptionSetcorrectly, which this project needs βInfo.plistis excluded automatically, and explicitexcludes(like the ~60 SVG exceptions onResources/images) come through asmembershipExceptions.explicitFoldersis available to keepResources/docsandCertificatesas folder references so the in-app doc browser keeps its directory structure.Regeneration is byte-deterministic β generating twice produced an identical SHA. This is what makes the committed-pbxproj model work: the file never churns spuriously, two contributors regenerating produce the same bytes, and a conflict is resolved by taking either side and re-running
xcodegen, with no hand-merging of plist fragments ever again.Scope: 4 targets (Meshtastic, WidgetsExtension, MeshtasticTests, Meshtastic Watch App), 9 remote + 1 local SPM package, 3 shared schemes, the Catalyst configuration, and watch/widget embedding.
Suggested acceptance criteria, so this is provable rather than trusted:
xcodebuild -showBuildSettingsoutput is identical between the committed project and the generated one, for every target Γ configuration..appbundle is identical file-for-file (catches any bundling or localization regression).project.yml.Docs that would need updating:
README.md(step 4) andCONTRIBUTING.md(step 4) keep "open the workspace" as-is, plus a short new section on when regeneration is required;docs/developer/contributing.mdanddocs/developer/codebase.mdget the same note.Two caveats worth stating up front. XcodeGen 2.45.0 or newer is required β 2.44.x silently ignores
excludeson synced folders, which would quietly bundle files that are currently excluded (I hit this while testing). And this should land only after #2102, since both rewrite the whole pbxproj and would otherwise collide β which would be an ironic way to make the point.Participation
Additional comments
Deliberately filing this as a proposal first β it's a change to how everyone interacts with the project, and worth agreeing on before any code. If needed can put up a proof-of-concept
project.ymlwith the-showBuildSettingsdiff attached, so the decision can be made against real output rather than a description.Code of Conduct