Add Xcode projects support for some Tuist features

We believe that Tuist projects are still the best way to manage your Xcode projects – but we also want any organization out there that works with Xcode to benefit from some of the Tuist features without having to go through the full migration to Tuist project.

Tuist Previews are a first such feature, but can we add support for Xcode projects in some of our existing features? I believe we can.

Xcode projects → XcodeGraph

XcodeGraph is already a piece that’s not specific to Tuist projects – and that’s often the only data input that some of our features like tuist inspect implicit-imports or tuist graph need.

During project generation, XcodeGraph is converted to XcodeProj. Can we go the other direction? Can we read an Xcode project into the XcodeProj format and then convert it to XcodeGraph?

If we can, then the inspect implicit-imports and tuist graph could be used outside of the context of Tuist projects. And for example, the interactive graphs that @ajkolean has been proposing could be used by the whole iOS community as well!

Conversion implementation

Most of XcodeGraph models are properties like resources, sources, settings, etc. All of those should be relatively straightforward to migrate from XcodeProj definition. For example, sources are directly represented by the sourcesBuildPhase.

To load the dependency graph, we can use the Link binary with libraries build phase. However, a lot of projects suffer from implicit dependencies, so the graph might be incomplete. We’d need to strongly recommend developers to use the inspect implicit-imports command to ensure other commands like tuist graph are accurate.

Structuring work

I’d suggest to develop the conversion inside the XcodeGraph repository. We can take some inspiration from xcdiff that uses XcodeProj to read and compare Xcode projects.

SPM projects

External SPM dependencies would be represented as external dependencies in the XcodeGraph. The graph knowledge would sort of end at the edges of the SPM graph. But what about projects that use SPM for managing most of their projects? Wouldn’t it be great if they could benefit from features like tuist graph as well?

To that I say – yes! But the story is a bit more complicated there.

There are two components to this:

  • SPM graph itself
  • The touchpoints between Xcode graph and SPM graph

SPM graph is different from Xcode graph – we could technically convert it to XcodeGraph to reuse most of our utilities, but it could make things more complex, especially for projects that are purely written in SPM. I believe such work will need deeper exploration and thinking.

I can see having another package called swift-package-manager-graph that would be for solely representing the SPM graph (or maybe that’s something that’s already in swift-package-manager repository?). For projects that are partly managed by SPM and partly by Xcode, we would either need to convert SPM graphs to XcodeGraph or we would need to work with two graphs seperately. I think the former might be easier, but again, this needs some deeper thinking and exploration.

Feedback

What do you think about this proposal? Is the support of Xcode projects for some of Tuist features worth the investment and maintenance?

Any blind spots that I have missed?

I’ve actually been developing a conversion tool externally that transforms Xcode projects from XcodeProj to XcodeGraph. I started this to make graph representations easier and streamline testing processes. If it fits with your goals, I’m happy to open a PR to include this functionality directly in the XcodeGraph repository.

For SPM projects, I’m using swift package dump-package to parse and convert dependencies into XcodeGraph. While integrating SPM does add some complexities, especially for projects primarily managed by SPM, I’m optimistic about creating a unified graph that works for both Xcode and SPM-managed projects.

I believe this enhancement will not only support features like tuist inspect implicit-imports and tuist graph beyond Tuist projects but also help the broader iOS community, including the interactive graphs we’ve been discussing.

Yes, totally! That would be amazing.

While integrating SPM does add some complexities, especially for projects primarily managed by SPM, I’m optimistic about creating a unified graph that works for both Xcode and SPM-managed projects.

Converting SPM targets into XcodeProj targets is not that straightforward. I agree we should aim to have a unified graph, but I’d try to find a solution where SPM modules/nodes are not converted to XcodeProj-targets.

For SPM projects, I’m using swift package dump-package to parse and convert dependencies into XcodeGraph.

This works for fully SPM-based projects. Then there’s the additional complexity of Xcode projects that have local and remote packages integrated via the Xcode GUI. It’s probably still possible to use swift dump-package by getting the location of those packages from pbxproj and running the command there – but not sure how that would work for remote packages. Remote packages can also be represented differently than local ones as it’s not that important to get a full subtree of an external dependency.

1 Like

Building on our conversation, I was wondering if this could further streamline the migration process for users transitioning from traditional Xcode projects to Tuist. What are your thoughts on introducing a dedicated migration command like:

tuist migrate from-xcodeproj /path/to/MyApp.xcodeproj

How It Might Work

1. Automated Conversion

  • Parsing .pbxproj: The command could use a tool to parse the existing .pbxproj file and generate an XcodeGraph representation.
  • Generating Tuist Manifests: From the XcodeGraph, it could automatically create the necessary Project.swift, Tuist.swift, and Package.swift files, capturing the project structure, targets, dependencies, and build settings.

2. Handling Dependencies

  • SPM and Xcode Dependencies: The tool could differentiate between dependencies managed by Swift Package Manager (SPM) and those managed directly by Xcode, ensuring each is accurately represented in the XcodeGraph.
  • External Dependencies: For remote packages, it might utilize swift package dump-package to incorporate these dependencies into the Package.swift file.

3. Validation and Cleanup

  • Build Settings Extraction: Automatically extract and migrate build settings into .xcconfig files, following the current migration guidelines.
  • Dependency Graph Validation: Use tuist inspect implicit-imports to ensure all dependencies are correctly captured, including any implicit ones not explicitly defined in the .pbxproj.

4. Interactive Review

  • Generated Files Review: After migration, users could review the generated Tuist manifest files (Project.swift, Tuist.swift, Package.swift) to make any necessary adjustments or optimizations.

Potential Benefits

  • Lower Migration Barrier: Automating the conversion from .pbxproj to XcodeGraph could reduce the manual effort required, making Tuist more accessible to projects with existing Xcode configurations.
  • Consistency and Reliability: Ensures the migrated Tuist project accurately reflects the original Xcode project’s structure and dependencies.
  • Enhanced Developer Experience: Simplifies the migration process, allowing developers to adopt Tuist’s project management features more easily.

If we can reliably and accurately convert to XcodeGraph from .pbxproj files, this should be possible, right? Am I missing anything here?

We considered this a few times, and it’d be a dream for many teams and developers–a function that maps between domains. However, we never executed it because implementing it reliably with the many Xcode project scenarios out there would be quite challenging and costly to maintain. I might be wrong here.

There’s also always the question of what the future holds and how much we should invest in developing and maintaining the workflow if we consider that future. However, there’s no clarity in that future. We live now in a world with two graphs, Xcode projects, and SPMs, and we see no signs of unification. So this poses the question: Should we bring the benefits of Tuist to Xcode projects and SPM packages or, the other way around, bring Xcode projects and SPM to Tuist projects?

Just to add to this, XcodeProjXcodeGraph is a lossy conversion. Not everything described in XcodeProj can be fined in XcodeGraph. For example, how things are embedded is a decision made by Tuist during generation and it’s not directly encoded in XcodeGraph. It might be worth trying and it might very well work for smaller/clean projects, but those that are larger/legacy will be … let’s say tough :sweat_smile:

But anything that eases the migration is worth exploring, but smaller improvements, liek tuist inspect implicit-imports support for .pbxproj might strike a better balance between the investment it takes to implement + maintain and the benefits users get out of it.