chore(project): convert main Meshtastic/ tree to Xcode 16 buildable folders#2102
chore(project): convert main Meshtastic/ tree to Xcode 16 buildable folders#2102bruschill wants to merge 7 commits into
Conversation
…le-folder plan Pre-flip gate for converting Meshtastic/ to an Xcode 16 buildable folder (issue meshtastic#2026, follow-up to meshtastic#2085). Both files are on disk but compiled into no target; both are non-viable if the folder is synced: - MessageTemplate.swift: does not compile (type '()' cannot conform to 'View'), dead since an old iOS 16 commit, referenced by nothing. - NodeInfo.swift: re-declares struct NodeInfoItem (already defined by the compiled NodeInfoItem.swift); stale superseded copy. App target still builds after removal (verified). Adds the verified conversion plan under docs/plans/.
…ldable folders Follow-up to meshtastic#2085 (issue meshtastic#2026). Converts 17 source folders under Meshtastic/ to PBXFileSystemSynchronizedRootGroups so adding/moving/deleting source files no longer edits project.pbxproj: Accessory, API, AppIntents, CarPlay, Enums, Export, Extensions, Helpers, Intents, Measurement, Model, Persistence, Provisioning, Router, Services, Tips, Views Net project.pbxproj: +179 / -2143. Details: - The 7 previously-orphaned but valid files (6 SwiftData entity extensions + Model+Sendable.swift) are now compiled automatically via the synced folders. Verified: 416/416 .swift under Meshtastic/ compile; 0 orphans remain. - Constants.swift (Extensions/, shared with WidgetsExtension) stays compiled in the app via sync and is re-added to WidgetsExtension via an explicit reference. - The nested PreferenceKeys synced folder is removed (now covered by Views/). - Removed ~19 stale duplicate file references (the "Recovered References" cruft) that would otherwise double-compile once their folders were synced. - Resources/ intentionally left as a classic group: it holds the images synced sub-folder with a build-script-driven SVG exception set / runtime image pipeline that must not be disturbed. It is not source. Validated: Meshtastic, WidgetsExtension, and Watch App targets all BUILD SUCCEEDED; MeshtasticTests XCTest suite passes (0 failures). A pre-existing Swift Testing SwiftData ModelContext.reset crash (in the untouched MeshtasticTests/ folder) is unrelated to these pbxproj-only changes.
…ree-buildable # Conflicts: # Meshtastic.xcodeproj/project.pbxproj
📝 WalkthroughWalkthroughThe Xcode project converts the main app tree to synchronized buildable folders, updates target/resource/source wiring, adds the PMTiles test source, removes two SwiftUI helper views, and records the completed conversion and validation plan. ChangesBuildable folder conversion
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
Meshtastic.xcodeproj/project.pbxproj (1)
31-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRemove the explicit
PMTilesExtractorTests.swiftwiring.
MeshtasticTestsis already a synchronized folder assigned to this target, so its contents are discovered automatically. Remove these four manual entries to avoid redundant target membership and restore the PR’s zero-maintenance model. (developer.apple.com)Also applies to: 140-140, 511-511, 920-920
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Meshtastic.xcodeproj/project.pbxproj` at line 31, Remove the explicit PMTilesExtractorTests.swift wiring from the Xcode project: delete its PBXBuildFile entry, file reference, and both associated target/group membership entries. Keep MeshtasticTests configured as the synchronized folder so the test file remains discovered automatically without manual references.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/plans/buildable-folders-main-tree.md`:
- Around line 76-77: Insert a blank line between the “### DELETE — 2 files
(compiler-/collision-confirmed non-viable)” heading and the table header that
begins with “| File | Origin | Verdict |”.
In `@Meshtastic.xcodeproj/project.pbxproj`:
- Around line 207-208: Add uk to every knownRegions list in the Xcode project
configuration, reusing the existing Ukrainian localization references shown by
the PBXFileReference entries. Preserve all existing regions and ordering
conventions while ensuring each project target’s supported-region list includes
uk.
---
Nitpick comments:
In `@Meshtastic.xcodeproj/project.pbxproj`:
- Line 31: Remove the explicit PMTilesExtractorTests.swift wiring from the Xcode
project: delete its PBXBuildFile entry, file reference, and both associated
target/group membership entries. Keep MeshtasticTests configured as the
synchronized folder so the test file remains discovered automatically without
manual references.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 43b48808-68b2-47ca-859d-7a787929953e
📒 Files selected for processing (4)
Meshtastic.xcodeproj/project.pbxprojMeshtastic/Views/Helpers/Messages/MessageTemplate.swiftMeshtastic/Views/Nodes/Helpers/NodeInfo.swiftdocs/plans/buildable-folders-main-tree.md
💤 Files with no reviewable changes (2)
- Meshtastic/Views/Helpers/Messages/MessageTemplate.swift
- Meshtastic/Views/Nodes/Helpers/NodeInfo.swift
| ### DELETE — 2 files (compiler-/collision-confirmed non-viable) | ||
| | File | Origin | Verdict | |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add a blank line before the table.
Proposed fix
### DELETE — 2 files (compiler-/collision-confirmed non-viable)
+
| File | Origin | Verdict |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ### DELETE — 2 files (compiler-/collision-confirmed non-viable) | |
| | File | Origin | Verdict | | |
| ### DELETE — 2 files (compiler-/collision-confirmed non-viable) | |
| | File | Origin | Verdict | |
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)
[warning] 77-77: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/buildable-folders-main-tree.md` around lines 76 - 77, Insert a
blank line between the “### DELETE — 2 files (compiler-/collision-confirmed
non-viable)” heading and the table header that begins with “| File | Origin |
Verdict |”.
Source: Linters/SAST tools
| AA000401SIRI000000000027 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = uk; path = uk.lproj/AppIntentVocabulary.plist; sourceTree = "<group>"; }; | ||
| AA000402IPLS000000000011 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
python3 - <<'PY'
from pathlib import Path
p = Path("Meshtastic.xcodeproj/project.pbxproj")
text = p.read_text(errors="replace").splitlines()
# Print line-numbered excerpts around knownRegions and uk file references
targets = ["knownRegions", "uk.lproj/AppIntentVocabulary.plist", "uk.lproj/InfoPlist.strings"]
for i, line in enumerate(text, 1):
if any(t in line for t in targets):
start = max(1, i - 8)
end = min(len(text), i + 12)
print(f"\n--- excerpt around line {i} ---")
for j in range(start, end + 1):
print(f"{j:5d}: {text[j-1]}")
PYRepository: meshtastic/Meshtastic-Apple
Length of output: 7832
🏁 Script executed:
python3 - <<'PY'
from pathlib import Path
p = Path("Meshtastic.xcodeproj/project.pbxproj")
lines = p.read_text(errors="replace").splitlines()
# Show every knownRegions block with enough context to include the full list.
for i, line in enumerate(lines, 1):
if "knownRegions = (" in line:
print(f"\n=== knownRegions at line {i} ===")
start = i
# print until matching ");"
depth = 0
for j in range(i, len(lines) + 1):
s = lines[j - 1]
print(f"{j:5d}: {s}")
if "(" in s:
depth += s.count("(")
if ")" in s:
depth -= s.count(")")
if depth <= 0 and s.strip() == ");":
break
PYRepository: meshtastic/Meshtastic-Apple
Length of output: 540
Add uk to each knownRegions list. Ukrainian localizations are present, but uk is missing from the project’s supported regions, so Xcode won’t treat them consistently.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Meshtastic.xcodeproj/project.pbxproj` around lines 207 - 208, Add uk to every
knownRegions list in the Xcode project configuration, reusing the existing
Ukrainian localization references shown by the PBXFileReference entries.
Preserve all existing regions and ordering conventions while ensuring each
project target’s supported-region list includes uk.
- Add uk to knownRegions (matches the uk.lproj localization files) - Remove redundant explicit PMTilesExtractorTests.swift wiring; it is auto-included via the synchronized MeshtasticTests folder (verified with build-for-testing)
What changed?
Converts the main
Meshtastic/app source tree to Xcode 16 buildable folders (PBXFileSystemSynchronizedRootGroup), so files under these folders are compiled by their on-disk location instead of by hand-maintainedproject.pbxprojentries.17 source folders converted:
Accessory,API,AppIntents,CarPlay,Enums,Export,Extensions,Helpers,Intents,Measurement,Model,Persistence,Provisioning,Router,Services,Tips,Views. Net effect on the project file: +187 / -2,226 lines, roughly 2,000 fewer hand-maintained references..swiftphysically inside them now compiles automatically.BUILD SUCCEEDED) and the compiler's ownMeshtastic.SwiftFileListdiffed against disk to find true orphans. Of ~418 on-disk.swiftfiles, exactly 9 were orphans (on disk, not compiled). Each was adjudicated by adding it to the target and rebuilding:PBXBuildFilein past merge conflicts: SwiftData entity extensions from Rename CoreData references to SwiftData, delete dead code #1752,Model+Sendable.swiftfrom Add wifi_threshold and ble_threshold fields to Paxcounter Config #1846). These now compile automatically.Views/Helpers/Messages/MessageTemplate.swift(doesn't compile) andViews/Nodes/Helpers/NodeInfo.swift(redeclaresNodeInfoItem, colliding with the liveNodeInfoItem.swift).Resources/is deliberately left classic (it has an image build-script/exception pipeline, not source). NestedResources/imagesandPreferenceKeyssynchronized groups are preserved.MeshtasticApp.swift,AppState.swift,MeshtasticAppDelegate.swift) remain explicit refs by design.Builds directly on the groundwork from #2085 by @laconicman, which converted
MeshtasticTests/, theMeshtastic Watch App/, and laterWidgets/+ a sharedShared/folder to buildable folders and established the pattern this PR follows for the main app tree.Behavior note (flagged intentionally): because folders are now synchronized, the 7 previously-orphaned files are compiled again. Most are additive
init/update(...)helpers.Model/Model+Sendable.swift(#1846) addsSendableconformance to 43@Modelentities — it compiles clean and no entity already declaredSendable, so it's purely additive, but it does change the concurrency-checking surface. Called out for reviewer awareness.Why the two deleted files were genuine orphans (evidence)
Both deleted files were present on disk but never referenced in
project.pbxproj, so they were never compiled into any target. Under buildable folders they would have been dragged into the build, so they had to be resolved.Views/Helpers/Messages/MessageTemplate.swift(struct MessageTemplate) —0references anywhere in the codebase,0references in upstream'sproject.pbxproj. Pure dead code.Views/Nodes/Helpers/NodeInfo.swift— despite its filename, declaresstruct NodeInfoItem: View, the same type as the siblingNodeInfoItem.swift. Under a synchronizedViews/folder this is an invalid redeclaration causing a build failure.NodeInfo.swift:0refs in upstream's pbxproj (orphan).NodeInfoItem.swift:4refs (the live, compiled file), kept. The only call site,NodeInfoItem(node:)inNodeDetail.swift, is satisfied by the kept file'sinit(node:).Why did it change?
Hand-maintained
project.pbxprojfile references are the single biggest source of merge conflicts and "file added but forgot to wire it into the target" mistakes in this repo. Buildable folders compile files by their on-disk location, eliminating that whole class of conflict/omission and removing ~2,000 hand-maintained references. The conversion also surfaced and resolved 9 pre-existing orphan files (7 restored to the build, 2 dead files removed).How is this tested?
plutil -lintclean; no duplicate object IDs.xcodebuildBUILD SUCCEEDED for theMeshtasticscheme (iOS Simulator), which builds + embeds WidgetsExtension and the Watch App.upstream/main; all newly-added upstream source files are auto-included via the synced folders (0 new explicit refs needed).Meshtastic.SwiftFileListdiffed against disk), not regex.Screenshots/Videos (when applicable)
N/A — project-structure/build-configuration change only; no runtime or UI change.
Checklist
docs/user/ordocs/developer/. No doc update is needed (project-structure/build change, no user-visible behavior) —skip-docs-checklabel applies.Summary by CodeRabbit
Bug Fixes
UI Updates
Documentation