Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dependency framework/library linking #93

Merged
merged 4 commits into from
Oct 18, 2017
Merged

Fix dependency framework/library linking #93

merged 4 commits into from
Oct 18, 2017

Conversation

keith
Copy link
Collaborator

@keith keith commented Oct 17, 2017

This PR updates XcodeGen to link framework and library dependencies of targets, into the dependent targets. This is required for them to be usable at runtime. This also removes libraries from the copy framework build phase, since that just results in a .a file ending up in your final package.

This should fix #92

// targetFrameworkBuildFiles.append(dependencyBuildFile)
if dependencyTarget.type.isLibrary || dependencyTarget.type.isFramework {
let dependencyBuildFile = targetBuildFileReferences[dependencyTargetName]!
targetFrameworkBuildFiles.append(dependencyBuildFile)
Copy link
Collaborator Author

@keith keith Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this seems to not be the type that Xcode is expecting.

Copy link
Collaborator Author

@keith keith Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I was testing with a project without a bundle identifier, which really confuses Xcode. This does work

@keith
Copy link
Collaborator Author

keith commented Oct 17, 2017

Updated the project since the changes are legit, the next test run should be green.

@keith
Copy link
Collaborator Author

keith commented Oct 17, 2017

Hmm, it looks like there is some issue with this, where right after generating the project, if I do a pod install, xcodeproj throws this error:

RuntimeError - [Xcodeproj] Consistency issue: no parent for object `Module2.framework`: `FrameworksBuildPhase`, `FrameworksBuildPhase`

I'll try and look in to why this is happening

@keith
Copy link
Collaborator Author

keith commented Oct 17, 2017

Based on the project diff after opening Xcode, it seems like the issue might be re-using file reference IDs in the "frameworks" build phase. As soon as you open the project in Xcode, it gets re-written to have new IDs, but leaves the original there for 1 of the references.

@keith
Copy link
Collaborator Author

keith commented Oct 17, 2017

Ok I just pushed a commit with a fix for this. So it turns out that the problem is, if you want to include a framework like this into multiple copy/frameworks/whatever phases, you need separate file PBXBuildFiles for each case. But they all need to point back to the original PBXFileReference which represents the original target's product.

This now allows the same framework to be linked to multiple dependent targets

@@ -46,6 +46,14 @@ extension PBXProductType {
}
}

public var isFramework: Bool {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add some tests here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Copy link

@pepicrft pepicrft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job @keith 👏

@keith
Copy link
Collaborator Author

keith commented Oct 17, 2017

Thanks for the review! Added some tests here

Copy link
Owner

@yonaskolb yonaskolb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @keith. I left some comments

@@ -46,6 +46,14 @@ extension PBXProductType {
}
}

public var isFramework: Bool {
return fileExtension == "framework"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this getter is need if it relates to a single case, we can just use target.type == .framework at call sites. At the very least, this getter could itself use self == .framework

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave the getter here to match the other accessors, but check the case within it 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

public var isLibrary: Bool {
return name == "library.static" || name == "library.dynamic"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this use the actual enum cases instead of strings

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


if embed {
if dependencyTarget.type.isLibrary {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a library never embeded, or are there special cases where they are?
If it can be sometimes, ca we move this logic up into where let embed is defined, which gives the embedding a default, and then users can override this.

If it's definitely never, we can also move this if into the if above if embed && !dependencyTarget.type.isLibrary

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are never embedded. Since that would just mean that you're literally copying the .a file into your .app, which would never be used at runtime since static libraries are linked into your final binary instead. I've updated the condition!

@@ -5,4 +5,5 @@ XCTMain([
testCase(GeneratorTests.allTests),
testCase(SpecLoadingTests.allTests),
testCase(FixtureTests.allTests),
testCase(TargetTests.allTests),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this ProjectSpecTests?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

These should only be linked. If we add a library to the project here,
Xcode will remove it next time it touches the project
@keith
Copy link
Collaborator Author

keith commented Oct 18, 2017

All feedback addressed!

Copy link

@pepicrft pepicrft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job @keith

@yonaskolb yonaskolb merged commit 09209a4 into yonaskolb:master Oct 18, 2017
@keith keith deleted the ks/link-dependencies branch October 18, 2017 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Frameworks and static library targets should be linked (and sometimes copied) into their dependent targets
3 participants