-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Write a blog post about the -ObjC flag
- Loading branch information
Showing
1 changed file
with
30 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
--- | ||
title: "Why you need the -ObjC flag" | ||
description: "In this blog post, I explain why you might need to set the -ObjC flag in the OTHER_LDFLAGS build setting of your Xcode project." | ||
tags: ["Swift", "Xcode"] | ||
--- | ||
|
||
Tuist provides a [method](https://docs.tuist.io/guide/project/dependencies.html#tuist-s-xcodeproj-based-integration) for integrating Swift Packages, previously resolved by SPM, into Xcode projects using XcodeProj primitives such as targets, build settings and phases. | ||
This feature uncovered a need that some packages in the ecosystem have, | ||
and that's the need for upstream targets to pass `-force_load` or `-ObjC` through the build setting `OTHER_LDFLAGS`. | ||
Why is that needed? | ||
Thanks to [David](https://github.com/thedavidharris), who put together some [troubleshooting](https://docs.tuist.io/guide/project/dependencies.html#troubleshooting) guidance and provided [some references](https://github.com/tuist/tuist/issues/6320#issuecomment-2146534862) to discussions, I could better understand what the problem was. | ||
This post is my attempt to write down my understanding of the problem, to help other developers in the future come across the same issue. | ||
|
||
|
||
In simple words, | ||
the problem is that the linker **overoptimizes the binary removing symbols that are needed at runtime.** | ||
The linker's dead-stripping logic can't delete dynamically referenced symbols. | ||
And this is something that happens not only when referencing Objective-C symbols, but [Swift too](https://forums.swift.org/t/linker-flag-objc-force-loads-swift-libraries/47466/3). | ||
For example, when integrating Composable Architecture, | ||
which [uses](https://github.com/pointfreeco/swift-composable-architecture/blob/7cbde3b07f193f732e256429e1351ff53cd31641/Sources/ComposableArchitecture/UIKit/NSObject%2BObservation.swift#L172) Objective-C runtime capabilities, | ||
developers might need to add explicit references to those symbols or add the aforementioned flags to the build settings. | ||
|
||
What's the solution? There are a few options: | ||
|
||
- The package maintainer can add static references to those symbols to prevent the dead-stripping logic from removing them (e.g., [Promises](https://github.com/google/promises/pull/221), [IGListKit](https://github.com/Instagram/IGListKit/pull/957)) | ||
- You set the `-force_load` or `-ObjC` flag in the `OTHER_LDFLAGS` build setting of the target that links those packages statically. Note that this has some effects, like potentially increasing the binary size. | ||
- You turn those dependencies into dynamic targets, which as a caveat might end up increasing the launch time of your app. | ||
|
||
This is a bit unfortunate because it requires developers to go a bit deeper in understanding their dependencies | ||
, but hopefully this write-up helps you understand the problem and the potential solutions. |