# Xcode previews do not work anymore after porting the project to Tuist

**URL:** https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277
**Category:** Troubleshooting & how to
**Created:** [December 16, 2024, 5:12pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277 "2024-12-16T17:12:22Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![nathan-sofia](https://community.tuist.dev/letter_avatar_proxy/v4/letter/n/e0b2c6/32.png) [@nathan-sofia](https://community.tuist.dev/u/nathan-sofia)
#### Post date: [December 16, 2024, 5:12pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/1 "2024-12-16T17:12:22Z")

</div>

# Question or problem

I tried to port our project to Tuist to see if the using cache would improve our build times (it does, by 53% 🎉 ).

However, Xcode previews do not work anymore.

It’s important to note that our code is split in multiple local small Swift packages (actually they are multiple targets inside a single SPM package) + a big app target. So in order to use previews, we have to first select the scheme corresponding to the target. Then, previews work. The big app target is too big and previews never worked (it loads indefinitely and we never figured out why).

When porting the project to Tuist, I turned each local Swift package into a static library target. However when I select the scheme corresponding to a target, previews no longer work (they build but they don’t start).

Changing the preview driver to the legacy one doesn’t work because it’s unable to preview “plain” static libraries (it worked before because they were Swift packages targets).

The error logs are below.

# Expectation

I expect the previews to work as they do in the project, as they do without using Tuist.

# Context

- Tuist version: 4.37.0
- Xcode version: 16.1.0

## Reproduction (mandatory for problems)

```auto
== PREVIEW UPDATE ERROR:

    [Remote] JITError: Runtime linking failure
    
    Additional Link Time Errors:
    Symbols not found: [___isPlatformVersionAtLeast]
    Symbols not found: [___isPlatformVersionAtLeast]
    In static-UITools, failed to materialize { _$sSS15SwiftRichStringE3set5style5rangeSo019NSMutableAttributedC0CSgSS_So8_NSRangeVSgtF }, due to unsatisfied dependencies { (static-UITools, { _$s15SwiftRichString13StylesManagerC6sharedACvau }) } (dependencies removed or in error state)
    
    ==================================
    
    | [Remote] LLVMError
    |  
    | LLVMError: LLVMError(description: "Failed to materialize symbols: { (static-UITools, { __replacement_tag$429 }) }")

== VERSION INFO:

    Tools: 16B40
    OS: 24B91
    PID: 44580
    Model: MacBook Pro
    Arch: arm64e

== ENVIRONMENT:

    openFiles = [
        /Redacted.swift
    ]
    wantsNewBuildSystem = true
    newBuildSystemAvailable = true
    activeScheme = UITools
    activeRunDestination = iPhone 16 Pro variant iphonesimulator arm64
    workspaceArena = [x]
    buildArena = [x]
    buildableEntries = [
        libUITools.a
    ]
    runMode = JIT Executor

== SELECTED RUN DESTINATION:

    Simulator - iOS 18.1 | iphonesimulator | arm64 | iPhone 16 Pro | no proxy

== EXECUTION MODE OVERRIDES:

    Workspace JIT mode user setting: true
    Falling back to Dynamic Replacement: false

== JIT LINKAGE:

    Run Destination: B696D6E3-9E09-4373-BF5B-277CA73071F6-iphonesimulator18.1-arm64-iphonesimulator
    JIT Link Description {
        10:libUITools.a [
            4:libAudioTools.a
            6:libModels.a
            5:libReporting.a
            2:libResources.a
            3:libTools.a
        ]
    }
    
== Truncated for brevity, if the rest is necessary I can provide it

```

`UITools` is the name of the target I am trying to preview. The different `libXXX.a` files are local dependencies of `UITools` (so other local targets in the project).

SwiftRichString in a SPM dependency that’s added to the target. It builds fine outside of previews. It’s missing from JIT LINKAGE, maybe this is the issue?

---

<div class="post-metadata">

### Author: ![marekfort](https://community.tuist.dev/user_avatar/community.tuist.dev/marekfort/32/8_2.png) [@marekfort](https://community.tuist.dev/u/marekfort)
#### Post date: [December 17, 2024, 2:54pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/2 "2024-12-17T14:54:23Z")

</div>

> [@nathan-sofia](#):
>
> I tried to port our project to Tuist to see if the using cache would improve our build times (it does, by 53% 🎉 ).

This is amazing 👏

> When porting the project to Tuist, I turned each local Swift package into a static library target.

Previews work better with dynamic frameworks – you can use Tuist’s support for environment variables to switch between dynamic and static frameworks easily by running a command such as `TUIST_DEFAULT_FRAMEWORK_TYPE="static" tuist generate` and then reading the environment variable in your `Project.swift` or `Package.swift` manifest to change the type at generation time. @pepicrft described this approach in more detail [here](https://community.tuist.dev/t/implicit-dependencies-declaration/91/2).

> In static-UITools, failed to materialize { \_$sSS15SwiftRichStringE3set5style5rangeSo019NSMutableAttributedC0CSgSS\_So8\_NSRangeVSgtF }

This suggests to me that some of the static symbols are stripped. This is because SwiftPM by default passes `GENERATE_MASTER_OBJECT_FILE=YES`. What this build setting does is that it disables code stripping of static libraries. This does help with some runtime failures but it also unnecessarily increases your binary size. We don’t recommend setting that value across the board, but some libraries end up working better with it. We considered making that a default to align with SwiftPM or at least adding an easy opt-in but we haven’t got around doing that, yet. There’s an issue for this, however: [Include a generation option to enable the generation of the master object file · Issue #6777 · tuist/tuist · GitHub](https://github.com/tuist/tuist/issues/6777)

What you can do and what I would recommend trying is setting that flag for the particular dependency in your `Package.swift` using Tuist’s [PackageSettings](https://docs.tuist.dev/en/references/project-description/structs/packagesettings#packagesettings):

```swift
// Tuist/Package.swift
import PackageDescription

#if TUIST
import ProjectDescription

let packageSettings = PackageSettings(
  targetSettings: ["SwiftRichString": ["GENERATE_MASTER_OBJECT_FILE": true]]
)

#endif

let package = Package(...)

```

I am quite sure either switching your libraries to dynamic or adding the `GENERATE_MASTER_OBJECT_FILE` setting should fix your issue – but preview failures are sometimes hard to pin down, so let me know if neither works for you.

---

<div class="post-metadata">

### Author: ![nathan-sofia](https://community.tuist.dev/letter_avatar_proxy/v4/letter/n/e0b2c6/32.png) [@nathan-sofia](https://community.tuist.dev/u/nathan-sofia)
#### Post date: [December 18, 2024, 10:04am UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/3 "2024-12-18T10:04:29Z")

</div>

Thank you for your reply!

Here is the summary of what I’ve tried:

### Static libraires with GENERATE\_MASTER\_OBJECT\_FILE

Previews do not start when the main scheme is selected, there is an infinite spinner (as usual).

When the right target scheme is selected, there is the same “Runtime linking failure” with the following error:

```auto
== PREVIEW UPDATE ERROR:

    [Remote] JITError: Runtime linking failure
    
    Additional Link Time Errors:
    Symbols not found: [___isPlatformVersionAtLeast]
    Symbols not found: [___isPlatformVersionAtLeast]
    Symbols not found: [___isPlatformVersionAtLeast]
    
    ==================================
    
    | [Remote] LLVMError
    |  
    | LLVMError: LLVMError(description: "Failed to materialize symbols: { (static-UITools, { __replacement_tag$429 }) }")

```

The `SwiftRichString` errors are gone but it’s not enough to make previews work.

### Switching to dynamic frameworks

It works, I can use previews from both the target scheme and the main app scheme (which was never possible under regular Xcode) 🎉

However when running `tuist generate` I have the following warnings:

```auto
 · Xcframework 'GoogleAppMeasurement.xcframework' has been linked from target 'Redacted' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Xcframework 'SwiftCompilerPluginMessageHandling.xcframework' has been linked from target 'CommonScenes', target 'Models', target 'Tools', and target 'UITools', it is a static product so may introduce unwanted side effects.
 · Xcframework 'SwiftDiagnostics.xcframework' has been linked from target 'CommonScenes', target 'Models', target 'Tools', and target 'UITools', it is a static product so may introduce unwanted side effects.
 · Xcframework 'SwiftSyntax509.xcframework' has been linked from target 'Models', target 'Tools', and target 'UITools', it is a static product so may introduce unwanted side effects.
 · Xcframework 'GoogleAppMeasurementIdentitySupport.xcframework' has been linked from target 'AlbusAir' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Xcframework 'SwiftCompilerPlugin.xcframework' has been linked from target 'Models', target 'Tools', and target 'UITools', it is a static product so may introduce unwanted side effects.

```

And so on, there is one line per external dependency per target.

I assume this is because my cache was generated _before_ I switched to dynamic frameworks.

I tried running `tuist cache` again after making the change to dynamic frameworks to see if it would make the warning disappear, and I noticed that Tuist now creates a cache for all internal targets. Which is not something that I want.

So I ran `tuist cache --external-only` and it says `All cacheable targets are already cached` which seems correct.

So can I safely ignore that warning? Or are there additional steps I need to take to ensure the cache has the right format for frameworks _and_ static libraries (because I want the CI/CD to keep using static libraries)?

---

<div class="post-metadata">

### Author: ![marekfort](https://community.tuist.dev/user_avatar/community.tuist.dev/marekfort/32/8_2.png) [@marekfort](https://community.tuist.dev/u/marekfort)
#### Post date: [December 18, 2024, 10:11am UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/4 "2024-12-18T10:11:51Z")

</div>

> [@nathan-sofia](#):
>
> The `SwiftRichString` errors are gone but it’s not enough to make previews work.

It’s not clear to me where those symbols exactly are coming from, so not sure what else you could do. But dynamic frameworks are either way preferred for local development.

> [@nathan-sofia](#):
>
> So can I safely ignore that warning? Or are there additional steps I need to take to ensure the cache has the right format for frameworks _and_ static libraries (because I want the CI/CD to keep using static libraries)?

This should have been fixed in [Do not output warnings for cache xcframeworks linked mulitple times by fortmarek · Pull Request #7158 · tuist/tuist · GitHub](https://github.com/tuist/tuist/pull/7158). Try upgrading to tuist `4.38.1` – those warnings should hopefully be gone. Yes, they should be false positives and can be safely ignored.

---

<div class="post-metadata">

### Author: ![nathan-sofia](https://community.tuist.dev/letter_avatar_proxy/v4/letter/n/e0b2c6/32.png) [@nathan-sofia](https://community.tuist.dev/u/nathan-sofia)
#### Post date: [December 18, 2024, 10:53am UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/5 "2024-12-18T10:53:27Z")

</div>

After updating to Tuist 4.38.1 and rebuilding the cache, most of the warnings are gone but they remain for some dependencies (mainly Google / Firebase ones):

```auto
The following warnings need attention:
 · Target 'GoogleUtilities-UserDefaults' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'FirebaseCoreInternal' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleAppMeasurementTarget' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleUtilities-Logger' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'Firebase' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleUtilities-Environment' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleUtilities-Network' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Xcframework 'GoogleAppMeasurementIdentitySupport.xcframework' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'FirebaseCore' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleUtilities-NSData' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'FirebaseInstallations' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleUtilities-Reachability' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleUtilities-AppDelegateSwizzler' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'GoogleUtilities-MethodSwizzler' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Xcframework 'GoogleAppMeasurement.xcframework' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'nanopb' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'FirebaseAnalyticsTarget' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'third-party-IsAppEncrypted' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'FBLPromises' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Xcframework 'FirebaseAnalytics.xcframework' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'FirebaseAnalyticsWrapper' has been linked from target 'MainAppTarget' and target 'Reporting', it is a static product so may introduce unwanted side effects.
 · Target 'SwiftRichString' has been linked from target 'MainAppTarget' and target 'UITools', it is a static product so may introduce unwanted side effects.
 · Target 'BetterSegmentedControl' has been linked from target 'MainAppTarget' and target 'SofiaBetterSegmentedControl', it is a static product so may introduce unwanted side effects.

```

Notice how they are worded differently. Are they not false positives?

---

<div class="post-metadata">

### Author: ![marekfort](https://community.tuist.dev/user_avatar/community.tuist.dev/marekfort/32/8_2.png) [@marekfort](https://community.tuist.dev/u/marekfort)
#### Post date: [December 18, 2024, 11:10am UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/6 "2024-12-18T11:10:41Z")

</div>

I believe those are not false positives. You should see those warnings even when you generate a project with `tuist generate --no-binary-cache` and with your internal targets being dynamic.

You can change the product types of most of those dependencies to dynamic using the `PackageSettings.productTypes`: [https://docs.tuist.dev/en/references/project-description/structs/packagesettings#packagesettings](https://docs.tuist.dev/en/references/project-description/structs/packagesettings#packagesettings). However, you can’t change the product type for some of the prebuilt frameworks like `FirebaseAnalytics.xcframework`. You can ignore those warnings as long as you use static frameworks when building for release.

---

<div class="post-metadata">

### Author: ![nathan-sofia](https://community.tuist.dev/letter_avatar_proxy/v4/letter/n/e0b2c6/32.png) [@nathan-sofia](https://community.tuist.dev/u/nathan-sofia)
#### Post date: [December 18, 2024, 12:13pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/7 "2024-12-18T12:13:04Z")

</div>

It looks like I have to specify the product type for transitive dependencies too, which is annoying.

Is there a way to specify the default product type for all products, without specifying their name?

Also how does this affect the cache? I noticed the cache needed to be rebuilt when I added the product type. Does that mean that caching is dependent on the product type? Which would make sense.

---

<div class="post-metadata">

### Author: ![marekfort](https://community.tuist.dev/user_avatar/community.tuist.dev/marekfort/32/8_2.png) [@marekfort](https://community.tuist.dev/u/marekfort)
#### Post date: [December 18, 2024, 12:28pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/8 "2024-12-18T12:28:49Z")

</div>

> [@nathan-sofia](#):
>
> It looks like I have to specify the product type for transitive dependencies too, which is annoying.

Yes, I undestand that’s annoying. There’s an issue, so that transitive dependencies respect the product type of their parent, however, we haven’t had the chance to implement it, yet: [When using cached xcframeworks for SPM packages, nested packages don't respect product type of their parent. · Issue #6638 · tuist/tuist · GitHub](https://github.com/tuist/tuist/issues/6638)

> [@nathan-sofia](#):
>
> Is there a way to specify the default product type for all products, without specifying their name?

Currently, no. But it’s something we could add and we would accept a contribution for that. There’s an issue for that as well: [SPM Targets with `automatic` product type is always fixed to `static` product type · Issue #6616 · tuist/tuist · GitHub](https://github.com/tuist/tuist/issues/6616)

> [@nathan-sofia](#):
>
> Does that mean that caching is dependent on the product type?

Yes, that is correct.

---

<div class="post-metadata">

### Author: ![nathan-sofia](https://community.tuist.dev/letter_avatar_proxy/v4/letter/n/e0b2c6/32.png) [@nathan-sofia](https://community.tuist.dev/u/nathan-sofia)
#### Post date: [December 18, 2024, 12:46pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/9 "2024-12-18T12:46:18Z")

</div>

Okay thanks, I think I’ll leave it at that and ignore the warnings locally.

Last question, is there a way to default to `--external-only` when running `tuist cache` so that I don’t have to specify the option every time? That would also prevent from running `tuist cache` without `--external-only`, to guarantee that our internal frameworks are never cached by mistake.

---

<div class="post-metadata">

### Author: ![marekfort](https://community.tuist.dev/user_avatar/community.tuist.dev/marekfort/32/8_2.png) [@marekfort](https://community.tuist.dev/u/marekfort)
#### Post date: [December 18, 2024, 12:56pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/10 "2024-12-18T12:56:52Z")

</div>

Not right now. We should add support for making that configurable through environment variables like we do for most of our other commands. Would you mind raising an issue?

Once implemented, you should be able to do the following:

```sh
export TUIST_CACHE_EXTERNAL_ONLY=true

tuist cache # by default uses external only as long as the above variable is defined

```

---

<div class="post-metadata">

### Author: ![nathan-sofia](https://community.tuist.dev/letter_avatar_proxy/v4/letter/n/e0b2c6/32.png) [@nathan-sofia](https://community.tuist.dev/u/nathan-sofia)
#### Post date: [December 18, 2024, 1:00pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/11 "2024-12-18T13:00:29Z")

</div>

Sure I will raise an issue.

I would personally prefer an option inside `Tuist.swift` over an environment variable because that way I’m sure the setting is always set. New contributors to my project can’t forget to set it, and it doesn’t add an additional step to the project setup.

---

<div class="post-metadata">

### Author: ![marekfort](https://community.tuist.dev/user_avatar/community.tuist.dev/marekfort/32/8_2.png) [@marekfort](https://community.tuist.dev/u/marekfort)
#### Post date: [December 18, 2024, 2:02pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/12 "2024-12-18T14:02:47Z")

</div>

> [@nathan-sofia](#):
>
> I would personally prefer an option inside `Tuist.swift` over an environment variable because that way I’m sure the setting is always set. New contributors to my project can’t forget to set it, and it doesn’t add an additional step to the project setup.

We try to keep the options in `Tuist.swift` limited. The environment variables for tuist flags and options are preferred as they scale easily without bloating the interface of our configuration files.

I understand it’s an extra thing you have to configure, but if you end up using Mise, that’s really easy to do: [Environments | mise-en-place](https://mise.jdx.dev/environments/)

---

<div class="post-metadata">

### Author: ![nathan-sofia](https://community.tuist.dev/letter_avatar_proxy/v4/letter/n/e0b2c6/32.png) [@nathan-sofia](https://community.tuist.dev/u/nathan-sofia)
#### Post date: [December 18, 2024, 2:05pm UTC](https://community.tuist.dev/t/xcode-previews-do-not-work-anymore-after-porting-the-project-to-tuist/277/13 "2024-12-18T14:05:57Z")

</div>

If mise can specify the environment then it’s all good !
