Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,119 @@ Read [instructions for Windows](https://github.com/MailCore/mailcore2/blob/maste

Read [instructions for Linux](https://github.com/MailCore/mailcore2/blob/master/build-linux/README.md).

## Updating mailcore2 on Windows (Spark prebuilt flow) ##

Windows builds of spark-core do **not** compile mailcore2 C++ from source.
`Build-SparkCore.ps1` clones this repo at a pinned tag and runs
`build-windows-5.10\Build-SwiftMailcore.ps1`, which compiles only the Swift
bindings (`src/swift`) and downloads the prebuilt C++ libraries from S3
(`Get-Mailcore2.ps1`, `mailcore2-all-<N>.zip`). **Any C++ change reaches
Windows only through a new prebuilt archive** — merging a PR or moving a tag
is not enough.

### Prerequisites ###

Everything below is preinstalled in the CI image
`ghcr.io/readdle/spark-js-addon-windows-builder` — building inside it is the
easiest path. On a bare machine you need:

- VS2022 Build Tools with an MSVC toolset whose STL accepts the Swift
toolchain's clang. Swift 5.10.1 ships clang 16, so the toolset must be
**14.39 (17.9) or older** — the 14.40+ STL requires clang 17 and fails with
`STL1000`. Install the side-by-side component
`Microsoft.VisualStudio.Component.VC.14.39.17.9.x86.x64` and make it the
default via `VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt` if a
newer toolset is also installed.
- Windows SDK **10.0.18362** (version 1903, from the Windows SDK archive) —
the RD build modules pin it when configuring the VS environment.
- RD PowerShell modules (`RDBuildCMake`, `RDBuildMSVC`, `RDDependency`) in
`PSModulePath`.
- Swift **5.10.1** toolchain (provides `clang-cl` and the Windows SDK with
dispatch/BlocksRuntime).
- ICU 69.1 at `C:\Library\icu-69.1\usr`, libxml2 2.11.5 at
`C:\Library\libxml2-2.11.5\usr` (paths are hardcoded in the script).
- `SPARK_PREBUILT_KEY` env var — download token for
`spark-prebuilt-binaries.s3.amazonaws.com` (zlib/sasl/openssl prebuilts).
- ssh access to `git@github.com:readdle/{ctemplate,libetpan,tidy-html5}`.

### Build ###

```powershell
$env:SPARK_PREBUILT_KEY = "<key>"
powershell -ExecutionPolicy Bypass -File .\build-windows-5.10\Build-Mailcore2.ps1 -Install
```

The script clones and builds ctemplate/libetpan/tidy, downloads the binary
deps, then builds mailcore2/CMailCore with CMake + Ninja using `clang-cl`
from the Swift toolchain. `-Install` lays the result out in `.build\install`
(`bin`, `include`, `lib`, `etc`).

- After a **failed** run, delete `.build` before retrying — stale CMake
caches keep the old configuration (wrong install prefix, wrong build type)
and produce confusing errors.
- Verify what was built: `type .build\install\etc\mailcore2-git-rev` must be
the commit you intend to ship.

### Package ###

The zip must contain a single top-level folder named exactly `mailcore2-all`
(that is the path `Get-Mailcore2.ps1` extracts):

```powershell
cd .\.build
Copy-Item -Recurse install mailcore2-all
tar -a -cf mailcore2-all-<N+1>.zip mailcore2-all
```

Sanity check against the current archive: `tar -tf` both files and compare
the top-level layout.

### Upload ###

The bucket is `spark-prebuilt-binaries` in **eu-central-1**.
`SPARK_PREBUILT_KEY` is a download-only token — uploads need real AWS
credentials:

```bash
aws s3 cp mailcore2-all-<N+1>.zip s3://spark-prebuilt-binaries/mailcore2-all-<N+1>.zip --region eu-central-1
```

Verify the build can fetch it the same way the script does:

```powershell
Invoke-RestMethod -Method Head -Uri "https://spark-prebuilt-binaries.s3.amazonaws.com/mailcore2-all-<N+1>.zip" -UserAgent $env:SPARK_PREBUILT_KEY
```

Never overwrite an existing `mailcore2-all-<N>.zip` — older tags keep
downloading it by name.

### Switch builds to the new prebuilt ###

1. In this repo: bump `$PrebuiltMailcoreVersion` in
`build-windows-5.10/Get-Mailcore2.ps1`, PR into `spark2`.
2. Tag the merge with the next `2.1.x` tag. The bump **must be inside the
tag** — spark-core runs `Get-Mailcore2.ps1` from its mailcore checkout at
that tag, so a tag without the bump silently downloads the previous
archive.
3. In `spark-core-mono`, update every mailcore pin to the new tag — the
versions must match across platforms:
- `spark-core/build-scripts/Windows-5.10/Build-SparkCore.ps1`
(`GitBranch` of the MailCore dependency) — Windows;
- `spark-core/Package.swift` and `spark-core/SparkCoreNano/Package.swift`
(`.package(... branch:)`) — Mac/Android SPM;
- `spark-js-addon/scripts/mac/configure.rb` (`RemoteSwiftPackage`) — the
source the addon workspace is generated from;
- `spark-js-addon/SparkCoreAddon.xcworkspace/xcshareddata/swiftpm/Package.resolved`
— autogenerated from `configure.rb` but tracked in git; update the
`branch`/`revision` pair so CI resolves without a regeneration step.

### Local testing without a prebuilt ###

To test unreleased C++ changes, add `-BuildMailcore2` to the
`Build-SwiftMailcore.ps1` invocation in `Build-SparkCore.ps1` — mailcore2 is
then compiled from the pinned checkout instead of downloading the archive.
Slower (~10–15 min extra), for test builds only; remove it before release.

## Basic IMAP Usage ##

Using MailCore 2 is just a little more complex conceptually than the original MailCore. All fetch requests in MailCore 2 are made asynchronously through a queue. What does this mean? Well, let's take a look at a simple example:
Expand Down
Loading