From ec38da53ebacf4158e9bc92674c933133915e197 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 30 Sep 2026 18:10:49 +0200 Subject: [PATCH] Document SwiftPM's #include form and add CI coverage Package.swift declares the json target with path: "single_include/nlohmann", so SwiftPM consumers must write #include ; the form used throughout the rest of this documentation does not resolve. The SwiftPM section of package_managers.md only had the summary box and did not mention this, nor the #4650 linker problem: because the json target ships only headers, SwiftPM/Xcode look for a json.o that is never built, so a consumer needs at least one .cpp file of its own. Add a usage example (docs/mkdocs/docs/integration/swift/) that depends on the json product, includes , and works around the linker problem with its own example.cpp; verified it builds with `swift build` against a local checkout. Also raise the deployment target from the deprecated .watchOS(.v4) to .watchOS(.v9): Swift 6.4 warns "'v4' is deprecated: watchOS 9.0 is the oldest supported version" on every `swift package` invocation, and `swift package dump-package` is now clean. This is the one behavior change in this commit: it raises the minimum watchOS version the package declares. Add a macOS CI job that runs `swift package dump-package` (so a future deprecation warning fails CI) and builds the new documentation example against the checked-out repository with `swift build`, so a change to Package.swift or the example is caught before release. No workflow previously referenced Swift or Package.swift. Adding an in-repository placeholder .cpp to the library itself, so the issue does not occur for consumers at all, was proposed and declined in #4650; the documented workaround is a consumer-side .cpp file instead. #5716 item 3 Signed-off-by: Niels Lohmann --- .github/workflows/macos.yml | 35 +++++++++++++++++++ Package.swift | 2 +- .../docs/integration/package_managers.md | 24 +++++++++++++ .../docs/integration/swift/Package.swift | 20 +++++++++++ .../mkdocs/docs/integration/swift/example.cpp | 8 +++++ 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 docs/mkdocs/docs/integration/swift/Package.swift create mode 100644 docs/mkdocs/docs/integration/swift/example.cpp diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 0adaf26d5..e63a034c6 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -71,3 +71,38 @@ jobs: run: cmake --build build --parallel 10 - name: Test run: cd build ; ctest -j 10 --output-on-failure + + swiftpm: + runs-on: macos-15 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Check that Package.swift resolves without a deprecation warning + run: swift package dump-package + - name: Build the SwiftPM documentation example against this checkout + run: | + mkdir -p /tmp/json-swiftpm-consumer/Sources/MyLibrary + cp docs/mkdocs/docs/integration/swift/example.cpp /tmp/json-swiftpm-consumer/Sources/MyLibrary/example.cpp + cat > /tmp/json-swiftpm-consumer/Package.swift << EOF + // swift-tools-version: 5.9 + import PackageDescription + + let package = Package( + name: "MyPackage", + dependencies: [ + .package(path: "${{ github.workspace }}") + ], + targets: [ + .target( + name: "MyLibrary", + dependencies: [ + .product(name: "json", package: "json") + ], + publicHeadersPath: "." + ) + ] + ) + EOF + cd /tmp/json-swiftpm-consumer + swift build diff --git a/Package.swift b/Package.swift index 2f1e654a2..09b12dea3 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "nlohmann-json", platforms: [ - .iOS(.v12), .macOS(.v10_13), .tvOS(.v12), .watchOS(.v4), .visionOS(.v1) + .iOS(.v12), .macOS(.v10_13), .tvOS(.v12), .watchOS(.v9), .visionOS(.v1) ], products: [ .library(name: "json", targets: ["json"]) diff --git a/docs/mkdocs/docs/integration/package_managers.md b/docs/mkdocs/docs/integration/package_managers.md index 792a0fa5a..5f881d563 100644 --- a/docs/mkdocs/docs/integration/package_managers.md +++ b/docs/mkdocs/docs/integration/package_managers.md @@ -443,6 +443,30 @@ installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nl - :octicons-file-24: File issues at the [library issue tracker](https://github.com/nlohmann/json/issues) - :octicons-question-24: [Xcode documentation](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app) +The `json` target's public headers live at `single_include/nlohmann`, so a consumer must write `#include ` rather than the +`#include ` form used elsewhere in this documentation. The `json` target also ships only headers, and SwiftPM/Xcode +expect every library target to produce an object file to link against; without one, linking a consumer fails with a missing `json.o` +([#4650](https://github.com/nlohmann/json/issues/4650)). The workaround is to add at least one `.cpp` file of your own to the target +that depends on `json`. + +??? example + + 1. Create the following files: + + ```swift title="Package.swift" + --8<-- "integration/swift/Package.swift" + ``` + + ```cpp title="Sources/MyLibrary/example.cpp" + --8<-- "integration/swift/example.cpp" + ``` + + 2. Build + + ```shell + swift build + ``` + ## NuGet !!! abstract "Summary" diff --git a/docs/mkdocs/docs/integration/swift/Package.swift b/docs/mkdocs/docs/integration/swift/Package.swift new file mode 100644 index 000000000..b0bf7e681 --- /dev/null +++ b/docs/mkdocs/docs/integration/swift/Package.swift @@ -0,0 +1,20 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "MyPackage", + dependencies: [ + .package(url: "https://github.com/nlohmann/json.git", from: "3.12.0") + ], + targets: [ + // the C++ target that uses nlohmann/json + .target( + name: "MyLibrary", + dependencies: [ + .product(name: "json", package: "json") + ], + // works around missing public headers in MyLibrary; not related to nlohmann/json + publicHeadersPath: "." + ) + ] +) diff --git a/docs/mkdocs/docs/integration/swift/example.cpp b/docs/mkdocs/docs/integration/swift/example.cpp new file mode 100644 index 000000000..becdd62b3 --- /dev/null +++ b/docs/mkdocs/docs/integration/swift/example.cpp @@ -0,0 +1,8 @@ +// MyLibrary must contain at least one .cpp file, or SwiftPM/Xcode will +// not build a usable "json" library to link against (see nlohmann/json#4650) +#include + +nlohmann::json example() +{ + return nlohmann::json::meta(); +}