Hive Hive
Sign in

Duplicate Symbols when Linking Static SPM Dependency into Shared Framework Target

GitHub issue · Open

Metadata
Source
tuist/tuist #8504
Updated
Jun 11, 2026
Domains
Generated projects
Details

What happened?

We stumbled over a very strange linking issue when (finally) trying to migrate from ancient Package enum to modern Package.swift approach leading to multiple runtime warnings like this (and subsequent casting failures and crashes):

<SPMDependency.SomeThing> is implemented in both _ and _. This may cause spurious casting failures and mysterious crashes. One of the duplicates must be removed or renamed.

This is somewhat similar to https://github.com/tuist/tuist/issues/6339 and maybe also https://github.com/tuist/tuist/issues/6081, but not quite the same I think.

How do we reproduce it?

The same will likely happen with any iOS app project that has

  • multiple layers of dynamic framework targets, like Framework A depends on B depends on C
  • where C depends on some static, non-binary SPM library product P
  • and some part of P is used by A and/or B

Error log

<SPMDependency.SomeThing> is implemented in both _ and _. This may cause spurious casting failures and mysterious crashes. One of the duplicates must be removed or renamed.

macOS version

15.6.1

Tuist version

4.89.0

Xcode version

26.0 and 16.4

Comments
L
linear[bot] Oct 23, 2025
D
dosubot[bot] Oct 23, 2025

Hi @iteracticman! I’m Dosu and I’m helping the tuist team.

This issue is caused by static SPM libraries being linked into multiple dynamic frameworks, which leads to duplicate symbol warnings and runtime crashes when those frameworks are used together. The migration from the old Package enum to the modern Package.swift approach in Tuist gives you more flexibility, but also requires more explicit management of how dependencies are linked.

Tuist currently does not automatically deduplicate or propagate product types for nested SPM dependencies, so static libraries can end up linked in multiple places in your dependency graph. This is especially problematic in multi-layered dynamic frameworks where a static SPM product is used by more than one layer. The result is the runtime warning and casting failures you’re seeing.

Workarounds include: explicitly setting the product type for all relevant SPM dependencies (including nested ones) to .framework (dynamic) in your PackageSettings, or restructuring your dependency graph to avoid sharing static SPM libraries across multiple dynamic frameworks. You may also need to ensure that all transitive dependencies are explicitly declared in your Tuist target dependencies, as Tuist does not support implicit imports and will not resolve them recursively for you [source 1] [source 2].

There is ongoing discussion about making this more automatic in Tuist, but for now, careful manual configuration is required to avoid these duplicate symbol issues. If you use custom xcconfig files, make sure they include all necessary search paths and linker flags, as missing settings can also cause or exacerbate linking problems [source 3].

To reply, just mention @dosu.


Docs are dead. Just use Dosu.

Leave Feedback Ask Dosu about tuist Share Dosu with your team

I
iteracticman Oct 30, 2025

If this can’t be fully solved by Tuist in a reasonable way, maybe it could at least emit warnings/errors at generation time?

I’d consider this pretty important since this is very unexpected and could lead to serious, hard to debug runtime issues for anyone trying to migrate from SPM to Tuist, expecting everything would basically work like before.

D
dosubot[bot] Oct 30, 2025

Tuist already has generation-time linting that emits warnings when static products (like SPM libraries) are linked from multiple targets, since this can cause unwanted side effects or duplicate symbols. This is handled by the StaticProductsGraphLinter and related linting infrastructure, which runs during project generation and can flag problematic static dependencies before you hit runtime issues. You can see this in action with warnings about SwiftSyntax or other static targets being linked from multiple places [source].

Currently, these warnings are focused on certain scenarios (like macros or SwiftSyntax), but the mechanism could be extended to cover more cases—such as static SPM dependencies that are linked into multiple dynamic frameworks, which is the root of your issue. The linting system is modular and already checks for duplicated product names and other dependency graph problems at generation time [source].

So, while Tuist doesn’t yet emit a specific warning for your exact scenario, the infrastructure is there and could be enhanced to catch these duplicate symbol/static SPM dependency issues at generation time. This would help prevent the kind of hard-to-debug runtime problems you described, especially for teams migrating from SPM to Tuist who expect similar safety guarantees.

To reply, just mention @dosu.


Docs are dead. Just use Dosu.

Leave Feedback Ask Dosu about tuist Share Dosu with your team

P
pepicrft Nov 5, 2025

If this can’t be fully solved by Tuist in a reasonable way, maybe it could at least emit warnings/errors at generation time?

I’d consider this pretty important since this is very unexpected and could lead to serious, hard to debug runtime issues for anyone trying to migrate from SPM to Tuist, expecting everything would basically work like before.

@iteracticman the graph that you are trying to declare is not valid, and the warning is connected to that. We can’t be more specific about what the impact of that is because we don’t know at generation time. It could be your app is just larger, or it could be that the app blows up. What would you expect Tuist to do in this case?

I
iteracticman Nov 5, 2025

Hmm, maybe I am not fully understanding the problem, but I thought it should be relatively easy to detect this (potential) issue at generation-time. It happens whenever a framework depends on a framework that depends on a static SPM library. (Which btw I would have expected to be perfectly valid, especially since it works perfectly fine when using native SPM).

P
pepicrft Nov 26, 2025

@iteracticman I tried the repo linked above with tuist 4.107.2 and I don’t get any issues neither at generation time nor at runtime. Could you try to reproduce it with that version?