-
Notifications
You must be signed in to change notification settings - Fork 823
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
Support external target dependencies via subprojects #701
Support external target dependencies via subprojects #701
Conversation
08f7443
to
253cbab
Compare
Just wanted to say thanks for this by the way! I'm experimenting with adopting XcodeGen and this would have been one of the blockers for us however when running your fork it works great, so good timing 😄 I did however noticed something while testing... But I'm not sure if it relates to this change in particular or if it was to do with the initial introduction of If I declare my ProjectDefinitions/base.yml ---
projectReferences:
Network:
path: Frameworks/Network/Network.xcodeproj
Logger:
path: Frameworks/Logger/Logger.xcodeproj
Persistence:
path: Frameworks/Persistence/Persistence.xcodeproj
options:
xcodeVersion: "11.1"
deploymentTarget:
iOS: "11.4"
settings:
base:
CURRENT_PROJECT_VERSION: 9.58.0.0
VERSIONING_SYSTEM: apple-generic
SWIFT_VERSION: 5.0
INFOPLIST_FILE: ${TARGET_NAME}/SupportingFiles/Info.plist
targetTemplates:
CoreModule:
platform: iOS
type: framework
sources:
- ../Frameworks/${frameworkName}/${frameworkName} project.yml name: Global
include:
- ProjectDefinitions/base.yml
... This example produces the xcodeproj correctly however the ProjectDefinitions/base.yml looks wrong since I have my projectReferences paths relative to a different directory from the targetTemplates sources path. I first tried implementing the projectReferences paths relative to the file they're defined in but I was then hit with the following while generating the project:
I just wanted to flag it here incase it's related to this change specifically... If it's not i can rase it separately and even have a go at correcting it. Thanks! |
Thank you for the great PR @evandcoleman! You've correctly identified the planned next step in harnessing the new project references 👍 |
@yonaskolb Thanks! I'm really looking forward to using XcodeGen and this is the last step for us! I'd also like your opinion on @liamnichols' comment. I wasn't really sure if I should be referencing subprojects via their relative path, or to prepend the project basepath so I think there's some room for improvement and consistency there. |
just adding some more context here. I managed to depend on targets from external projects without using the new
An example name: Example
options:
minimumXcodeGenVersion: 2.10.1
fileGroups: [
FooLib/FooLib.xcodeproj
]
targets:
Bar:
platform: iOS
type: application
dependencies:
- framework: FooLib.framework
implicit: true Find a working example here (under the |
@acecilia I don't believe that will actually add a target dependency to your target. That was one of the driving factors here since there's no requirement that target product names be unique. |
@evandcoleman It adds a framework dependency that Xcode is able to implicitly understand that corresponds to the target in the external project (due to the "Find Implicit Dependencies" option of the scheme), and thus it will build both correctly. If you do not believe it works you can have a look at the example project. That said, it does not turn this PR invalid. My goal was just to add my experience and some extra context to this discussion :) |
@yonaskolb Is this PR still being considered? The solutions posted here may work for some, but we include several dependencies that have multiple targets with the same product name (for different platforms). So implicit dependencies will not work. |
I'm wrestling with a similar issue. Unfortunately some of my sub dependencies have cocoapod dependencies too so the fileGroups workaround that @acecilia demonstrated doesn't work. Some of them support Carthage so I could move to that and dump cocoa pods for everything below my root applications, unless anyone can think of another work around. I understand trying to marry the cocoa pods approach and this one is not really feasible or desirable. For context I am trying to modularize a codebase into a tree of modules that compile into cross platform apps. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late review @evandcoleman. Great work on this one! I've left some comments above. This PR will need to have master merged in as well (preferable to a rebase at this point, so we have visibility of the changes, in regards to conflict resolution)
|
||
let link = dependency.link ?? | ||
((dependecyLinkage == .dynamic && target.type != .staticLibrary) || | ||
(dependecyLinkage == .static && target.type.isExecutable)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we pull common stuff like this out and above the switch
PBXGroup( | ||
children: subprojectFileReferences, | ||
sourceTree: .group, | ||
name: "Projects" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is adding all projects into a Projects
group sufficient for most people? I could imagine people wanting to add their projects to a specific group.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my use case, it doesn't really matter. But I agree, I could see a use for it. How would you think that would work best? A new parameter under projectReferences?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now it's ok 👍
|
||
guard let index = projectFileReferenceIndex, | ||
let projectFileReference = self.pbxProj.rootObject?.projects[index]["ProjectRef"] as? PBXFileReference, | ||
let productsGroup = self.pbxProj.rootObject?.projects[index]["ProductGroup"] as? PBXGroup else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is getting too large and complicated. Will have to look at splitting this up into things like TargetGenerator
and the like, after this
@liamnichols the relative project reference paths in included files should be fixed with #740 and #751 |
453f5f2
to
75b426d
Compare
@yonaskolb Just pushed up a bunch of changes and rebased with master. Let me know what you think of the dependency target generation now. I opted to create a "fake" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating @evandcoleman. Left some comments above
if let cachedProject = projects[reference] { | ||
return cachedProject | ||
} | ||
let pbxproj = try XcodeProj(pathString: (project.basePath + Path(reference.path).normalize()).string).pbxproj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right about not being able to import GenerationError
. We can just leave this as it is for now
PBXGroup( | ||
children: subprojectFileReferences, | ||
sourceTree: .group, | ||
name: "Projects" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now it's ok 👍
@@ -78,6 +79,7 @@ | |||
66C3C5E3C13325F351A3008F /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = F2950763C4C568CC85021D18 /* module.modulemap */; }; | |||
6E8F8303759824631C8D9DA3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9E17D598D98065767A04740F /* Localizable.strings */; }; | |||
7148A4172BFA1CC22E6ED5DB /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 753001CDCEAA4C4E1AFF8E87 /* MainInterface.storyboard */; }; | |||
715DD7C4C194A04A5C4049EF /* ExternalTarget.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3DCDCD083AABD1D30EA34576 /* ExternalTarget.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there supposed to be 2 build files added? As these are referencing the same PBXFileReference, XcodeProj can't give them a deterministic id hence the failing diff tests.
If they both need to be there then XcodeProj needs to be updated to take into account something that is different about them like the settings
. That has to be done here https://github.com/tuist/XcodeProj/blob/master/Sources/XcodeProj/Utils/ReferenceGenerator.swift#L290
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, one is for linking and the other is to embed it. I notice this is also the case for Framework2.framework in that test project, but it does not cause a failing diff test. Any idea why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be fixed in tuist/XcodeProj#518. Will update this PR once that is merged.
Sources/ProjectSpec/Linkage.swift
Outdated
|
||
extension PBXTarget { | ||
|
||
public var defaultLinkage: Linkage { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same logic as above. Let's combine to an extension on PBXProductType
in this file
|
||
let embed = dependency.embed ?? target.shouldEmbedDependencies | ||
func processTargetDependency(_ dependency: Dependency, dependencyTarget: Target, embedFileReference: PBXFileElement) { | ||
let dependencyLinkage = dependencyTarget.defaultLinkage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just use the following once defaultLinkage is extracted to PBXProductType
in Linkage.swift:
let dependencyLinkage = dependencyTarget.productType.defaultLinkage ?? .none
ab0cc74
to
8cb1f5a
Compare
@yonaskolb Updated to the latest XcodeProj and tests are passing now 🎉 |
I've started to look at
"Application"
"Framework"
I did use evandcoleman's branch here: https://github.com/evandcoleman/XcodeGen/tree/edc-external-target-dependency The issue with the scheme exists still (could be user error of course). The difference is a group called Projects is created with the subproject. Definitely better, but would be helpful to be able to define where to place it. |
@mobileben I believe the issue you are seeing is not related to this PR. This PR relates to depending on targets from subprojects. The feature to create schemes based on external targets was done in #655. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work @evandcoleman!
I've just fixed some small conflicts and added a note in the docs
Thanks @yonaskolb! |
Resolves #570
This builds upon the work done in #655 by allowing target dependencies to reference targets in other Xcode projects.
Motivation
At my company, we have several internal dependencies that we include via submodules. We'd like the ability to include these dependencies as subprojects and reference their targets in our main Xcode project.
Changes
As introduced in #655, subprojects are declared at the top level.