Need/problem
Currently, the tuist edit
command generates a project that includes only the Tuist/Package.swift
file. While this is useful for editing the Tuist manifests, it does not support workflows where the Tuist/Package.swift
file references other Package.swift
files. As a result:
- Developers lose Xcode’s code completion and navigation support for these additional
Package.swift
files. - Editing interconnected Swift packages becomes cumbersome, requiring either using a separate editor or opening the external
Package.swift
in a separate instance of Xcode, which leads to Xcode resolving the packages (wastefully) and producing a separate, irrelevantPackage.resolved
file.
For example, in a setup where Tuist/Package.swift
depends on PackageA.swift
and PackageB.swift
, these additional package manifests are not included in the generated project. This limitation makes it a little confusing for other developers to follow how things are set up and where various external dependencies live.
Motivation
The motivation for this proposal is to streamline workflows involving multiple Swift package manifests and improve the developer experience by leveraging Xcode’s code completion and navigation features.
Detailed design
Proposed Solution
Enhance the tuist edit
command to support the optional inclusion of additional Package.swift
files in the generated project. This can be achieved by:
- Command-Line Argument
Adding a new flag totuist edit
to specify additionalPackage.swift
files:tuist edit --include-packages path/to/PackageA.swift path/to/PackageB.swift
This is not my preferred approach, since developers will need to do this often and would essentially require tooling in front of tuist to make seamless.
- Configuration-Based Inclusion using Tuist.swift
Something like this could work.
let tuist = Tuist(
project: .tuist(
additionalPackageManifests: ["PackageA.swift", "PackageB.swift"]
)
)
Though my preferred approach would be for this to be automatic…
- Automatic Detection
Automatically detecting and including referenced Package.swift
files from Tuist/Package.swift
if feasible. For example, parsing the manifest to identify dependencies and including their manifests in the generated project.
This could be accomplished with swift package describing --type json
and parsing the "dependencies"
key, for instance:
...
"dependencies" : [
{
"identity" : "components",
"path" : "/Users/ben/myproj/components",
"type" : "fileSystem"
}
],
Using this we could infer that there is a Package.swift
to include at components/Packages.swift
Note: recursive local packages would not be expected to be supported with this approach
Implementation Notes
- Update the
tuist edit
logic to:- Include any referenced packages from
Tuist/Package.swift
- Add these package manifests to the generated Xcode project.
- Ensure backward compatibility by making this feature configurable via
Tuist.swift
- Include any referenced packages from
Example Workflow
-
A project has the following structure:
├── Tuist │ ├── Package.swift ├── PackageA │ ├── Package.swift ├── PackageB ├── Package.swift
-
Run the enhanced
tuist edit
command:tuist edit
-
The generated Xcode project includes
Tuist/Package.swift
,PackageA.swift
, andPackageB.swift
, providing full code completion and navigation support in Xcode.
Drawbacks
- Implementation Complexity: Adding support for multiple
Package.swift
files increases the complexity of thetuist edit
implementation. - A change in
Tuist.swift
would be a breaking change
Alternatives
- Manual Inclusion: Developers can manually open additional
Package.swift
files in separate Xcode projects. However, this is tedious and disrupts workflow continuity. Additionally it produces unnecessary Package resolutions and aPackage.resolved
that is more confusing. - Embed all dependencies in
Tuist/Package.swift
– this is also not currently a valid approach, as these dependencies won’t be understood asexternal
if they are listed in theproducts
section, onlydependencies
. - Do Nothing: Continue with the current behavior, leaving developers to work around the limitation. This negatively impacts productivity and developer experience.
Adoption strategy
This feature is non-breaking and entirely optional. Existing Tuist developers can continue using tuist edit
as before without any changes. To adopt the feature, developers can:
How we teach this
- Documentation: Update the
tuist edit
documentation to include a section about this behavior, updatedTuist.swift
API documentation (if needed).
One major benefit of this approach is that you don’t need to know about it, it can “just work” and would be fairly obvious to users, similar to how a Project.swift
gets picked up automatically.
This feature aligns with existing Tuist patterns and does not require significant reorganization of Tuist documentation or teaching materials.