google / google/promises

Xcode 27 unbrella for module FBLPromises already covers this directory

Open Beginner friendly
#246 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Objective-C
Stars
3.8k
Forks
316
PR merge metrics
No merged PRs in 30d

Description

### Description

`FBLPromises`' module map fails to build under Xcode's newer Clang toolchain (Xcode 26/27 beta, iOS 27 SDK) when **Explicitly Built Modules** are enabled. The module map declares an `umbrella header` *and* an explicit list of the sibling headers in the same directory, which the newer Clang rejects.

### Error

```
.../checkouts/promises/Sources/FBLPromises/include/module.modulemap:2:21:
error: umbrella for module 'FBLPromises' already covers this directory
```

The error is fatal to Clang dependency scanning, so every module that transitively imports `FBLPromises` (e.g. via Firebase) then fails with `could not build module 'FBLPromises'` and a cascade of `Compilation search paths unable to resolve module dependency` errors.

### Environment

- Xcode: 26/27 beta (iPhoneSimulator 27.0 SDK)
- Integration: Swift Package Manager
- Build mode: Explicitly Built Modules enabled (`-explicit-module-build`)
- Promises version:

### Root cause

`Sources/FBLPromises/include/module.modulemap` declares an umbrella header together with an explicit list of `header` entries for files that live in the same directory the umbrella already covers:

```
module FBLPromises {
umbrella header "FBLPromises.h"

header "FBLPromise.h"
header "FBLPromise+All.h"
// ... all the other FBLPromise+*.h headers ...

exclude header "FBLPromisePrivate.h"

export *
}
```

An `umbrella header` already covers the whole directory. Re-declaring the sibling headers explicitly makes Clang see the directory as covered twice. Older Clang tolerated this; the newer toolchain treats it as an error.

### Suggested fix

Drop the redundant explicit `header` entries and keep the umbrella plus the `exclude` for the private header:

```
module FBLPromises {
umbrella header "FBLPromises.h"

exclude header "FBLPromisePrivate.h"

export *
}
```

The umbrella header already imports every public `FBLPromise+*.h`, so the explicit list only duplicated coverage. The `exclude` is still required so `FBLPromisePrivate.h` (which sits in the covered directory) isn't pulled into the module.

### Steps to reproduce

1. Integrate Firebase (or Promises directly) via SPM.
2. Build with Xcode 26/27 beta with Explicitly Built Modules enabled.
3. Observe the `umbrella ... already covers this directory` error and the downstream `could not build module` cascade.

### Workarounds

- Patch the module map as above (not durable — the SPM checkout is regenerated on re-resolution).
- Disable Explicitly Built Modules (`SWIFT_ENABLE_EXPLICIT_MODULES = NO`).

Contributor guide

Open the contributing guide

Research direction

Start with Sources/FBLPromises/include/module.modulemap and compare its umbrella, header, and exclude declarations with the reported Clang error. Reproduce the failure using Swift Package Manager and Explicitly Built Modules under the affected Xcode toolchain, then verify that FBLPromises and a dependent module build without the duplicate-coverage error while the private header remains excluded.

Written by the indexing model from the issue text.

Assessment

Tech stack
objective-c, swift
Domain
build-system, mobile
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.