Comments (11)
Bumping this, I'd love to fix this on my own but I really don't understand what's going on.
from xcodeproj.
Hey @stevelandeyasana 👋
I can try looking into this but would it be possible if you first wrote a unit / integration test for this in the codebase? That would be super helpful 🙏
from xcodeproj.
I'll probably be able to carve out some time this week to try to break it in a test.
from xcodeproj.
Well, this is spooky: I wrote a test that should do exactly what I'm doing in my larger codebase, but it works. I added this to PBXProjIntegrationTests.swift
:
func test_uuids_after_adding_to_build_phase() throws {
let fixturePath = self.fixturePath().parent().parent()
let xcp = try XcodeProj(path: self.fixturePath().parent())
let project = xcp.pbxproj.projects.first(where: { $0.name == "Project" })!
let iosGroup = project.mainGroup.children.first(where: { $0.path == "iOS" }) as! PBXGroup
let appTarget = xcp.pbxproj.nativeTargets.first(where: { $0.name == "iOS" })!
let sourcesPhase = appTarget.buildPhases.first(where: { $0.buildPhase == .sources }) as! PBXSourcesBuildPhase
let newFilePath = Path(components: fixturePath.components + ["iOS", "FileNotInProject.swift"])
let file = try iosGroup.addFile(at: newFilePath, sourceRoot: fixturePath)
let buildFile = PBXBuildFile(file: file, product: nil, settings: [:])
sourcesPhase.files?.append(buildFile)
let encoder = PBXProjEncoder(outputSettings: PBXOutputSettings())
let output: String = try encoder.encode(proj: xcp.pbxproj)
XCTAssert(!output.contains("TEMP"))
}
It passed. :-( I'll keep poking at it.
Differences I can think of vs my own project file:
- More build targets
- More build phases
- I'm dynamically iterating over files in a directory instead of using a static path
from xcodeproj.
I tried attaching a debugger to see if I could see where ReferenceGenerator skips over my new files. I found that when it's iterating over the build file references, it's skipping at least one because it can't find the PBXBuildFile that goes with a PBXObjectReference. I'm still trying to work out what that means. These conditions do happen when working with my main project, and not with the integration test I wrote above.
private func generateBuildPhaseReferences(_ buildPhase: PBXBuildPhase,
identifiers: [String]) throws {
var identifiers = identifiers
if let name = buildPhase.name() {
identifiers.append(name)
}
// Build phase
fixReference(for: buildPhase, identifiers: identifiers)
// Build files
buildPhase.fileReferences?.forEach { buildFileReference in
if !buildFileReference.temporary { return }
// THIS LINE: buildFileReference.getObject() returns nil
guard let buildFile: PBXBuildFile = buildFileReference.getObject() else { return }
from xcodeproj.
OK, this looks like a spooky memory management thing. If I make an [Any]
array outside my loop, and append the PBXBuildFiles I create to that array, then it works. My example integration test doesn't have a loop, so it doesn't have the bug. When I add the loop to the integration test, it fails. I'll open a PR with the failing test, and fix my code using this workaround.
from xcodeproj.
Clearer explanation of what I learned: XcodeProj does not keep any strong internal references to PBXBuildFile, so unless the caller keeps its own references, newly created PBXBuildFile objects added to a build phase may be come nil before the project file is written.
I think this is really surprising behavior, but it does have a straightforward workaround.
from xcodeproj.
XcodeProj does not keep any strong internal references to PBXBuildFile, so unless the caller keeps its own references, newly created PBXBuildFile objects added to a build phase may be come nil before the project file is written.
Ouch, that's a pretty good find!
It does seem to be the case:
PBXObjectReference
keeps a weak pointer to itsobjects
(PBXBuildFile
will be one of those)PBXBuildPhase
does not storePBXBuildFile
s directly - instead uses the getter inPBXObjectReference
We'll need to keep a strong pointer somewhere.
I think we can rewrite:
/// References to build files.
var fileReferences: [PBXObjectReference]?
/// Build files.
public var files: [PBXBuildFile]? {
get {
fileReferences?.objects()
}
set {
newValue?.forEach { $0.buildPhase = self }
fileReferences = newValue?.references()
}
}
to:
/// References to build files.
var fileReferences: [PBXObjectReference]? {
files?.references()
}
/// Build files.
public var files: [PBXBuildFile]? {
didSet {
files?.forEach { $0.buildPhase = self }
}
}
This change will strongly hold the PBXBuildFile
s and subsequently also the PBXObjectReference
s since the former holds strongly the latter but not the other way around.
Would such a change make sense @stevelandeyasana? If so, let me know if you wanted to implement this yourself or I can go ahead. Either way, it would be great if you tested it in your project where you have first seen the issue.
from xcodeproj.
Unfortunately that isn't quite sufficient. The initializers directly assign to fileReferences
, which you changed from a get
/set
to just a get
property, and I'm not sure what's supposed to happen with the Decodable initializer. But otherwise that looks like a good solution.
from xcodeproj.
Hola 👋,
We want to inform you that the issue has been marked as stale. This means that there hasn't been any activity or updates on it for quite some time, and it's possible that it may no longer be relevant or actionable.
If you still believe that this issue is valid and requires attention, please provide an update or any additional information that can help us address it. Otherwise, we may consider closing it in the near future.
Thank you for your understanding.
from xcodeproj.
Hola 👋,
We want to inform you that we have decided to close this stale issue as there hasn't been any activity or response regarding it after marking it as stale.
We understand that circumstances may have changed or priorities may have shifted, and that's completely understandable. If you still believe that this issue needs to be addressed, please feel free to reopen it and provide any necessary updates or additional information.
We appreciate your understanding and look forward to your continued contributions to the project.
Thank you.
from xcodeproj.
Related Issues (20)
- `pbxProject.setTargetAttributes()` isn't thread safe HOT 5
- Unable to add an Embed App Clip phase HOT 4
- Question: Adding subprojects
- `XCSchemeManagement` reads from path are unstable HOT 2
- deleted
- Add support for type on runtime issue breakpoints HOT 2
- Dependency Dashboard HOT 7
- Depfu Error: No dependency files found HOT 2
- Better messaging for corrupt `xcworkspace` inside `xcodeproj` files HOT 2
- Having issues cleanly removing a local swift package dependency HOT 3
- Add an option to get the String representation of PBXProj
- Creating a new release HOT 2
- How to find the active scheme of a project/workspace HOT 2
- Create PBXProj from Data Representation HOT 1
- deleted
- Cannot remove remotePackage HOT 2
- Release 8.15.1 not published HOT 2
- Error during package resolving
- Cannot find 'Glibc' in scope on Mac HOT 2
- Incorrect name of the target product returned from `productNameWithExtension()` HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from xcodeproj.