Skip to content

Commit 5e01fda

Browse files
authored
Header/Import Guidelines (#5765)
1 parent 93eb6d8 commit 5e01fda

File tree

4 files changed

+103
-3
lines changed

4 files changed

+103
-3
lines changed

AddNewPod.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ explicit import by other Firebase pods)
4646
* `FirebaseFoo/Tests/Sample` - Optional
4747
* `FirebaseFoo/Tests/{Other}` - Optional
4848

49+
## Headers and Imports
50+
51+
See [Headers and Imports](HeadersImports.md) for details on managing headers and imports.
52+
4953
## Continous Integration
5054

5155
Set up a GitHub Action workflow for the pod. A good example template is
@@ -61,7 +65,10 @@ For GitHub tag management and public header change detection, add a GitHub api t
6165

6266
## Firebase Integration
6367

64-
* Make sure the public headers are imported via [Firebase.h](CoreOnly/Sources/Firebase.h).
68+
For top-level Firebase pods that map to documented products:
69+
70+
* Make sure the public umbrella header is imported via [Firebase.h](CoreOnly/Sources/Firebase.h)
71+
wrapped in `__has_include`. Follow the existing examples for details.
6572
* Update [Firebase.podspec](Firebase.podspec).
6673
* Register library via registerInternalLibrary API like this
6774
[Storage example](FirebaseStorage/Sources/FIRStorageComponent.m).

HeadersImports.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Headers and Imports
2+
3+
## Introduction
4+
5+
Follow this set of guidelines when creating header files and importing them. The
6+
guidelines are designed to support a wide range of build systems and usage scenarios.
7+
8+
In this document, the term `library` refers to a buildable package. In CocoaPods, it's a CocoaPod.
9+
In Swift Package Manager, it's a library target.
10+
11+
## Header File Types and Locations - For Header File Creators
12+
13+
* *Public Headers* - Headers that define the library's API. They should be located in
14+
`FirebaseFoo/Sources/Public`. Any additions require a minor version update. Any changes or
15+
deletions require a major version update.
16+
17+
* *Public Umbrella Header* - A single header that includes the full library's public API located at
18+
`FirebaseFoo/Sources/Public/FirebaseFoo.h`.
19+
20+
* *Private Headers* - Headers that are available to other libraries in the repo, but are not part
21+
of the public API. These should be located in `FirebaseFoo/Sources/Private`.
22+
[Xcode](https://stackoverflow.com/a/8016333) and CocoaPods refer to these as "Private Headers".
23+
Note that the usage CocoaPods `private_headers` is deprecated and should instead
24+
the `source_files` attribute should be used for access them with a repo-relative import.
25+
26+
* *Interop Headers* - A special kind of private header that defines an interface to another library.
27+
Details in [Firebase Component System docs](Interop/FirebaseComponentSystem.md).
28+
29+
* *Private Umbrella Header* - A single header that includes the library's public API plus any APIs
30+
provided for other libraries in the repo. Any package manager complexity should be localized to
31+
this umbrella header.
32+
33+
* *Library Internal Headers* - Headers that are only used by the enclosing library. These headers
34+
should be located among the source files. [Xcode](https://stackoverflow.com/a/8016333) refers to
35+
these as "Project Headers".
36+
37+
## Imports - For Header File Consumers
38+
39+
* *Headers within the Library* - Use a repo-relative path for all of the header types above.
40+
* *Exception* - Public header imports from other public headers should do an unqualified
41+
import like `#import "publicHeader.h"` to avoid public module collisions.
42+
43+
* *Private Headers from other Libraries* - Import a private umbrella header like
44+
`FirebaseCore/Sources/Private/FirebaseCoreInternal.h`. For CocoaPods, these files should be
45+
added to the podspec in the `preserved_path` attribute like:
46+
```
47+
s.preserve_paths = 'Interop/Auth/Public/*.h', 'FirebaseCore/Sources/Private/*.h'
48+
```
49+
50+
* *Headers from an external dependency* - Do a module import for Swift Package Manager and an
51+
umbrella header import otherwise, like:
52+
```
53+
#if SWIFT_PACKAGE
54+
@import GTMSessionFetcherCore;
55+
#else
56+
#import <GTMSessionFetcher/GTMSessionFetcher.h>
57+
#endif
58+
```
59+
60+
## Additional Background
61+
62+
Here is some additional detail that should give deeper insight onto the above guidelines.
63+
64+
### Build Systems
65+
66+
We support building with CocoaPods, cmake, internal Google build system, and Swift Package
67+
Manager (in development). Using repo-relative headers is a key enabler since it allows all headers
68+
to be found with a single path specifier no matter what the build system.
69+
70+
#### CocoaPods Build Systems
71+
CocoaPods itself has a range of options that impact the functionality of header imports.
72+
73+
The `use_frameworks!` option enables `@import {module-name}`. CocoaPods creates a directory structure
74+
such that `#import <pod-name/header>` works whether or not frameworks are built.
75+
76+
CocoaPods builds a different directory structure for a `Development Pods` install versus an install
77+
from a published podspec. This can hide errors resulting from header search path pointing outside
78+
of a particular pod's sources.
79+
80+
81+
### "Internal" versus "Private"
82+
83+
"Internal" and "Private" are often used interchangeably since
84+
[Xcode](https://stackoverflow.com/a/8016333) and CocoaPods usage is
85+
inconsistent with expectations of C++ developers. "Private" headers are available to clients
86+
via an explicit import. "Internal" or "Project" headers are only available to their enclosing
87+
library. Many file names in this repo include "Private" or "Internal" do not comply. Always
88+
check the build definition to see how the file is used.

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Instructions for installing binary frameworks via
9898
To develop Firebase software in this repository, ensure that you have at least
9999
the following software:
100100

101-
* Xcode 10.1 (or later)
101+
* Xcode 10.3 (or later)
102102
* CocoaPods 1.7.2 (or later)
103103
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
104104

@@ -129,6 +129,10 @@ Firestore has a self contained Xcode project. See
129129

130130
See [AddNewPod.md](AddNewPod.md).
131131

132+
### Managing Headers and Imports
133+
134+
See [HeadersImports.md](HeadersImports.md).
135+
132136
### Code Formatting
133137

134138
To ensure that the code is formatted consistently, run the script

scripts/check_no_module_imports.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ function exit_with_error {
2929

3030
git grep "${options[@]}" \
3131
-- ':(exclude,glob)**/Example/**' ':(exclude,glob)**/Sample/**' \
32-
':(exclude)FirebaseCore/Sources/Private/FirebaseCoreInternal.h' && exit_with_error
32+
':(exclude)FirebaseCore/Sources/Private/FirebaseCoreInternal.h' \
33+
':(exclude)HeadersImports.md' && exit_with_error
3334

3435
# Tests are under the Example directory, so we have to separately grep them for
3536
# @import statements (otherwise they'd be excluded).

0 commit comments

Comments
 (0)