I have a framework target which contains a mixture of Objective-C and Swift source files.
I just upgraded my project’s build settings to the settings recommended by Xcode 14.3.1.
One of the changes made by Xcode was to turn on the ENABLE_MODULE_VERIFIER
build setting for my framework target.
Following this upgrade, I get the following build error in all of the public header files of my framework which contain a semantic import (i.e. an import of the form @import MODULE_NAME;
):
use of ‘@import’ in framework header is discouraged, including this header requires -fmodules
I see this advice communicated in the Xcode > Build system > Identifying and addressing framework module issues article also:
Avoid the use of semantic import syntax in your public and private headers.
Neither the Xcode build error nor the article explain why we should avoid semantic imports in our frameworks’ public and private header files.
Why should we avoid semantic imports in our frameworks’ public and private header files?
2
Answers
The stated reason from Apple in the release notes for Xcode 11.4 (the release that made it a default warning) is "using @import in framework headers is discouraged, because doing so requires all importers to use modules."
In other words, using it forces a dependency relationship as opposed to a normal
import
statement where the preprocessor simply includes the necessary aspects of another file.Here are a few reasons why Apple discourages its use:
Slower Compilation Times: When you use @import in framework headers, it can result in slower compilation times, especially in large codebases. The module interfaces generated by @import include a lot of unnecessary information, and the compiler has to process all of it. This can slow down the build process.
Increased Coupling: Using @import can create tight coupling between modules. When you import a framework using @import in a header file, you expose all of the framework’s implementation details to the client code. This can lead to unintended dependencies and make it harder to maintain and evolve your codebase.
Difficulty in Code Isolation: Frameworks are supposed to provide a clear, isolated API to their clients. Using @import can leak implementation details and expose symbols that should remain private. This can lead to issues when you want to make changes to the framework’s internals without breaking client code.