Open claybridges opened 6 years ago
The root cause of this problem appears to have been a FileReference object that was removed from the project (by Xcodeproj) without also removing existing BuildFile objects that referenced it.
PBXFileReference
object is a reference to an actual file on disk, and is how Xcode tracks which files should appear on the left panel (among other things)PBXBuildFile
object is meant to wrap an existing PBXFileReference
object, and is created when a FileReference is added to a Target (for tracking file specific build information)That means that a BuildFile entry without a FileReference is meaningless. That's what we're looking at here: orphaned BuildFile entries in our project file. They appear to be inert. In fact, we would probably would never have noticed them if it weren't for a slight difference in how Xcode and Xcodeproj handled them.
These orphaned PBXBuildFile
entries in the project file are very recognizable once you know what to look for:
F54BBB842787606B00A10CEE /* MyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54BBB832787606B00A10CEE /* MyViewController.swift */; };
F567366F26D8052C0084ECEF /* BuildFile in Sources */ = {isa = PBXBuildFile; };
The first line is fine. The second line is the problem:
isa = PBXBuildFile;
)fileRef = [UUID];
attributeThe second line is an example of an orphaned BuildFile object in the project. The problem for us is that Xcode and Xcodeproj handle this line slightly differently. When the name of the FileReference is missing (because the underlying FileReference is missing):
(null) in Headers
, (null) in Sources
, (null) in Frameworks
, etc.Class
of the object (when the name is missing), producing BuildFile in Headers
, BuildFile in Sources
, BuildFile in Frameworks
So we see flapping between the two, as Xcode writes it one way, and then Xcodeproj writes it the other way.
The source of these orphaned BuildFile entries appears to have been Xcodeproj. It was not removing BuildFile objects from the project when it removed FileReferences.
The underlying issue appears to have been fixed in #861 (which as of now, hasn't shipped in a new version yet).
Once that is released, and we update, any projects using this patched version of Xcodeproj won't produce any new orphaned BuildFile objects. But any existing objects will not be cleaned up by this fix.
This StackOverflow post suggests a simple way to remove some of the most commonly reported orphaned entries:
#!/bin/sh
sed -i '' '/(null) in Sources /d' ProjectName.xcodeproj/project.pbxproj
sed -i '' '/(null) in Resources /d' ProjectName.xcodeproj/project.pbxproj
sed -i '' '/(null) in Frameworks /d' ProjectName.xcodeproj/project.pbxproj
Note that this script assumes that the project file was most recently updated by Xcode, which results in (null)
entries. If the project file was last updated by Xcodeproj (or CocoaPods via Xcodeproj), then these lines will show BuildFile
instead of (null)
.
Given the nature of the root problem, it might be safer to write a short ruby script that used Xcodeproj to find PBXBuildFile
entires that are missing a PBXFileReference
, or some similar check, and remove them. I may have some time this week to work on that.
We updated to CocoaPods 1.5.0. Having done this, it seems like whenever we touch our
project.pbxproj
files, references like these:Turn into these
We can fix with
However, this is generating a lot of unnecessary and obfuscating noise in our project file.
See possibly related #248.