Swift Package Manager in Xcode is the newest way of managing third party dependencies of Swift projects. It is very neatly integrated and allows for clean and easy dependency management. At least sometimes. Show TL;DRIn this article I am going through struggle of adding SPM to legacy project containing frameworks not compatible with Apple Silicon iOS simulators (arm64). If you are in rush for a solution head straight to SPM build configurations paragraph. When working on greenfield projects SPM in most cases is really a breeze to use. In reality however quite frequently we find ourselves working on some kind of legacy projects with all of their quirks. [Disclaimer]: Described problems and their solutions were tested on Xcode 13.2.1 and 13.4.1. Behavior may change in future Xcode releases. Here you can find a repository with an example project. We are looking for iOS DevelopersBuild with us the iOS application that will impact how Just Eat shapes the retail world. Or work for our other clients representing industries such as FinTech, Blockchain, HealthTech, and Logistics. The problemThe other day I was trying to add Swift Package Manager to one of the projects I work on as my Team tends to move to SPM from other dependency managers. Surprisingly I was greeted with a big fat red error preventing the project from compiling:
Whatever library I wanted to add to the project it always ended in the same way: error telling you that module for current architecture is lacking. At that point I left behind the idea of slow migration to SPM. When I stumbled on this issue once again I finally thought that something needs to be done about that. Root of all evilAfter lots of trials and errors I finally arrived at a solution. But before opening a bottle of champaign let's try to think why that was even happening. Issue itself originates not from other dependency managers, but rather build settings of the project. You may be familiar with workaround for running projects with legacy frameworks (e.g. “Fat” .framework not built for arm64 iOS simulator) on Apple silicon machines. There are two main options to deal with that:
Even though we are explicitly excluding arm64 architecture for iOS simulator we are getting error shown above. What is more it explicitly says that SPM built our dependency just for arm64 architecture. We can conclude that SPM is ignoring our project build settings. Unfortunately there is no (at least straightforward) way to configure the build configuration of SPM dependencies. But it works in other project with exactly the same limitations. So in my case it seemed obvious that there must be a way of affecting build configuration of SPM dependencies. SPM build configurationsIf we
inspect the documentation we can see that there is I believe I have quite valuable and maybe even shocking observations: Debug build configuration is being applied to Swift Package Manager dependencies if our current build configuration contains “debug” or “development” in its name (case-insensitive). So if you try to build an app in default Release configuration, rename Debug to something else or create a new configuration (eg. Stage) and it will just work™. This means there is some kind of parsing logic for project build configuration name that then translates to different build configurations of SPM dependencies. I want to highlight that once more: as silly as it sounds renaming your project build configuration is the key to success. It cannot contain Reverse problemWe just arrived at the conclusion that we need release configuration of SPM dependencies for our project in the scenario described above. But in the past I have stumbled on a similar issue, however from the other side. Since we are writing Unit Tests we also wrote such for internal packages that we used for code separation. It turned out that we faced issues while trying to run our unit tests together with other test targets in the main project scheme:
As you may already suspect the solution here is totally opposite to what we just did before. In order to make such error go away we must compile our Swift Package with debug configuration and that means we need to add “debug” to our development configuration name. If at the same time you are dealing with a previous issue then this is not possible. We solved it by creating a separate scheme just for running unit tests of local packages. ConclusionsSwift Package Manager is a great way of managing third party dependencies in iOS projects. With new releases of Xcode it is getting more useful and powerful. Unfortunately SPM is still a young addition to Xcode and lacks some functionalities. Also its ephemeral way of implementation brings issues like those I have faced. In this particular case we could benefit from explicit documentation telling about build configuration name parsing logic applied to our Swift Packages. If you ever find yourself in a similar situation I hope this article will help you in sorting it out :) We are looking for iOS DevelopersBuild with us the iOS application that will impact how Just Eat shapes the retail world. Or work for our other clients representing industries such as FinTech, Blockchain, HealthTech, and Logistics. |