• Stars
    star
    125
  • Rank 286,335 (Top 6 %)
  • Language
    Swift
  • Created over 4 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Workaround about SPM (Swift package manager) deal with Xcode 11.4 and Swift 5.2 with external static libraries. Adding an internal dynamic library to resolve static code duplication error

Swift Package Manager Static Dynamic Xcode Bug

Since Xcode 11.4 and Swift 5.2 you may experience some trouble regarding SPM and compilation errors due to

  • Library code duplication: Swift package product 'your library' is linked as a static library by 'your project' and 'your widget'. This will result in duplication of library code.
  • Unable to find a library within your Unit Tests target while using dynamic libraries
  • and so on related to SPM libraries

There is an open thread on Apple forum: https://forums.developer.apple.com/thread/128806 without concrete and definitive solution ๐Ÿ˜ž

And on Swift forum: https://forums.swift.org/t/migrating-to-spm-from-mix-of-embedded-frameworks-and-static-libraries/34253

Also another one on Swift forums: https://forums.swift.org/t/how-to-link-a-swift-package-as-dynamic/32062 which the solution proposed by https://github.com/piercifani was the base of this step by step tutorial.

In a nutshell: since Xcode 11.4, it seems that your project will only use .static libraries, and if your library is present twice or more in your project (2 different targets that use the same library, for example an iOS app target and its Today Widget). You can lead to a duplication of static library. I suspect it was the case before Xcode 11.4, but no complains whatsoever... Since I applied the trick in this tutorial, my app shrunk a little in size, maybe due to the fact that my App and its Widget use the exact same code and not a duplicated one.

An easy fix is to force the library to be .dynamic, but it requires either to ask the library maintainer to update his Package.swift definition, or fork the library yourself to do so. For me, it's not a solution ๐Ÿค”.

I tried this first as all my libraries I used in my project was mine. It worked ๐ŸŽ‰. But my Unit Tests refused to compile ๐Ÿคฌ. Because I used the same library for doing Snapshot Testing in both UI library and my main project...

IMHO it's an Xcode issue. Because in SPM documentation, it's mentioned that if you don't want to force either .dynamic or .static you can let blank and it will be automatically manager by the SPM consumer (a.k.a Xcode in our case). Xcode should be smart enough to detect that a SPM library is used twice or more and apply the .dynamic itself or something.

Create SPMLibraries is a possible workaround to continue using SPM with Xcode 11.4 and avoid moving all your external dependencies to .dynamic ones.

Step by Step

Step 1 to 3 is only to create a new project from scratch to reproduce the problem.

You can jump directly to step 4 to get the workaround immediately

Step 1: project without libraries

  • this commit contains placeholder for the main screen and the widget

Step 2: add just the first external library (SwiftClockUI) with SPM for the main project

  • I don't try to use the external library for the Widget yet Add SPM External Library
  • You can notice that we have already a dependencies for SnapshotTesting, keep that in mind for later.

Step 3: add the same external library for the Widget (โŒ won't compile)

  • Add the external library to the Widget Add SPM External Library to the Widget

  • Library duplication: Swift package product 'your library' is linked as a static library by 'your project' and 'your widget'. This will result in duplication of library code. ๐Ÿ˜ž Error static library code duplication

Step 4: create an additional internal Framework named SPMLibraries

  • Click on the + button to add a new Framework Add SPM static dynamic library step 1

  • Name it SPMLibraries or something like this (uncheck Include Unit Tests) Add SPM static dynamic library step 2

  • Add all the static dependencies from SPM you need here by clicking on the + button Add SPM static dynamic library step 3

  • โš ๏ธ Click on the "Allow app extension API only". It's important for Widget, instead it will be refused by the AppStore review

  • In your project targets (your project and your widget), remove references to your external library (SwiftClockUI) Add SPM static dynamic library step 4

  • Add SPMLibraries as a Framework

  • Your project now compiles ๐ŸŽ‰

Step 5: add common libraries into Unit Tests target

If you're using the same library as one of your dependency already use, you will have a library conflict.

  • My project use SnapshotTesting library from Point-Free
  • One of my library use it as well... so I've already this dependency in my project, indirectly though
  • My Unit Tests target is unable to access directly to SnapshotTesting ๐Ÿ˜ž with a "No such module 'SnapshotTesting'"
  • Tests won't compile and run...

Unit Tests: unable to find common external library

Here is the steps to follow to get the workaround

Step 1: Add your common dependency as a SPM package in your main project (even if it's indirectly already there)

Add Common external library with SPM into the main project

  • โ—๏ธ For library like this one, you shouldn't link it with your project, so uncheck this while SPM/Xcode ask you which target you want
  • โš ๏ธ don't forget to update to last package version!

Don't forget to update to last package version

Step 2: Link common libraries with your Unit Tests target manually

Link Unit Tests target with library manually and directly

  • You need to go to "Build Phases" and add libraries that Unit Tests will use manually

Add Library to Unit Tests manually example

  • Add SPMLibraries framework as well

Unit Tests target linked with libraries

  • And here we are ๐ŸŽ‰๐ŸŽ‰๐ŸŽ‰

Unit Tests results

More Repositories

1

SwiftClockUI

SwiftUI library to display a clock. You can move the arms to change the time, change the style of the clock and customise some configurations.
Swift
297
star
2

TellTime

iOS application to tell the time in the British way ๐Ÿ‡ฌ๐Ÿ‡งโฐ
Swift
64
star
3

SwiftUI-with-Size-Classes

Demonstrates how to deal with SwiftUI Size Class for iPhone, iPad Landscape and Portrait with SwiftUI
Swift
63
star
4

swift-tts

A straightforward package containing version for Swift modern concurrency, Point-Free Swift Dependency compatible with TCA and a Combine wrapper to provide Text to Speech (TTS) over AVFoundation/AVSpeechSynthesizer
Swift
37
star
5

swift-speech-recognizer

A straightforward Combine wrapper to provide Speech Recognition over SFSpeechRecognition
Swift
21
star
6

MixTeam

An old Swift project started in Swift 3 that I want to migrate to modern Swift, SwiftUI and at last publish it on the AppStore (which is done now :D).
Swift
11
star
7

MemoArt

A basic but smart SwiftUI pair-matching game. Continuously improving with some new art styles, new difficulty levels and some other user experience ideas.
Swift
8
star
8

steamScrum

Written in Swift for backend (Vapor) and using HTML+VanillaJS for frontend (With Milligram for styling purpose). Provide a simple interface to help team to do Poker Planning. Style WIP though.
Swift
6
star
9

SoliArt

An other Solitaire/Patience/Klondike game. This time in Swift with SwiftUI using TCA (The Composable Architecture). WIP
Swift
6
star
10

WeeklyRecipePlanning

Yet another recipe book app. But this one is made with SwiftUI, TCA (Composable Architecture) and CoreData
Swift
4
star
11

swift-ui-shape-maker

macOS application to draw your shape and directly convert it (in real time) to usable SwiftUI code that you can copy/paste to your codebase.
Swift
4
star
12

Pomme-s-Adventure

First tryout with SpriteKit
Swift
3
star
13

MarketingScreenshots

Automatically generate Screenshots for AppStore with XCUITests Test plans for multiple languages and everything is written in Swift
Swift
3
star
14

swift-past-ten

A Swift framework that telling the time passing a given time format (HH:mm) into "British"
Swift
2
star
15

HeuresCreuses

iOS, Apple Watch and macOS application that helps you find the best time to start your electric consuming devices like dishwasher or washing machine, it does the math for you to find the best delay for your programs.
Swift
2
star