Overview
Dependencies in Tuist can be internal (between your own targets) or external (third-party packages and frameworks). Tuist provides a robust dependency management system that validates your dependency graph and prevents common issues.Why Tuist’s Approach is Different
Unlike Xcode projects where dependency graphs can be error-prone and implicit, Tuist makes dependencies explicit and static. This enables:- Validation: Automatic detection of cycles and invalid dependencies
- Optimization: Binary caching and selective testing
- Consistency: Guaranteed correct linking and embedding
- Simplicity: Focus on what depends on what, not implementation details
Internal Dependencies
Internal dependencies are connections between targets in your project.Dependency Types
When defining a target, use thedependencies parameter with these types:
Conditional Dependencies
Link dependencies only for specific platforms:Project.swift
Dependency Graph Best Practices
Layered Architecture
Organize dependencies in clear layers:Visualize Your Graph
Use Tuist’s graph command to understand dependencies:External Dependencies
Tuist supports multiple ways to integrate external dependencies.Swift Packages (Recommended)
Swift Packages are the recommended approach for external dependencies.XcodeProj-Based Integration
Tuist’s default integration method provides more control and enables caching:Xcode’s Default Integration
For simpler projects or when you need Xcode’s native SPM integration:Project.swift
.runtime- Standard dependency.macro- Swift macros.plugin- Build tool plugins
Build Tool Plugin Example
Project.swift
Binary Targets
Include binary frameworks directly in Package.swift:Tuist/Package.swift
Carthage
Integrate Carthage dependencies as frameworks:CocoaPods
Integrate CocoaPods after generating the project:Static vs Dynamic Linking
The choice between static and dynamic linking significantly impacts app size and boot time.General Guidelines
- Release builds: Link as much as possible statically for fast boot times
- Debug builds: Link as much as possible dynamically for fast iteration
Configuring Linking Type
Use environment variables to change linking at generation time:Project.swift
Special Scenarios
Apps with Extensions
Shared code between app and extensions should be dynamic to avoid duplication:Project.swift
Static Side Effects
Troubleshooting
Objective-C Dependencies
Objective-C dependencies may require the-ObjC linker flag:
Project.swift
Firebase and Google Libraries
Add -ObjC Flag
Project.swift
Configure FBLPromises
SetFBLPromises to dynamic framework:
Tuist/Package.swift
The Composable Architecture
Link all TCA dependencies dynamically:Tuist/Package.swift
With this configuration, import
SwiftSharing instead of Sharing.Transitive Static Dependencies
When a dynamic framework depends on static ones, useinternal import (Swift 6+):
@_implementationOnly:
Dependencies Not Resolving
Best Practices
On CI: Force Resolved Versions
Ensure deterministic builds:CI Script
Keep Dependencies Updated
Regularly update and test:Version Pinning Strategy
Tuist/Package.swift
Document Special Configurations
Create aDEPENDENCIES.md file:
DEPENDENCIES.md
Next Steps
Optimize Builds
Enable binary caching for faster builds
Project Structure
Learn how to organize your dependency graph
Set Up CI/CD
Configure CI for dependency management
Migrate from Xcode
Migrate existing dependencies to Tuist