tuist / XcodeProj

📝 Read, update and write your Xcode projects
https://xcodeproj.tuist.io
MIT License
2.03k stars 307 forks source link

Names of linked frameworks #254

Closed artemnovichkov closed 6 years ago

artemnovichkov commented 6 years ago

Context 🕵️‍♀️

I'm developing Carting and in next major release I want to rewrite project parsing logic with xcproj.

What 🌱

I want to get a names of linked frameworks for every target, but I didn't API for it. Here is my test code:

let project = try XcodeProj(pathString: path)
for (_, target) in project.pbxproj.objects.nativeTargets {
    let frameworksBuildPhase = project.pbxproj.objects.frameworksBuildPhases.first { (key, _) in
        target.buildPhases.contains(key)
    }
    print(frameworksBuildPhase!.value.files)
}

I got only refs for frameworks.

pepicrft commented 6 years ago

Hi @artemnovichkov. Those references are references to build files:

BuildPhase > Build File > FileReference

So you would need to get the build file, and from it the file reference. Unfortunately there's no convenience API that allows you get get it directly without having to do multiple calls. Improving this is in the backlog but I haven't worked on it yet. Let me know if that works for you :)

artemnovichkov commented 6 years ago

I'm not sure I have enough time, but I'm ready to start it. Could you please tell me how I can get the names for framework references with current xcproj implementation?

pepicrft commented 6 years ago

Sure, no worries. I can do that, I just tried to explain you why it's not possible right now. So in order to do that with the current implementation:

func likedFrameworks(targetName: String, project: PBXProj) -> [PBXFileReference] {
    guard let target = project.objects.targets(named: targetName).first else { return [] }
    guard let frameworksBuildPhase: PBXFrameworksBuildPhase = project.objects.frameworksBuildPhases.filter({ (key, phase) in
        target.object.buildPhases.contains(key)
    }).first?.value else { return [] }
    let buildFiles = frameworksBuildPhase.files.compactMap({ project.objects.buildFiles[$0] }).compactMap({ $0.fileRef })
    return buildFiles.compactMap({ project.objects.fileReferences[$0] })
}

That should give you the linked frameworks for any target.

artemnovichkov commented 6 years ago

Got it, thank you!