From b9b0d7f447c2b6e8d7cfa12629428005153a1467 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 17:25:18 -0400 Subject: [PATCH 01/39] Build examples in CI --- .github/workflows/ci.yml | 181 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0344ad8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,181 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + build: + name: Build (swift:${{ matrix.swift_version }}) + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + swift_version: ['nightly-main', 'nightly-6.3', '6.3'] + sdk_triple: ['aarch64-unknown-linux-android28'] + ndk_version: ['r27d'] + env: + SDK_TRIPLE: ${{ matrix.sdk_triple }} + NDK_VERSION: ${{ matrix.ndk_version }} + SWIFT_VERSION: ${{ matrix.swift_version }} + steps: + - uses: actions/checkout@v6 + + - name: Set up JDK 25 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '25' + + - name: Install Swift toolchain and Android Swift SDK + # Mirrors the build-swift-android job from + # https://github.com/swiftlang/swift-java/blob/main/.github/workflows/pull_request.yml + # but uses ":" as a no-op build command because we want only the + # toolchain + Android Swift SDK installed, not a Swift package built. + run: | + set -euxo pipefail + sudo apt-get -q update + sudo apt-get -yq install curl jq gpg unzip + curl -L -O --retry 3 https://raw.githubusercontent.com/swiftlang/github-workflows/refs/heads/main/.github/workflows/scripts/install-and-build-with-sdk.sh + perl -pi -e "s#(download_and_extract_toolchain \".ANDROID_SDK_TAG\"\))#\1\n PATH=\\\$(dirname \\\$SWIFT_EXECUTABLE_FOR_ANDROID_SDK):\\\$PATH\n echo \"path is now \\\$PATH\"#" install-and-build-with-sdk.sh + chmod 500 install-and-build-with-sdk.sh + ./install-and-build-with-sdk.sh \ + --android \ + --build-command=":" \ + --android-sdk-triple="${SDK_TRIPLE}" \ + --android-ndk-version="${NDK_VERSION}" \ + "${SWIFT_VERSION}" + + - name: Locate installed Swift toolchain + run: | + set -euo pipefail + SWIFT_BIN=$(find "$HOME/.swift-toolchains" -type f -name swift -path '*/usr/bin/swift' | head -n1) + if [ -z "$SWIFT_BIN" ]; then + echo "Error: could not find swift binary under $HOME/.swift-toolchains" >&2 + exit 1 + fi + echo "Found Swift binary: $SWIFT_BIN" + "$SWIFT_BIN" --version + echo "SWIFT_BIN=$SWIFT_BIN" >> "$GITHUB_ENV" + dirname "$SWIFT_BIN" >> "$GITHUB_PATH" + + - name: Create swiftly shim + # The example projects' Gradle scripts invoke Swift via swiftly + # (e.g. `swiftly run +6.3 swift build ...`). Install a tiny shim that + # strips the swiftly-specific arguments and forwards to the swift + # binary that the install script downloaded. + run: | + set -euo pipefail + mkdir -p "$HOME/.swiftly/bin" + cat > "$HOME/.swiftly/bin/swiftly" <<'SHIM' + #!/usr/bin/env bash + set -e + if [ -z "${SWIFT_BIN:-}" ]; then + echo "swiftly shim: SWIFT_BIN is not set" >&2 + exit 1 + fi + # Drop a leading "run" subcommand + if [ "${1:-}" = "run" ]; then shift; fi + # Drop any "+" tokens + new_args=() + for arg in "$@"; do + case "$arg" in + +*) ;; + *) new_args+=("$arg") ;; + esac + done + # Drop a leading "swift" since we're calling the swift binary directly + if [ "${#new_args[@]}" -gt 0 ] && [ "${new_args[0]}" = "swift" ]; then + new_args=("${new_args[@]:1}") + fi + exec "$SWIFT_BIN" "${new_args[@]}" + SHIM + chmod +x "$HOME/.swiftly/bin/swiftly" + echo "SWIFTLY_PATH=$HOME/.swiftly/bin/swiftly" >> "$GITHUB_ENV" + + - name: Locate Swift Android SDK + # The per-library build.gradle scripts (hashing-lib, weather-lib, + # hello-cpp-swift/swift-lib) and swift-android.gradle.kts hardcode the + # artifactbundle directory name to "swift-6.3-RELEASE_android.artifactbundle". + # When we install a different snapshot, expose the actual bundle under + # that name via a symlink so the Gradle scripts can locate the runtime libs. + run: | + set -euo pipefail + SDK_BUNDLE="" + for d in "$HOME/.swiftpm/swift-sdks" "$HOME/.config/swiftpm/swift-sdks" "$HOME/Library/org.swift.swiftpm/swift-sdks"; do + if [ -d "$d" ]; then + found=$(find "$d" -maxdepth 1 -type d -name '*_android*.artifactbundle' | head -n1) + if [ -n "$found" ]; then + SDK_BUNDLE="$found" + break + fi + fi + done + if [ -z "$SDK_BUNDLE" ]; then + echo "Error: Android Swift SDK artifactbundle was not found" >&2 + find "$HOME/.swiftpm" "$HOME/.config/swiftpm" 2>/dev/null || true + exit 1 + fi + echo "Found Android SDK bundle: $SDK_BUNDLE" + SDK_DIR=$(dirname "$SDK_BUNDLE") + EXPECTED="$SDK_DIR/swift-6.3-RELEASE_android.artifactbundle" + if [ ! -e "$EXPECTED" ]; then + ln -s "$SDK_BUNDLE" "$EXPECTED" + echo "Symlinked $EXPECTED -> $SDK_BUNDLE" + fi + echo "SWIFT_SDK_PATH=$SDK_DIR" >> "$GITHUB_ENV" + + - name: Publish swift-java packages to local Maven + # The hashing-lib, weather-lib, and hello-cpp-swift/swift-lib modules + # depend on org.swift.swiftkit:swiftkit-core:1.0-SNAPSHOT, which is not + # published to a public Maven repo. The hashing-lib README documents + # publishing it to mavenLocal from the swift-java checkout that + # SwiftPM resolves into .build/checkouts/swift-java. + working-directory: hello-swift-java/hashing-lib + run: | + set -euxo pipefail + "$SWIFT_BIN" package resolve + ./.build/checkouts/swift-java/gradlew \ + --project-dir .build/checkouts/swift-java \ + :SwiftKitCore:publishToMavenLocal + continue-on-error: true + + - name: Build hello-swift-raw-jni APK + run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace + continue-on-error: true + + - name: Build hello-swift-raw-jni-callback APK + run: ./gradlew :hello-swift-raw-jni-callback:assembleDebug --stacktrace + continue-on-error: true + + - name: Build hello-swift-raw-jni-library + run: ./gradlew :hello-swift-raw-jni-library:assembleDebug --stacktrace + continue-on-error: true + + - name: Build native-activity APK + run: ./gradlew :native-activity:assembleDebug --stacktrace + continue-on-error: true + + - name: Build hello-swift-java APK + run: ./gradlew :hello-swift-java-hashing-app:assembleDebug --stacktrace + continue-on-error: true + + - name: Build swift-java-weather-app APK + run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace + continue-on-error: true + + - name: Build hello-cpp-swift APK + run: ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace + continue-on-error: true + + - name: Upload APK artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: apks-${{ matrix.swift_version }} + path: '**/build/outputs/apk/**/*.apk' + if-no-files-found: warn From 41f902a64294463143de2423b8c130569a25a007 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 17:29:51 -0400 Subject: [PATCH 02/39] Update swift_version in matrix --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0344ad8..bc056bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['nightly-main', 'nightly-6.3', '6.3'] + swift_version: ['nightly-main', 'nightly-6.3', '6.3.0'] sdk_triple: ['aarch64-unknown-linux-android28'] ndk_version: ['r27d'] env: From 040c718a04c598224e5e9c17f57568d0921747df Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 17:39:29 -0400 Subject: [PATCH 03/39] Install swiftly --- .github/workflows/ci.yml | 108 +++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc056bc..716100b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['nightly-main', 'nightly-6.3', '6.3.0'] + swift_version: ['nightly-main', 'nightly-6.3', '6.3'] sdk_triple: ['aarch64-unknown-linux-android28'] ndk_version: ['r27d'] env: @@ -31,15 +31,62 @@ jobs: distribution: temurin java-version: '25' - - name: Install Swift toolchain and Android Swift SDK - # Mirrors the build-swift-android job from - # https://github.com/swiftlang/swift-java/blob/main/.github/workflows/pull_request.yml - # but uses ":" as a no-op build command because we want only the - # toolchain + Android Swift SDK installed, not a Swift package built. + - name: Install swiftly run: | set -euxo pipefail sudo apt-get -q update sudo apt-get -yq install curl jq gpg unzip + ARCH="$(uname -m)" + curl -L -O --retry 3 "https://download.swift.org/swiftly/linux/swiftly-${ARCH}.tar.gz" + tar -xzf "swiftly-${ARCH}.tar.gz" + ./swiftly init \ + --assume-yes \ + --skip-install \ + --no-modify-profile \ + --quiet-shell-followup + rm -f "swiftly-${ARCH}.tar.gz" swiftly + # The example projects' Gradle scripts look for swiftly under + # $HOME/.local/share/swiftly/bin, which is also where the official + # installer puts it. Add it to PATH for subsequent steps. + echo "$HOME/.local/share/swiftly/bin" >> "$GITHUB_PATH" + "$HOME/.local/share/swiftly/bin/swiftly" --version + + - name: Install Swift via swiftly + run: | + set -euxo pipefail + # Translate the matrix's swift_version into the form swiftly expects: + # nightly-main -> main-snapshot + # nightly-6.3 -> 6.3-snapshot + # 6.3 / 6.3.0 -> passed through as-is + case "$SWIFT_VERSION" in + nightly-main) SWIFTLY_VER="main-snapshot" ;; + nightly-*) SWIFTLY_VER="${SWIFT_VERSION#nightly-}-snapshot" ;; + *) SWIFTLY_VER="$SWIFT_VERSION" ;; + esac + POST_INSTALL_FILE="$(mktemp)" + swiftly install "$SWIFTLY_VER" \ + --use \ + --assume-yes \ + --post-install-file="$POST_INSTALL_FILE" + # Some toolchains print follow-up commands (e.g. apt-get install + # of missing system libs) to the post-install file. Run them if + # any were emitted. + if [ -s "$POST_INSTALL_FILE" ]; then + sudo bash "$POST_INSTALL_FILE" + fi + rm -f "$POST_INSTALL_FILE" + swift --version + + - name: Install Android Swift SDK and NDK + # Uses the build-swift-android mechanism from + # https://github.com/swiftlang/swift-java/blob/main/.github/workflows/pull_request.yml + # to install the Android Swift SDK and NDK and link them via the + # bundle's setup-android-sdk.sh script. The Swift toolchain itself + # was already installed in the previous step via swiftly. ":" is + # passed as a no-op build command because we don't want this script + # to also try to `swift build` anything. + run: | + set -euxo pipefail curl -L -O --retry 3 https://raw.githubusercontent.com/swiftlang/github-workflows/refs/heads/main/.github/workflows/scripts/install-and-build-with-sdk.sh perl -pi -e "s#(download_and_extract_toolchain \".ANDROID_SDK_TAG\"\))#\1\n PATH=\\\$(dirname \\\$SWIFT_EXECUTABLE_FOR_ANDROID_SDK):\\\$PATH\n echo \"path is now \\\$PATH\"#" install-and-build-with-sdk.sh chmod 500 install-and-build-with-sdk.sh @@ -50,53 +97,6 @@ jobs: --android-ndk-version="${NDK_VERSION}" \ "${SWIFT_VERSION}" - - name: Locate installed Swift toolchain - run: | - set -euo pipefail - SWIFT_BIN=$(find "$HOME/.swift-toolchains" -type f -name swift -path '*/usr/bin/swift' | head -n1) - if [ -z "$SWIFT_BIN" ]; then - echo "Error: could not find swift binary under $HOME/.swift-toolchains" >&2 - exit 1 - fi - echo "Found Swift binary: $SWIFT_BIN" - "$SWIFT_BIN" --version - echo "SWIFT_BIN=$SWIFT_BIN" >> "$GITHUB_ENV" - dirname "$SWIFT_BIN" >> "$GITHUB_PATH" - - - name: Create swiftly shim - # The example projects' Gradle scripts invoke Swift via swiftly - # (e.g. `swiftly run +6.3 swift build ...`). Install a tiny shim that - # strips the swiftly-specific arguments and forwards to the swift - # binary that the install script downloaded. - run: | - set -euo pipefail - mkdir -p "$HOME/.swiftly/bin" - cat > "$HOME/.swiftly/bin/swiftly" <<'SHIM' - #!/usr/bin/env bash - set -e - if [ -z "${SWIFT_BIN:-}" ]; then - echo "swiftly shim: SWIFT_BIN is not set" >&2 - exit 1 - fi - # Drop a leading "run" subcommand - if [ "${1:-}" = "run" ]; then shift; fi - # Drop any "+" tokens - new_args=() - for arg in "$@"; do - case "$arg" in - +*) ;; - *) new_args+=("$arg") ;; - esac - done - # Drop a leading "swift" since we're calling the swift binary directly - if [ "${#new_args[@]}" -gt 0 ] && [ "${new_args[0]}" = "swift" ]; then - new_args=("${new_args[@]:1}") - fi - exec "$SWIFT_BIN" "${new_args[@]}" - SHIM - chmod +x "$HOME/.swiftly/bin/swiftly" - echo "SWIFTLY_PATH=$HOME/.swiftly/bin/swiftly" >> "$GITHUB_ENV" - - name: Locate Swift Android SDK # The per-library build.gradle scripts (hashing-lib, weather-lib, # hello-cpp-swift/swift-lib) and swift-android.gradle.kts hardcode the @@ -138,7 +138,7 @@ jobs: working-directory: hello-swift-java/hashing-lib run: | set -euxo pipefail - "$SWIFT_BIN" package resolve + swift package resolve ./.build/checkouts/swift-java/gradlew \ --project-dir .build/checkouts/swift-java \ :SwiftKitCore:publishToMavenLocal From 0c20f0bb84361ca4e175d89c4c5b064a4bcf65d1 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 17:56:39 -0400 Subject: [PATCH 04/39] Update CI --- .github/workflows/ci.yml | 110 ++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 716100b..f415438 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,13 +11,14 @@ permissions: jobs: build: name: Build (swift:${{ matrix.swift_version }}) - runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: swift_version: ['nightly-main', 'nightly-6.3', '6.3'] sdk_triple: ['aarch64-unknown-linux-android28'] ndk_version: ['r27d'] + os: ['ubuntu-latest', 'macos-latest'] + runs-on: ${{ matrix.os }} env: SDK_TRIPLE: ${{ matrix.sdk_triple }} NDK_VERSION: ${{ matrix.ndk_version }} @@ -77,57 +78,72 @@ jobs: rm -f "$POST_INSTALL_FILE" swift --version - - name: Install Android Swift SDK and NDK - # Uses the build-swift-android mechanism from - # https://github.com/swiftlang/swift-java/blob/main/.github/workflows/pull_request.yml - # to install the Android Swift SDK and NDK and link them via the - # bundle's setup-android-sdk.sh script. The Swift toolchain itself - # was already installed in the previous step via swiftly. ":" is - # passed as a no-op build command because we don't want this script - # to also try to `swift build` anything. + - name: Install Android NDK run: | set -euxo pipefail - curl -L -O --retry 3 https://raw.githubusercontent.com/swiftlang/github-workflows/refs/heads/main/.github/workflows/scripts/install-and-build-with-sdk.sh - perl -pi -e "s#(download_and_extract_toolchain \".ANDROID_SDK_TAG\"\))#\1\n PATH=\\\$(dirname \\\$SWIFT_EXECUTABLE_FOR_ANDROID_SDK):\\\$PATH\n echo \"path is now \\\$PATH\"#" install-and-build-with-sdk.sh - chmod 500 install-and-build-with-sdk.sh - ./install-and-build-with-sdk.sh \ - --android \ - --build-command=":" \ - --android-sdk-triple="${SDK_TRIPLE}" \ - --android-ndk-version="${NDK_VERSION}" \ - "${SWIFT_VERSION}" - - - name: Locate Swift Android SDK - # The per-library build.gradle scripts (hashing-lib, weather-lib, - # hello-cpp-swift/swift-lib) and swift-android.gradle.kts hardcode the - # artifactbundle directory name to "swift-6.3-RELEASE_android.artifactbundle". - # When we install a different snapshot, expose the actual bundle under - # that name via a symlink so the Gradle scripts can locate the runtime libs. + curl -L -o ndk.zip --retry 3 "https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip" + unzip -q ndk.zip -d "$HOME" + rm ndk.zip + echo "ANDROID_NDK_HOME=$HOME/android-ndk-${NDK_VERSION}" >> "$GITHUB_ENV" + + - name: Install Android Swift SDK + # Looks up the Android Swift SDK URL and checksum from the swift.org + # install API and installs it via `swift sdk install`. For releases + # we use https://www.swift.org/api/v1/install/releases.json (which + # gives us each platform's checksum, but not a download URL — we + # construct that from the version). For nightlies we query + # https://www.swift.org/api/v1/install/dev//android-sdk.json + # for the latest snapshot tag and checksum. run: | - set -euo pipefail - SDK_BUNDLE="" - for d in "$HOME/.swiftpm/swift-sdks" "$HOME/.config/swiftpm/swift-sdks" "$HOME/Library/org.swift.swiftpm/swift-sdks"; do - if [ -d "$d" ]; then - found=$(find "$d" -maxdepth 1 -type d -name '*_android*.artifactbundle' | head -n1) - if [ -n "$found" ]; then - SDK_BUNDLE="$found" - break + set -euxo pipefail + case "$SWIFT_VERSION" in + nightly-*) + nightly_version="${SWIFT_VERSION#nightly-}" + sdk_json=$(curl -fsSL "https://www.swift.org/api/v1/install/dev/${nightly_version}/android-sdk.json") + snapshot_tag=$(echo "$sdk_json" | jq -r '.[0].dir') + sdk_checksum=$(echo "$sdk_json" | jq -r '.[0].checksum') + if [ "$nightly_version" = "main" ]; then + branch="development" + else + branch="swift-${nightly_version}-branch" fi - fi - done - if [ -z "$SDK_BUNDLE" ]; then - echo "Error: Android Swift SDK artifactbundle was not found" >&2 - find "$HOME/.swiftpm" "$HOME/.config/swiftpm" 2>/dev/null || true - exit 1 - fi - echo "Found Android SDK bundle: $SDK_BUNDLE" - SDK_DIR=$(dirname "$SDK_BUNDLE") - EXPECTED="$SDK_DIR/swift-6.3-RELEASE_android.artifactbundle" - if [ ! -e "$EXPECTED" ]; then - ln -s "$SDK_BUNDLE" "$EXPECTED" - echo "Symlinked $EXPECTED -> $SDK_BUNDLE" + sdk_url="https://download.swift.org/${branch}/android-sdk/${snapshot_tag}/${snapshot_tag}_android.artifactbundle.tar.gz" + ;; + *) + releases_json=$(curl -fsSL "https://www.swift.org/api/v1/install/releases.json") + # Pick the highest patch release whose name starts with the + # requested version (e.g. "6.3" -> "6.3.1" if it exists). + latest_version=$(echo "$releases_json" | jq -r --arg v "$SWIFT_VERSION" \ + '[.[] | select(.name | startswith($v))] + | sort_by(.name | split(".") | map(tonumber? // 0)) + | last + | .name') + if [ -z "$latest_version" ] || [ "$latest_version" = "null" ]; then + echo "Error: no Swift release matching '$SWIFT_VERSION' found in releases.json" >&2 + exit 1 + fi + sdk_checksum=$(echo "$releases_json" | jq -r --arg v "$latest_version" \ + '.[] | select(.name == $v) | .platforms[] | select(.platform == "android") | .checksum') + snapshot_tag="swift-${latest_version}-RELEASE" + sdk_url="https://download.swift.org/swift-${latest_version}-release/android-sdk/${snapshot_tag}/${snapshot_tag}_android.artifactbundle.tar.gz" + ;; + esac + echo "Installing Android Swift SDK" + echo " url: $sdk_url" + echo " checksum: $sdk_checksum" + swift sdk install "$sdk_url" --checksum "$sdk_checksum" + swift sdk list + + - name: Configure Swift Android SDK + run: | + set -euo pipefail + cd $HOME/.swiftpm/swift-sdks/*android*.artifactbundle || cd $HOME/.config/swiftpm/swift-sdks/*android*.artifactbundle || cd $HOME/Library/org.swift.swiftpm/swift-sdks/*android*.artifactbundle + # Link the SDK against the NDK we installed in the previous step. + # Someday we might not need this script, so gracefully skip it + # if it does not exist. + if [[ -x "./swift-android/scripts/setup-android-sdk.sh" ]]; then + "./swift-android/scripts/setup-android-sdk.sh" fi - echo "SWIFT_SDK_PATH=$SDK_DIR" >> "$GITHUB_ENV" - name: Publish swift-java packages to local Maven # The hashing-lib, weather-lib, and hello-cpp-swift/swift-lib modules From 37bf3dabbe737f1eabe841a6169c3e4b7b6b7d3d Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 18:13:19 -0400 Subject: [PATCH 05/39] Update CI --- .github/workflows/ci.yml | 91 ++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f415438..2e9c448 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,8 +9,7 @@ permissions: contents: read jobs: - build: - name: Build (swift:${{ matrix.swift_version }}) + build-examples: strategy: fail-fast: false matrix: @@ -27,7 +26,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up JDK 25 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: '25' @@ -35,58 +34,46 @@ jobs: - name: Install swiftly run: | set -euxo pipefail - sudo apt-get -q update - sudo apt-get -yq install curl jq gpg unzip - ARCH="$(uname -m)" - curl -L -O --retry 3 "https://download.swift.org/swiftly/linux/swiftly-${ARCH}.tar.gz" - tar -xzf "swiftly-${ARCH}.tar.gz" - ./swiftly init \ - --assume-yes \ - --skip-install \ - --no-modify-profile \ - --quiet-shell-followup - rm -f "swiftly-${ARCH}.tar.gz" swiftly - # The example projects' Gradle scripts look for swiftly under - # $HOME/.local/share/swiftly/bin, which is also where the official - # installer puts it. Add it to PATH for subsequent steps. - echo "$HOME/.local/share/swiftly/bin" >> "$GITHUB_PATH" - "$HOME/.local/share/swiftly/bin/swiftly" --version - - - name: Install Swift via swiftly - run: | - set -euxo pipefail - # Translate the matrix's swift_version into the form swiftly expects: - # nightly-main -> main-snapshot - # nightly-6.3 -> 6.3-snapshot - # 6.3 / 6.3.0 -> passed through as-is - case "$SWIFT_VERSION" in - nightly-main) SWIFTLY_VER="main-snapshot" ;; - nightly-*) SWIFTLY_VER="${SWIFT_VERSION#nightly-}-snapshot" ;; - *) SWIFTLY_VER="$SWIFT_VERSION" ;; - esac - POST_INSTALL_FILE="$(mktemp)" - swiftly install "$SWIFTLY_VER" \ - --use \ - --assume-yes \ - --post-install-file="$POST_INSTALL_FILE" - # Some toolchains print follow-up commands (e.g. apt-get install - # of missing system libs) to the post-install file. Run them if - # any were emitted. - if [ -s "$POST_INSTALL_FILE" ]; then - sudo bash "$POST_INSTALL_FILE" + if [[ "${RUNNER_OS}" == "Linux" ]]; then + sudo apt-get -yq update install curl jq gpg unzip + ARCH="$(uname -m)" + curl -L -O --retry 3 "https://download.swift.org/swiftly/linux/swiftly-${ARCH}.tar.gz" + tar -xzf "swiftly-${ARCH}.tar.gz" + ./swiftly init \ + --assume-yes \ + --skip-install \ + --no-modify-profile \ + --quiet-shell-followup + rm -f "swiftly-${ARCH}.tar.gz" swiftly + # The example projects' Gradle scripts look for swiftly under + # $HOME/.local/share/swiftly/bin, which is also where the official + # installer puts it. Add it to PATH for subsequent steps. + echo "$HOME/.local/share/swiftly/bin" >> "$GITHUB_PATH" + "$HOME/.local/share/swiftly/bin/swiftly" --version + elif [[ "${RUNNER_OS}" == "macOS" ]]; then + curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg && \ + installer -pkg swiftly.pkg -target CurrentUserHomeDirectory && \ + ~/.swiftly/bin/swiftly init --quiet-shell-followup && \ + . "${SWIFTLY_HOME_DIR:-$HOME/.swiftly}/env.sh" && \ + hash -r + + echo "$HOME/.swiftly/bin" >> "$GITHUB_PATH" + "$HOME/.swiftly/bin/swiftly" --version + else + echo "Unknown OS: ${RUNNER_OS}" + exit 1 fi - rm -f "$POST_INSTALL_FILE" - swift --version - name: Install Android NDK run: | set -euxo pipefail - curl -L -o ndk.zip --retry 3 "https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip" + OS="$(uname -s | tr '[A-Z]' '[a-z]')" + curl -L -o ndk.zip --retry 3 "https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-${OS}.zip" unzip -q ndk.zip -d "$HOME" rm ndk.zip echo "ANDROID_NDK_HOME=$HOME/android-ndk-${NDK_VERSION}" >> "$GITHUB_ENV" - - name: Install Android Swift SDK + - name: Install Android Swift SDK and matching host toolchain # Looks up the Android Swift SDK URL and checksum from the swift.org # install API and installs it via `swift sdk install`. For releases # we use https://www.swift.org/api/v1/install/releases.json (which @@ -128,9 +115,11 @@ jobs: sdk_url="https://download.swift.org/swift-${latest_version}-release/android-sdk/${snapshot_tag}/${snapshot_tag}_android.artifactbundle.tar.gz" ;; esac - echo "Installing Android Swift SDK" + echo "Installing Android Swift SDK and host toolchain" + echo " tag: $snapshot_tag" echo " url: $sdk_url" echo " checksum: $sdk_checksum" + swiftly install ${snapshot_tag} swift sdk install "$sdk_url" --checksum "$sdk_checksum" swift sdk list @@ -158,35 +147,27 @@ jobs: ./.build/checkouts/swift-java/gradlew \ --project-dir .build/checkouts/swift-java \ :SwiftKitCore:publishToMavenLocal - continue-on-error: true - name: Build hello-swift-raw-jni APK run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace - continue-on-error: true - name: Build hello-swift-raw-jni-callback APK run: ./gradlew :hello-swift-raw-jni-callback:assembleDebug --stacktrace - continue-on-error: true - name: Build hello-swift-raw-jni-library run: ./gradlew :hello-swift-raw-jni-library:assembleDebug --stacktrace - continue-on-error: true - name: Build native-activity APK run: ./gradlew :native-activity:assembleDebug --stacktrace - continue-on-error: true - name: Build hello-swift-java APK run: ./gradlew :hello-swift-java-hashing-app:assembleDebug --stacktrace - continue-on-error: true - name: Build swift-java-weather-app APK run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace - continue-on-error: true - name: Build hello-cpp-swift APK run: ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace - continue-on-error: true - name: Upload APK artifacts if: always() From 6466620aacc9e22572de13799f9b10429e4d0b0a Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 18:20:57 -0400 Subject: [PATCH 06/39] Update CI --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e9c448..8d32453 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: run: | set -euxo pipefail if [[ "${RUNNER_OS}" == "Linux" ]]; then - sudo apt-get -yq update install curl jq gpg unzip + sudo apt-get -yq install curl jq gpg unzip ARCH="$(uname -m)" curl -L -O --retry 3 "https://download.swift.org/swiftly/linux/swiftly-${ARCH}.tar.gz" tar -xzf "swiftly-${ARCH}.tar.gz" @@ -119,7 +119,7 @@ jobs: echo " tag: $snapshot_tag" echo " url: $sdk_url" echo " checksum: $sdk_checksum" - swiftly install ${snapshot_tag} + swiftly install ${${snapshot_tag/swift-/}/-RELEASE/} swift sdk install "$sdk_url" --checksum "$sdk_checksum" swift sdk list @@ -149,7 +149,7 @@ jobs: :SwiftKitCore:publishToMavenLocal - name: Build hello-swift-raw-jni APK - run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace + run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace --verbose - name: Build hello-swift-raw-jni-callback APK run: ./gradlew :hello-swift-raw-jni-callback:assembleDebug --stacktrace @@ -176,3 +176,4 @@ jobs: name: apks-${{ matrix.swift_version }} path: '**/build/outputs/apk/**/*.apk' if-no-files-found: warn + From 49da23142e61e4487acf85928fcd802ef53a9bdd Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 18:44:40 -0400 Subject: [PATCH 07/39] Update CI --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d32453..77f946a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,11 +115,17 @@ jobs: sdk_url="https://download.swift.org/swift-${latest_version}-release/android-sdk/${snapshot_tag}/${snapshot_tag}_android.artifactbundle.tar.gz" ;; esac + + swift_install=${snapshot_tag} + # trim leading "swift-" and trailing "-RELEASE" + swift_install=${swift_install/swift-/} + swift_install=${swift_install/-RELEASE/} + echo "Installing Android Swift SDK and host toolchain" - echo " tag: $snapshot_tag" + echo " tag: $swift_install" echo " url: $sdk_url" echo " checksum: $sdk_checksum" - swiftly install ${${snapshot_tag/swift-/}/-RELEASE/} + swiftly install "${swift_install}" swift sdk install "$sdk_url" --checksum "$sdk_checksum" swift sdk list From 0fbc79f7389e16a4e1135ca11aa104d23feaff65 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 18:54:21 -0400 Subject: [PATCH 08/39] Update CI --- .github/workflows/ci.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77f946a..a99cf3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: run: | set -euxo pipefail if [[ "${RUNNER_OS}" == "Linux" ]]; then - sudo apt-get -yq install curl jq gpg unzip + sudo apt-get -yq install curl jq gpg unzip libcurl4-openssl-dev ARCH="$(uname -m)" curl -L -O --retry 3 "https://download.swift.org/swiftly/linux/swiftly-${ARCH}.tar.gz" tar -xzf "swiftly-${ARCH}.tar.gz" @@ -75,12 +75,7 @@ jobs: - name: Install Android Swift SDK and matching host toolchain # Looks up the Android Swift SDK URL and checksum from the swift.org - # install API and installs it via `swift sdk install`. For releases - # we use https://www.swift.org/api/v1/install/releases.json (which - # gives us each platform's checksum, but not a download URL — we - # construct that from the version). For nightlies we query - # https://www.swift.org/api/v1/install/dev//android-sdk.json - # for the latest snapshot tag and checksum. + # install API and installs it via `swift sdk install`. run: | set -euxo pipefail case "$SWIFT_VERSION" in @@ -155,7 +150,7 @@ jobs: :SwiftKitCore:publishToMavenLocal - name: Build hello-swift-raw-jni APK - run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace --verbose + run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace --debug - name: Build hello-swift-raw-jni-callback APK run: ./gradlew :hello-swift-raw-jni-callback:assembleDebug --stacktrace @@ -177,7 +172,7 @@ jobs: - name: Upload APK artifacts if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: apks-${{ matrix.swift_version }} path: '**/build/outputs/apk/**/*.apk' From e10dd0d6191946e0f5d20177442a112145b97ef3 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 22:51:02 -0400 Subject: [PATCH 09/39] Update CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a99cf3c..5abc3a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,7 +113,7 @@ jobs: swift_install=${snapshot_tag} # trim leading "swift-" and trailing "-RELEASE" - swift_install=${swift_install/swift-/} + swift_install=${swift_install#swift-} swift_install=${swift_install/-RELEASE/} echo "Installing Android Swift SDK and host toolchain" @@ -150,7 +150,7 @@ jobs: :SwiftKitCore:publishToMavenLocal - name: Build hello-swift-raw-jni APK - run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace --debug + run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace - name: Build hello-swift-raw-jni-callback APK run: ./gradlew :hello-swift-raw-jni-callback:assembleDebug --stacktrace From 270fef19d9156ad404b03e0950bed72c477a05d0 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 22:54:02 -0400 Subject: [PATCH 10/39] Update CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5abc3a5..8b7892f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,7 +105,7 @@ jobs: exit 1 fi sdk_checksum=$(echo "$releases_json" | jq -r --arg v "$latest_version" \ - '.[] | select(.name == $v) | .platforms[] | select(.platform == "android") | .checksum') + '.[] | select(.name == $v) | .platforms[] | select(.platform == "android-sdk") | .checksum') snapshot_tag="swift-${latest_version}-RELEASE" sdk_url="https://download.swift.org/swift-${latest_version}-release/android-sdk/${snapshot_tag}/${snapshot_tag}_android.artifactbundle.tar.gz" ;; From 63f4b89e32a8e01da04f607e5dcaf2bb68ed9fad Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 23:11:41 -0400 Subject: [PATCH 11/39] Update CI --- .github/workflows/ci.yml | 4 ++++ swift-android.gradle.kts | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b7892f..b13f768 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,6 +124,10 @@ jobs: swift sdk install "$sdk_url" --checksum "$sdk_checksum" swift sdk list + # set environment variables used by swift-android.gradle.kts + echo "SWIFT_VERSION=${swift_install}" >> $GITHUB_ENV + echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag}_android" >> $GITHUB_ENV + - name: Configure Swift Android SDK run: | set -euo pipefail diff --git a/swift-android.gradle.kts b/swift-android.gradle.kts index 37fa46a..08ca0fa 100644 --- a/swift-android.gradle.kts +++ b/swift-android.gradle.kts @@ -14,8 +14,14 @@ data class SwiftConfig( var releaseExtraBuildFlags: List = emptyList(), var swiftlyPath: String? = null, // Optional custom swiftly path var swiftSDKPath: String? = null, // Optional custom Swift SDK path - var swiftVersion: String = "6.3", // Swift version - var androidSdkVersion: String = "6.3-RELEASE_android" // SDK version + // Swift toolchain version passed to swiftly (e.g. "6.3", "main-snapshot"). + // Can be overridden via the SWIFT_VERSION environment variable, which is + // useful for CI matrices that test multiple toolchains. + var swiftVersion: String = System.getenv("SWIFT_VERSION")?.takeIf { it.isNotEmpty() } ?: "6.3", + // Android Swift SDK artifactbundle suffix. Substituted into the bundle + // directory name as "swift-${androidSdkVersion}.artifactbundle". Can be + // overridden via the SWIFT_ANDROID_SDK_VERSION environment variable. + var androidSdkVersion: String = System.getenv("SWIFT_ANDROID_SDK_VERSION")?.takeIf { it.isNotEmpty() } ?: "${swiftVersion}-RELEASE_android" ) // Architecture definitions @@ -296,4 +302,4 @@ project.afterEvaluate { } else { throw GradleException("Android extension not found. Make sure to apply this script after the Android plugin.") } -} \ No newline at end of file +} From 7db51f66c4905b796f86aa6183d0fa1e36f170f0 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 23:17:47 -0400 Subject: [PATCH 12/39] Update CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b13f768..8ab4a33 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -126,7 +126,7 @@ jobs: # set environment variables used by swift-android.gradle.kts echo "SWIFT_VERSION=${swift_install}" >> $GITHUB_ENV - echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag}_android" >> $GITHUB_ENV + echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag#swift-}_android" >> $GITHUB_ENV - name: Configure Swift Android SDK run: | From eb07553a5fe3d94a6894de189c508b4dbac0fff6 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 23:23:59 -0400 Subject: [PATCH 13/39] Update CI --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ab4a33..0eb037a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -171,7 +171,9 @@ jobs: - name: Build swift-java-weather-app APK run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace + # skipping due to: error: local binary target 'HelloWorldCpp' at '/Users/runner/work/swift-android-examples/swift-android-examples/hello-cpp-swift/cpp-lib/prebuilt/HelloWorldCpp.artifactbundle' does not contain a binary artifact. - name: Build hello-cpp-swift APK + if: false run: ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace - name: Upload APK artifacts From 5b2f0225b675a9401c287dba41d978b92acece2e Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 23:25:23 -0400 Subject: [PATCH 14/39] Update CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0eb037a..007069b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['nightly-main', 'nightly-6.3', '6.3'] + swift_version: ['nightly-main', '6.3'] sdk_triple: ['aarch64-unknown-linux-android28'] ndk_version: ['r27d'] os: ['ubuntu-latest', 'macos-latest'] From 571da46f48ca6c79017d21c86d1a8fb31f2420e7 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 23:27:28 -0400 Subject: [PATCH 15/39] Update CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 007069b..ece4629 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ permissions: jobs: build-examples: + name: Build ${{ matrix.os }} ${{ matrix.swift_version }} strategy: fail-fast: false matrix: From cfecb383a257f352fc99e7552e624109d9061919 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 8 Apr 2026 23:50:08 -0400 Subject: [PATCH 16/39] Update CI --- .github/workflows/ci.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ece4629..429bcbc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,6 +154,13 @@ jobs: --project-dir .build/checkouts/swift-java \ :SwiftKitCore:publishToMavenLocal + - name: Build hello-cpp-swift APK + run: | + cd hello-cpp-swift/cpp-lib + ./build-android-static.sh + cd - + ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace + - name: Build hello-swift-raw-jni APK run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace @@ -172,11 +179,6 @@ jobs: - name: Build swift-java-weather-app APK run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace - # skipping due to: error: local binary target 'HelloWorldCpp' at '/Users/runner/work/swift-android-examples/swift-android-examples/hello-cpp-swift/cpp-lib/prebuilt/HelloWorldCpp.artifactbundle' does not contain a binary artifact. - - name: Build hello-cpp-swift APK - if: false - run: ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace - - name: Upload APK artifacts if: always() uses: actions/upload-artifact@v7 From f8ab14d649c9573e4fe92b2d8d8acb9bb5775f2f Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 9 Apr 2026 00:03:35 -0400 Subject: [PATCH 17/39] Update CI --- .github/workflows/ci.yml | 14 +++++++------- hello-cpp-swift/swift-lib/build.gradle | 11 +++++++++-- hello-swift-java/hashing-lib/build.gradle | 11 +++++++++-- swift-java-weather-app/weather-lib/build.gradle | 11 +++++++++-- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 429bcbc..cd33c0d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,13 +154,6 @@ jobs: --project-dir .build/checkouts/swift-java \ :SwiftKitCore:publishToMavenLocal - - name: Build hello-cpp-swift APK - run: | - cd hello-cpp-swift/cpp-lib - ./build-android-static.sh - cd - - ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace - - name: Build hello-swift-raw-jni APK run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace @@ -179,6 +172,13 @@ jobs: - name: Build swift-java-weather-app APK run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace + - name: Build hello-cpp-swift APK + run: | + cd hello-cpp-swift/cpp-lib + ./build-android-static.sh + cd - + ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace + - name: Upload APK artifacts if: always() uses: actions/upload-artifact@v7 diff --git a/hello-cpp-swift/swift-lib/build.gradle b/hello-cpp-swift/swift-lib/build.gradle index 63b2fb8..cadc804 100644 --- a/hello-cpp-swift/swift-lib/build.gradle +++ b/hello-cpp-swift/swift-lib/build.gradle @@ -89,8 +89,15 @@ def swiftRuntimeLibs = [ "swiftSynchronization" ] -def sdkName = "swift-6.3-RELEASE_android.artifactbundle" -def swiftVersion = "6.3" +// Swift toolchain version passed to swiftly (e.g. "6.3", "main-snapshot"). +// Can be overridden via the SWIFT_VERSION environment variable, which is +// useful for CI matrices that test multiple toolchains. +def swiftVersion = System.getenv("SWIFT_VERSION") ?: "6.3" +// Android Swift SDK artifactbundle suffix. Substituted into the bundle +// directory name as "swift-${androidSdkVersion}.artifactbundle". Can be +// overridden via the SWIFT_ANDROID_SDK_VERSION environment variable. +def androidSdkVersion = System.getenv("SWIFT_ANDROID_SDK_VERSION") ?: "${swiftVersion}-RELEASE_android" +def sdkName = "swift-${androidSdkVersion}.artifactbundle" def minSdk = android.defaultConfig.minSdkVersion.apiLevel def abis = [ diff --git a/hello-swift-java/hashing-lib/build.gradle b/hello-swift-java/hashing-lib/build.gradle index 9fd45a7..da2d25d 100644 --- a/hello-swift-java/hashing-lib/build.gradle +++ b/hello-swift-java/hashing-lib/build.gradle @@ -99,8 +99,15 @@ def swiftRuntimeLibs = [ "swiftSynchronization" ] -def sdkName = "swift-6.3-RELEASE_android.artifactbundle" -def swiftVersion = "6.3" +// Swift toolchain version passed to swiftly (e.g. "6.3", "main-snapshot"). +// Can be overridden via the SWIFT_VERSION environment variable, which is +// useful for CI matrices that test multiple toolchains. +def swiftVersion = System.getenv("SWIFT_VERSION") ?: "6.3" +// Android Swift SDK artifactbundle suffix. Substituted into the bundle +// directory name as "swift-${androidSdkVersion}.artifactbundle". Can be +// overridden via the SWIFT_ANDROID_SDK_VERSION environment variable. +def androidSdkVersion = System.getenv("SWIFT_ANDROID_SDK_VERSION") ?: "${swiftVersion}-RELEASE_android" +def sdkName = "swift-${androidSdkVersion}.artifactbundle" def minSdk = android.defaultConfig.minSdkVersion.apiLevel /** * Android ABIs and their Swift triple mappings diff --git a/swift-java-weather-app/weather-lib/build.gradle b/swift-java-weather-app/weather-lib/build.gradle index db8a66d..38b7d53 100644 --- a/swift-java-weather-app/weather-lib/build.gradle +++ b/swift-java-weather-app/weather-lib/build.gradle @@ -98,8 +98,15 @@ def swiftRuntimeLibs = [ "_FoundationICU", "swiftSynchronization" ] -def sdkName = "swift-6.3-RELEASE_android.artifactbundle" -def swiftVersion = "6.3" +// Swift toolchain version passed to swiftly (e.g. "6.3", "main-snapshot"). +// Can be overridden via the SWIFT_VERSION environment variable, which is +// useful for CI matrices that test multiple toolchains. +def swiftVersion = System.getenv("SWIFT_VERSION") ?: "6.3" +// Android Swift SDK artifactbundle suffix. Substituted into the bundle +// directory name as "swift-${androidSdkVersion}.artifactbundle". Can be +// overridden via the SWIFT_ANDROID_SDK_VERSION environment variable. +def androidSdkVersion = System.getenv("SWIFT_ANDROID_SDK_VERSION") ?: "${swiftVersion}-RELEASE_android" +def sdkName = "swift-${androidSdkVersion}.artifactbundle" def minSdk = android.defaultConfig.minSdkVersion.apiLevel /** * Android ABIs and their Swift triple mappings From 9b4ba795caef196129bd75e3d950e1aa60da6be8 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 9 Apr 2026 00:30:43 -0400 Subject: [PATCH 18/39] Update CI --- .github/workflows/ci.yml | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd33c0d..a7540fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,8 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['nightly-main', '6.3'] + #swift_version: ['nightly-main', '6.3'] + swift_version: ['6.3'] sdk_triple: ['aarch64-unknown-linux-android28'] ndk_version: ['r27d'] os: ['ubuntu-latest', 'macos-latest'] @@ -179,11 +180,45 @@ jobs: cd - ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace + - name: Summarize APK artifacts + if: always() + run: | + echo "## APK Artifacts (${{ matrix.os }} / swift:${{ matrix.swift_version }} / ${{ matrix.sdk_triple }})" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "| Project | APK | Size |" >> "$GITHUB_STEP_SUMMARY" + echo "|---------|-----|------|" >> "$GITHUB_STEP_SUMMARY" + found=0 + while IFS= read -r apk; do + found=1 + # Derive a human-readable project name from the path + project=$(echo "$apk" | sed -E 's#^\./##; s#/build/outputs/.*##') + name=$(basename "$apk") + # Human-readable size + if command -v numfmt >/dev/null 2>&1; then + size=$(stat --format='%s' "$apk" 2>/dev/null | numfmt --to=iec-i --suffix=B) + else + bytes=$(stat -f '%z' "$apk" 2>/dev/null || echo 0) + if [ "$bytes" -ge 1073741824 ]; then + size="$(awk "BEGIN {printf \"%.1f\", $bytes/1073741824}")GiB" + elif [ "$bytes" -ge 1048576 ]; then + size="$(awk "BEGIN {printf \"%.1f\", $bytes/1048576}")MiB" + elif [ "$bytes" -ge 1024 ]; then + size="$(awk "BEGIN {printf \"%.1f\", $bytes/1024}")KiB" + else + size="${bytes}B" + fi + fi + echo "| \`$project\` | \`$name\` | $size |" >> "$GITHUB_STEP_SUMMARY" + done < <(find . -path '*/build/outputs/apk/*.apk' -type f | sort) + if [ "$found" -eq 0 ]; then + echo "| _(none)_ | — | — |" >> "$GITHUB_STEP_SUMMARY" + fi + - name: Upload APK artifacts if: always() uses: actions/upload-artifact@v7 with: - name: apks-${{ matrix.swift_version }} + name: apks-${{ matrix.os }}-${{ matrix.swift_version }}-${{ matrix.sdk_triple }}-${{ matrix.ndk_version }} path: '**/build/outputs/apk/**/*.apk' if-no-files-found: warn From 6a59d5f3a6a0c31793d485d7fc07a719ce63fa33 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 9 Apr 2026 00:39:33 -0400 Subject: [PATCH 19/39] Update CI --- .github/workflows/ci.yml | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7540fb..667deb5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,21 +193,8 @@ jobs: # Derive a human-readable project name from the path project=$(echo "$apk" | sed -E 's#^\./##; s#/build/outputs/.*##') name=$(basename "$apk") - # Human-readable size - if command -v numfmt >/dev/null 2>&1; then - size=$(stat --format='%s' "$apk" 2>/dev/null | numfmt --to=iec-i --suffix=B) - else - bytes=$(stat -f '%z' "$apk" 2>/dev/null || echo 0) - if [ "$bytes" -ge 1073741824 ]; then - size="$(awk "BEGIN {printf \"%.1f\", $bytes/1073741824}")GiB" - elif [ "$bytes" -ge 1048576 ]; then - size="$(awk "BEGIN {printf \"%.1f\", $bytes/1048576}")MiB" - elif [ "$bytes" -ge 1024 ]; then - size="$(awk "BEGIN {printf \"%.1f\", $bytes/1024}")KiB" - else - size="${bytes}B" - fi - fi + # Human-readable size (du -h works on both Linux and macOS) + size=$(du -h "$apk" | cut -f1 | tr -d '[:space:]') echo "| \`$project\` | \`$name\` | $size |" >> "$GITHUB_STEP_SUMMARY" done < <(find . -path '*/build/outputs/apk/*.apk' -type f | sort) if [ "$found" -eq 0 ]; then From e0258fa2de0be9ef6ddae0f3a8d77da690f86da8 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 30 Apr 2026 12:06:13 -0400 Subject: [PATCH 20/39] Update build matrix --- .github/workflows/ci.yml | 57 +++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 667deb5..cbdaa1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,18 +4,27 @@ on: push: branches: [main] pull_request: + workflow_dispatch: + inputs: + swift_versions: + description: 'JSON array of Swift versions to test (e.g. ["6.3"], ["6.3", "nightly-main"])' + required: false + default: '["6.3"]' permissions: contents: read +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: build-examples: name: Build ${{ matrix.os }} ${{ matrix.swift_version }} strategy: fail-fast: false matrix: - #swift_version: ['nightly-main', '6.3'] - swift_version: ['6.3'] + swift_version: ${{ fromJSON(inputs.swift_versions || '["6.3"]') }} sdk_triple: ['aarch64-unknown-linux-android28'] ndk_version: ['r27d'] os: ['ubuntu-latest', 'macos-latest'] @@ -53,12 +62,11 @@ jobs: echo "$HOME/.local/share/swiftly/bin" >> "$GITHUB_PATH" "$HOME/.local/share/swiftly/bin/swiftly" --version elif [[ "${RUNNER_OS}" == "macOS" ]]; then - curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg && \ - installer -pkg swiftly.pkg -target CurrentUserHomeDirectory && \ - ~/.swiftly/bin/swiftly init --quiet-shell-followup && \ - . "${SWIFTLY_HOME_DIR:-$HOME/.swiftly}/env.sh" && \ + curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg + installer -pkg swiftly.pkg -target CurrentUserHomeDirectory + ~/.swiftly/bin/swiftly init --quiet-shell-followup + . "${SWIFTLY_HOME_DIR:-$HOME/.swiftly}/env.sh" hash -r - echo "$HOME/.swiftly/bin" >> "$GITHUB_PATH" "$HOME/.swiftly/bin/swiftly" --version else @@ -126,14 +134,31 @@ jobs: swift sdk install "$sdk_url" --checksum "$sdk_checksum" swift sdk list - # set environment variables used by swift-android.gradle.kts - echo "SWIFT_VERSION=${swift_install}" >> $GITHUB_ENV - echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag#swift-}_android" >> $GITHUB_ENV + # Override the matrix-supplied SWIFT_VERSION (e.g. "6.3") with the + # resolved patch version (e.g. "6.3.1") so the gradle scripts pick up + # the actual artifactbundle directory name produced by `swift sdk + # install`. SWIFT_ANDROID_SDK_VERSION pins the bundle suffix for the + # same reason. + echo "SWIFT_VERSION=${swift_install}" >> "$GITHUB_ENV" + echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag#swift-}_android" >> "$GITHUB_ENV" - name: Configure Swift Android SDK run: | set -euo pipefail - cd $HOME/.swiftpm/swift-sdks/*android*.artifactbundle || cd $HOME/.config/swiftpm/swift-sdks/*android*.artifactbundle || cd $HOME/Library/org.swift.swiftpm/swift-sdks/*android*.artifactbundle + # Locate the installed Android SDK artifactbundle. Its parent + # directory varies by OS / swiftpm version, so try the known + # candidates and pick the first one that actually matches. + shopt -s nullglob + candidates=( + "$HOME"/.swiftpm/swift-sdks/*android*.artifactbundle + "$HOME"/.config/swiftpm/swift-sdks/*android*.artifactbundle + "$HOME"/Library/org.swift.swiftpm/swift-sdks/*android*.artifactbundle + ) + if [[ ${#candidates[@]} -eq 0 ]]; then + echo "No android SDK artifactbundle found in any known location" >&2 + exit 1 + fi + cd "${candidates[0]}" # Link the SDK against the NDK we installed in the previous step. # Someday we might not need this script, so gracefully skip it # if it does not exist. @@ -173,12 +198,12 @@ jobs: - name: Build swift-java-weather-app APK run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace + - name: Build hello-cpp-swift cpp-lib + working-directory: hello-cpp-swift/cpp-lib + run: ./build-android-static.sh + - name: Build hello-cpp-swift APK - run: | - cd hello-cpp-swift/cpp-lib - ./build-android-static.sh - cd - - ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace + run: ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace - name: Summarize APK artifacts if: always() From 75f826b9e02c7f1da060705fab415086db5b8291 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 13:35:13 -0400 Subject: [PATCH 21/39] Add nightly-main to SDK matrix --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cbdaa1e..99ad797 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: swift_versions: description: 'JSON array of Swift versions to test (e.g. ["6.3"], ["6.3", "nightly-main"])' required: false - default: '["6.3"]' + default: '["6.3", "nightly-main"]' permissions: contents: read From 6f7c4351557012eb4bc9674e4de0b79dc6809d61 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 13:36:47 -0400 Subject: [PATCH 22/39] Run CI on push --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99ad797..2580558 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: ci on: push: - branches: [main] + #branches: [main] pull_request: workflow_dispatch: inputs: From 1f48004646b6f63f19b6e5f57fa5ffe2c2ec28bb Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 14:46:19 -0400 Subject: [PATCH 23/39] Run apt-get update on Linux to ensure we can get libcurl4-openssl-dev --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2580558..67839fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ${{ fromJSON(inputs.swift_versions || '["6.3"]') }} + swift_version: ${{ fromJSON(inputs.swift_versions || '["6.3", "nightly-main"]') }} sdk_triple: ['aarch64-unknown-linux-android28'] ndk_version: ['r27d'] os: ['ubuntu-latest', 'macos-latest'] @@ -46,6 +46,7 @@ jobs: run: | set -euxo pipefail if [[ "${RUNNER_OS}" == "Linux" ]]; then + sudo apt-get update sudo apt-get -yq install curl jq gpg unzip libcurl4-openssl-dev ARCH="$(uname -m)" curl -L -O --retry 3 "https://download.swift.org/swiftly/linux/swiftly-${ARCH}.tar.gz" From 1e6c8ee6ea36290f2e4f5c8a84bfc42461abe688 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 15:25:27 -0400 Subject: [PATCH 24/39] Enable --build-system native to work around https://github.com/swiftlang/swift-build/issues/1363 --- hello-cpp-swift/swift-lib/build.gradle | 2 +- hello-swift-java/hashing-lib/build.gradle | 4 ++-- swift-android.gradle.kts | 1 + swift-java-weather-app/weather-lib/build.gradle | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hello-cpp-swift/swift-lib/build.gradle b/hello-cpp-swift/swift-lib/build.gradle index cadc804..1662e39 100644 --- a/hello-cpp-swift/swift-lib/build.gradle +++ b/hello-cpp-swift/swift-lib/build.gradle @@ -132,7 +132,7 @@ abis.each { abi, info -> workingDir = layout.projectDirectory executable(getSwiftlyPath()) - args("run", "swift", "build", "+${swiftVersion}", "--swift-sdk", info.triple) + args("run", "swift", "build", "+${swiftVersion}", "--swift-sdk", info.triple, "--build-system", "native") } buildSwiftAll.configure { dependsOn(task) } diff --git a/hello-swift-java/hashing-lib/build.gradle b/hello-swift-java/hashing-lib/build.gradle index da2d25d..58416f0 100644 --- a/hello-swift-java/hashing-lib/build.gradle +++ b/hello-swift-java/hashing-lib/build.gradle @@ -145,7 +145,7 @@ abis.each { abi, info -> workingDir = layout.projectDirectory executable(getSwiftlyPath()) - args("run", "swift", "build", "+${swiftVersion}", "--swift-sdk", info.triple) + args("run", "swift", "build", "+${swiftVersion}", "--swift-sdk", info.triple, "--build-system", "native") } buildSwiftAll.configure { dependsOn(task) } @@ -197,4 +197,4 @@ android { } // Make sure we run our tasks before build -preBuild.dependsOn(copyJniLibs) \ No newline at end of file +preBuild.dependsOn(copyJniLibs) diff --git a/swift-android.gradle.kts b/swift-android.gradle.kts index 08ca0fa..9b22916 100644 --- a/swift-android.gradle.kts +++ b/swift-android.gradle.kts @@ -140,6 +140,7 @@ fun createSwiftBuildTask( val defaultArgs = listOf( "run", "+${swiftVersion}", "swift", "build", "--swift-sdk", sdkName, + "--build-system", "native", // old build system until we can sort out the output paths "-Xswiftc", "-static-stdlib", "-Xswiftc", "-resource-dir", "-Xswiftc", resourcesPath diff --git a/swift-java-weather-app/weather-lib/build.gradle b/swift-java-weather-app/weather-lib/build.gradle index 38b7d53..ce3a838 100644 --- a/swift-java-weather-app/weather-lib/build.gradle +++ b/swift-java-weather-app/weather-lib/build.gradle @@ -147,7 +147,7 @@ abis.each { abi, info -> // We must disable sandbox, because we use the `enableJavaCallbacks` feature // of swift-java. - args("run", "swift", "build", "+${swiftVersion}", "--swift-sdk", info.triple, "--disable-sandbox") + args("run", "swift", "build", "+${swiftVersion}", "--swift-sdk", info.triple, "--build-system", "native", "--disable-sandbox") } buildSwiftAll.configure { dependsOn(task) } @@ -199,4 +199,4 @@ android { } // Make sure we run our tasks before build -preBuild.dependsOn(copyJniLibs) \ No newline at end of file +preBuild.dependsOn(copyJniLibs) From 6e2724df250885a36259d3f0f4ab02dcdd56d51a Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 15:49:59 -0400 Subject: [PATCH 25/39] Add ndk caching and remove unused sdk_triple --- .github/workflows/ci.yml | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67839fc..047dd89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,8 +2,9 @@ name: ci on: push: - #branches: [main] pull_request: + schedule: + - cron: '0 0 * * *' workflow_dispatch: inputs: swift_versions: @@ -25,12 +26,10 @@ jobs: fail-fast: false matrix: swift_version: ${{ fromJSON(inputs.swift_versions || '["6.3", "nightly-main"]') }} - sdk_triple: ['aarch64-unknown-linux-android28'] - ndk_version: ['r27d'] + ndk_version: ['r27d', 'r30-beta1'] os: ['ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} env: - SDK_TRIPLE: ${{ matrix.sdk_triple }} NDK_VERSION: ${{ matrix.ndk_version }} SWIFT_VERSION: ${{ matrix.swift_version }} steps: @@ -75,14 +74,24 @@ jobs: exit 1 fi + - name: Cache Android NDK + id: cache-ndk + uses: actions/cache@v4 + with: + path: ~/android-ndk-${{ matrix.ndk_version }} + key: android-ndk-${{ runner.os }}-${{ runner.arch }}-${{ matrix.ndk_version }} + - name: Install Android NDK + if: steps.cache-ndk.outputs.cache-hit != 'true' run: | set -euxo pipefail OS="$(uname -s | tr '[A-Z]' '[a-z]')" curl -L -o ndk.zip --retry 3 "https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-${OS}.zip" unzip -q ndk.zip -d "$HOME" rm ndk.zip - echo "ANDROID_NDK_HOME=$HOME/android-ndk-${NDK_VERSION}" >> "$GITHUB_ENV" + + - name: Set ANDROID_NDK_HOME + run: echo "ANDROID_NDK_HOME=$HOME/android-ndk-${NDK_VERSION}" >> "$GITHUB_ENV" - name: Install Android Swift SDK and matching host toolchain # Looks up the Android Swift SDK URL and checksum from the swift.org @@ -182,34 +191,34 @@ jobs: :SwiftKitCore:publishToMavenLocal - name: Build hello-swift-raw-jni APK - run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace + run: ./gradlew :hello-swift-raw-jni:assembleRelease --stacktrace - name: Build hello-swift-raw-jni-callback APK - run: ./gradlew :hello-swift-raw-jni-callback:assembleDebug --stacktrace + run: ./gradlew :hello-swift-raw-jni-callback:assembleRelease --stacktrace - name: Build hello-swift-raw-jni-library - run: ./gradlew :hello-swift-raw-jni-library:assembleDebug --stacktrace + run: ./gradlew :hello-swift-raw-jni-library:assembleRelease --stacktrace - name: Build native-activity APK - run: ./gradlew :native-activity:assembleDebug --stacktrace + run: ./gradlew :native-activity:assembleRelease --stacktrace - name: Build hello-swift-java APK - run: ./gradlew :hello-swift-java-hashing-app:assembleDebug --stacktrace + run: ./gradlew :hello-swift-java-hashing-app:assembleRelease --stacktrace - name: Build swift-java-weather-app APK - run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace + run: ./gradlew :swift-java-weather-app-weather-app:assembleRelease --stacktrace - name: Build hello-cpp-swift cpp-lib working-directory: hello-cpp-swift/cpp-lib run: ./build-android-static.sh - name: Build hello-cpp-swift APK - run: ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace + run: ./gradlew :hello-cpp-swift:app:assembleRelease --stacktrace - name: Summarize APK artifacts if: always() run: | - echo "## APK Artifacts (${{ matrix.os }} / swift:${{ matrix.swift_version }} / ${{ matrix.sdk_triple }})" >> "$GITHUB_STEP_SUMMARY" + echo "## APK Artifacts (os:${{ matrix.os }} / swift:${{ matrix.swift_version }} / ndk:${{ matrix.ndk_version }})" >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" echo "| Project | APK | Size |" >> "$GITHUB_STEP_SUMMARY" echo "|---------|-----|------|" >> "$GITHUB_STEP_SUMMARY" @@ -231,7 +240,7 @@ jobs: if: always() uses: actions/upload-artifact@v7 with: - name: apks-${{ matrix.os }}-${{ matrix.swift_version }}-${{ matrix.sdk_triple }}-${{ matrix.ndk_version }} + name: apks-${{ matrix.os }}-${{ matrix.swift_version }}-${{ matrix.ndk_version }} path: '**/build/outputs/apk/**/*.apk' if-no-files-found: warn From 167291edba1499d0496d6730a6f06728b1c195c2 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 16:33:47 -0400 Subject: [PATCH 26/39] Add release build variants --- .github/workflows/ci.yml | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 047dd89..5cba814 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,11 +6,6 @@ on: schedule: - cron: '0 0 * * *' workflow_dispatch: - inputs: - swift_versions: - description: 'JSON array of Swift versions to test (e.g. ["6.3"], ["6.3", "nightly-main"])' - required: false - default: '["6.3", "nightly-main"]' permissions: contents: read @@ -21,13 +16,13 @@ concurrency: jobs: build-examples: - name: Build ${{ matrix.os }} ${{ matrix.swift_version }} strategy: fail-fast: false matrix: - swift_version: ${{ fromJSON(inputs.swift_versions || '["6.3", "nightly-main"]') }} + swift_version: ["6.3", "nightly-main"] ndk_version: ['r27d', 'r30-beta1'] os: ['ubuntu-latest', 'macos-latest'] + configuration: ['Debug', 'Release'] runs-on: ${{ matrix.os }} env: NDK_VERSION: ${{ matrix.ndk_version }} @@ -191,34 +186,34 @@ jobs: :SwiftKitCore:publishToMavenLocal - name: Build hello-swift-raw-jni APK - run: ./gradlew :hello-swift-raw-jni:assembleRelease --stacktrace + run: ./gradlew :hello-swift-raw-jni:assemble${{ matrix.configuration }} --stacktrace - name: Build hello-swift-raw-jni-callback APK - run: ./gradlew :hello-swift-raw-jni-callback:assembleRelease --stacktrace + run: ./gradlew :hello-swift-raw-jni-callback:assemble${{ matrix.configuration }} --stacktrace - name: Build hello-swift-raw-jni-library - run: ./gradlew :hello-swift-raw-jni-library:assembleRelease --stacktrace + run: ./gradlew :hello-swift-raw-jni-library:assemble${{ matrix.configuration }} --stacktrace - name: Build native-activity APK - run: ./gradlew :native-activity:assembleRelease --stacktrace + run: ./gradlew :native-activity:assemble${{ matrix.configuration }} --stacktrace - name: Build hello-swift-java APK - run: ./gradlew :hello-swift-java-hashing-app:assembleRelease --stacktrace + run: ./gradlew :hello-swift-java-hashing-app:assemble${{ matrix.configuration }} --stacktrace - name: Build swift-java-weather-app APK - run: ./gradlew :swift-java-weather-app-weather-app:assembleRelease --stacktrace + run: ./gradlew :swift-java-weather-app-weather-app:assemble${{ matrix.configuration }} --stacktrace - name: Build hello-cpp-swift cpp-lib working-directory: hello-cpp-swift/cpp-lib run: ./build-android-static.sh - name: Build hello-cpp-swift APK - run: ./gradlew :hello-cpp-swift:app:assembleRelease --stacktrace + run: ./gradlew :hello-cpp-swift:app:assemble${{ matrix.configuration }} --stacktrace - name: Summarize APK artifacts if: always() run: | - echo "## APK Artifacts (os:${{ matrix.os }} / swift:${{ matrix.swift_version }} / ndk:${{ matrix.ndk_version }})" >> "$GITHUB_STEP_SUMMARY" + echo "## APK Artifacts (os:${{ matrix.os }} / swift:${{ matrix.swift_version }} / ndk:${{ matrix.ndk_version }}) / configuration:${{ matrix.configuration }}" >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" echo "| Project | APK | Size |" >> "$GITHUB_STEP_SUMMARY" echo "|---------|-----|------|" >> "$GITHUB_STEP_SUMMARY" From 85f163af411e96a3e0772350d5bd708814e3ff29 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 18:28:51 -0400 Subject: [PATCH 27/39] Add soundness checks --- .github/workflows/ci.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cba814..0b44500 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,14 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + soundness: + name: Soundness + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + with: + api_breakage_check_enabled: false # this repo doesn't vend any API + license_header_check_enabled: false # feature: https://github.com/swiftlang/github-workflows/issues/78 + license_header_check_project_name: "Swift.org" # bug: https://github.com/swiftlang/github-workflows/issues/76 + build-examples: strategy: fail-fast: false @@ -71,7 +79,7 @@ jobs: - name: Cache Android NDK id: cache-ndk - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/android-ndk-${{ matrix.ndk_version }} key: android-ndk-${{ runner.os }}-${{ runner.arch }}-${{ matrix.ndk_version }} From 8fa1aacf16f198ca0ecb81b831aeb556b1ec2b55 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 18:48:50 -0400 Subject: [PATCH 28/39] Update formatting for soundness and disable format checks --- .github/workflows/ci.yml | 5 +- .spi.yml | 7 + Package.swift | 2 + .../Sources/WeatherLibrary/openapi.yaml | 144 +++++++++--------- 4 files changed, 82 insertions(+), 76 deletions(-) create mode 100644 .spi.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b44500..00bcb27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,9 +19,7 @@ jobs: name: Soundness uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main with: - api_breakage_check_enabled: false # this repo doesn't vend any API - license_header_check_enabled: false # feature: https://github.com/swiftlang/github-workflows/issues/78 - license_header_check_project_name: "Swift.org" # bug: https://github.com/swiftlang/github-workflows/issues/76 + format_check_enabled: false # aspire to true build-examples: strategy: @@ -246,4 +244,3 @@ jobs: name: apks-${{ matrix.os }}-${{ matrix.swift_version }}-${{ matrix.ndk_version }} path: '**/build/outputs/apk/**/*.apk' if-no-files-found: warn - diff --git a/.spi.yml b/.spi.yml new file mode 100644 index 0000000..402bf11 --- /dev/null +++ b/.spi.yml @@ -0,0 +1,7 @@ +version: 1 +external_links: + documentation: "https://docs.swift.org/android/documentation/android" +builder: + configs: + - documentation_targets: [SwiftAndroid] + diff --git a/Package.swift b/Package.swift index 5b071ee..77c4246 100644 --- a/Package.swift +++ b/Package.swift @@ -2,6 +2,8 @@ import PackageDescription +// Note that this product exists purely to build documentation: +// swift package generate-documentation --target SwiftAndroid --transform-for-static-hosting --output-path dos let package = Package( name: "swift-android-examples", products: [ diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml index 2b4034f..125630a 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml @@ -17,55 +17,55 @@ paths: - url: https://api.open-meteo.com get: tags: - - Weather Forecast APIs + - Weather Forecast APIs summary: 7 day weather forecast for coordinates description: 7 day weather variables in hourly and daily resolution for given WGS84 latitude and longitude coordinates. Available worldwide. parameters: - - name: hourly - in: query - explode: false - schema: - type: array - items: - type: string - enum: - - temperature_2m - - relative_humidity_2m - - dew_point_2m - - apparent_temperature - - pressure_msl - - cloud_cover - - cloud_cover_low - - cloud_cover_mid - - cloud_cover_high - - wind_speed_10m - - wind_speed_80m - - wind_speed_120m - - wind_speed_180m - - wind_direction_10m - - wind_direction_80m - - wind_direction_120m - - wind_direction_180m - - wind_gusts_10m - - shortwave_radiation - - direct_radiation - - direct_normal_irradiance - - diffuse_radiation - - vapour_pressure_deficit - - evapotranspiration - - precipitation - - weather_code - - snow_height - - freezing_level_height - - soil_temperature_0cm - - soil_temperature_6cm - - soil_temperature_18cm - - soil_temperature_54cm - - soil_moisture_0_1cm - - soil_moisture_1_3cm - - soil_moisture_3_9cm - - soil_moisture_9_27cm - - soil_moisture_27_81cm + - name: hourly + in: query + explode: false + schema: + type: array + items: + type: string + enum: + - temperature_2m + - relative_humidity_2m + - dew_point_2m + - apparent_temperature + - pressure_msl + - cloud_cover + - cloud_cover_low + - cloud_cover_mid + - cloud_cover_high + - wind_speed_10m + - wind_speed_80m + - wind_speed_120m + - wind_speed_180m + - wind_direction_10m + - wind_direction_80m + - wind_direction_120m + - wind_direction_180m + - wind_gusts_10m + - shortwave_radiation + - direct_radiation + - direct_normal_irradiance + - diffuse_radiation + - vapour_pressure_deficit + - evapotranspiration + - precipitation + - weather_code + - snow_height + - freezing_level_height + - soil_temperature_0cm + - soil_temperature_6cm + - soil_temperature_18cm + - soil_temperature_54cm + - soil_moisture_0_1cm + - soil_moisture_1_3cm + - soil_moisture_3_9cm + - soil_moisture_9_27cm + - soil_moisture_27_81cm - name: daily in: query schema: @@ -73,22 +73,22 @@ paths: items: type: string enum: - - temperature_2m_max - - temperature_2m_min - - apparent_temperature_max - - apparent_temperature_min - - precipitation_sum - - precipitation_hours - - weather_code - - sunrise - - sunset - - wind_speed_10m_max - - wind_gusts_10m_max - - wind_direction_10m_dominant - - shortwave_radiation_sum - - uv_index_max - - uv_index_clear_sky_max - - et0_fao_evapotranspiration + - temperature_2m_max + - temperature_2m_min + - apparent_temperature_max + - apparent_temperature_min + - precipitation_sum + - precipitation_hours + - weather_code + - sunrise + - sunset + - wind_speed_10m_max + - wind_gusts_10m_max + - wind_direction_10m_dominant + - shortwave_radiation_sum + - uv_index_max + - uv_index_clear_sky_max + - et0_fao_evapotranspiration - name: latitude in: query required: true @@ -113,18 +113,18 @@ paths: type: string default: celsius enum: - - celsius - - fahrenheit + - celsius + - fahrenheit - name: wind_speed_unit in: query schema: type: string default: kmh enum: - - kmh - - ms - - mph - - kn + - kmh + - ms + - mph + - kn - name: timeformat in: query description: If format `unixtime` is selected, all time values are returned in UNIX epoch time in seconds. Please not that all time is then in GMT+0! For daily values with unix timestamp, please apply `utc_offset_seconds` again to get the correct date. @@ -132,8 +132,8 @@ paths: type: string default: iso8601 enum: - - iso8601 - - unixtime + - iso8601 + - unixtime - name: timezone in: query description: If `timezone` is set, all timestamps are returned as local-time and data is returned starting at 0:00 local-time. Any time zone name from the [time zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is supported. @@ -145,8 +145,8 @@ paths: schema: type: integer enum: - - 1 - - 2 + - 1 + - 2 responses: "200": description: OK From 0ae7fcb5cb574391594a7be94053074652de34ff Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 18:53:24 -0400 Subject: [PATCH 29/39] Update soundness checks --- .github/workflows/ci.yml | 3 +- .spi.yml | 1 - .../Sources/WeatherLibrary/openapi.yaml | 158 +++++++++--------- 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00bcb27..e431994 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,8 @@ jobs: name: Soundness uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main with: - format_check_enabled: false # aspire to true + license_header_check_project_name: "Swift.org" + format_check_enabled: false # aspire to true build-examples: strategy: diff --git a/.spi.yml b/.spi.yml index 402bf11..589a5d4 100644 --- a/.spi.yml +++ b/.spi.yml @@ -4,4 +4,3 @@ external_links: builder: configs: - documentation_targets: [SwiftAndroid] - diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml index 125630a..b1a0595 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/openapi.yaml @@ -66,87 +66,87 @@ paths: - soil_moisture_3_9cm - soil_moisture_9_27cm - soil_moisture_27_81cm - - name: daily - in: query - schema: - type: array - items: + - name: daily + in: query + schema: + type: array + items: + type: string + enum: + - temperature_2m_max + - temperature_2m_min + - apparent_temperature_max + - apparent_temperature_min + - precipitation_sum + - precipitation_hours + - weather_code + - sunrise + - sunset + - wind_speed_10m_max + - wind_gusts_10m_max + - wind_direction_10m_dominant + - shortwave_radiation_sum + - uv_index_max + - uv_index_clear_sky_max + - et0_fao_evapotranspiration + - name: latitude + in: query + required: true + description: "WGS84 coordinate" + schema: + type: number + format: double + - name: longitude + in: query + required: true + description: "WGS84 coordinate" + schema: + type: number + format: double + - name: current_weather + in: query + schema: + type: boolean + - name: temperature_unit + in: query + schema: type: string + default: celsius enum: - - temperature_2m_max - - temperature_2m_min - - apparent_temperature_max - - apparent_temperature_min - - precipitation_sum - - precipitation_hours - - weather_code - - sunrise - - sunset - - wind_speed_10m_max - - wind_gusts_10m_max - - wind_direction_10m_dominant - - shortwave_radiation_sum - - uv_index_max - - uv_index_clear_sky_max - - et0_fao_evapotranspiration - - name: latitude - in: query - required: true - description: "WGS84 coordinate" - schema: - type: number - format: double - - name: longitude - in: query - required: true - description: "WGS84 coordinate" - schema: - type: number - format: double - - name: current_weather - in: query - schema: - type: boolean - - name: temperature_unit - in: query - schema: - type: string - default: celsius - enum: - - celsius - - fahrenheit - - name: wind_speed_unit - in: query - schema: - type: string - default: kmh - enum: - - kmh - - ms - - mph - - kn - - name: timeformat - in: query - description: If format `unixtime` is selected, all time values are returned in UNIX epoch time in seconds. Please not that all time is then in GMT+0! For daily values with unix timestamp, please apply `utc_offset_seconds` again to get the correct date. - schema: - type: string - default: iso8601 - enum: - - iso8601 - - unixtime - - name: timezone - in: query - description: If `timezone` is set, all timestamps are returned as local-time and data is returned starting at 0:00 local-time. Any time zone name from the [time zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is supported. - schema: - type: string - - name: past_days - in: query - description: If `past_days` is set, yesterdays or the day before yesterdays data are also returned. - schema: - type: integer - enum: - - 1 - - 2 + - celsius + - fahrenheit + - name: wind_speed_unit + in: query + schema: + type: string + default: kmh + enum: + - kmh + - ms + - mph + - kn + - name: timeformat + in: query + description: If format `unixtime` is selected, all time values are returned in UNIX epoch time in seconds. Please not that all time is then in GMT+0! For daily values with unix timestamp, please apply `utc_offset_seconds` again to get the correct date. + schema: + type: string + default: iso8601 + enum: + - iso8601 + - unixtime + - name: timezone + in: query + description: If `timezone` is set, all timestamps are returned as local-time and data is returned starting at 0:00 local-time. Any time zone name from the [time zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is supported. + schema: + type: string + - name: past_days + in: query + description: If `past_days` is set, yesterdays or the day before yesterdays data are also returned. + schema: + type: integer + enum: + - 1 + - 2 responses: "200": description: OK From 262aef8fa49b907e2de88e8792ac0b8e02bf6f2b Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 19:09:47 -0400 Subject: [PATCH 30/39] Update license headers for soundness license checks --- .licenseignore | 54 +++++++++++++++++++ Sources/SwiftAndroid/Empty.swift | 14 +++++ build.gradle.kts | 16 +++++- hello-cpp-swift/app/build.gradle.kts | 14 +++++ .../com/example/hellocppswift/MainActivity.kt | 13 +++++ .../Sources/HelloCppSwift/Calculator.swift | 13 +++++ hello-swift-java/hashing-app/build.gradle.kts | 14 +++++ hello-swift-raw-jni-callback/build.gradle.kts | 16 +++++- hello-swift-raw-jni-library/build.gradle.kts | 16 +++++- hello-swift-raw-jni/build.gradle.kts | 16 +++++- native-activity/build.gradle.kts | 16 +++++- settings.gradle.kts | 14 +++++ swift-android.gradle.kts | 14 +++++ .../weather-app/build.gradle.kts | 14 +++++ 14 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 .licenseignore diff --git a/.licenseignore b/.licenseignore new file mode 100644 index 0000000..212c684 --- /dev/null +++ b/.licenseignore @@ -0,0 +1,54 @@ +.gitignore +**/.gitignore +.licenseignore +.unacceptablelanguageignore +.swiftformatignore +.gitattributes +.mailfilter +.mailmap +.spi.yml +.swift-format +.editorconfig +.github/* +.idea/icon.svg +gradle/libs.versions.toml +gradle-wrapper.properties +gradle.properties +gradlew +gradlew.bat +proguard-rules.pro +*.xml +*.webp +*.png +*.config +*.jar +*.md +*.txt +*.yml +*.yaml +*.json +Package.swift +**/Package.swift +Package@-*.swift +**/Package@-*.swift +Package.resolved +**/Package.resolved +Makefile +*.modulemap +**/*.modulemap +**/*.docc/* +*.xcprivacy +**/*.xcprivacy +*.symlink +**/*.symlink +Dockerfile +**/Dockerfile +Snippets/* +dev/git.commit.template +*.crt +**/*.crt +*.pem +**/*.pem +*.der +**/*.der +native-app-glue/Sources/AndroidNativeAppGlue/android_native_app_glue.c diff --git a/Sources/SwiftAndroid/Empty.swift b/Sources/SwiftAndroid/Empty.swift index 114df8d..e64de9d 100644 --- a/Sources/SwiftAndroid/Empty.swift +++ b/Sources/SwiftAndroid/Empty.swift @@ -1 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + // This file is included so SwiftPM considers the target to be a Swift target. diff --git a/build.gradle.kts b/build.gradle.kts index ecf7a23..24598f0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.android.library) apply false -} \ No newline at end of file +} diff --git a/hello-cpp-swift/app/build.gradle.kts b/hello-cpp-swift/app/build.gradle.kts index ec92bcb..fb58dc6 100644 --- a/hello-cpp-swift/app/build.gradle.kts +++ b/hello-cpp-swift/app/build.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) diff --git a/hello-cpp-swift/app/src/main/java/com/example/hellocppswift/MainActivity.kt b/hello-cpp-swift/app/src/main/java/com/example/hellocppswift/MainActivity.kt index 63d5356..a064d95 100644 --- a/hello-cpp-swift/app/src/main/java/com/example/hellocppswift/MainActivity.kt +++ b/hello-cpp-swift/app/src/main/java/com/example/hellocppswift/MainActivity.kt @@ -1,3 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// package com.example.hellocppswift import android.os.Bundle diff --git a/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift b/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift index 494ad99..45b0ed6 100644 --- a/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift +++ b/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift @@ -1,3 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// #if canImport(FoundationEssentials) import FoundationEssentials #else diff --git a/hello-swift-java/hashing-app/build.gradle.kts b/hello-swift-java/hashing-app/build.gradle.kts index e087f09..d45d66f 100644 --- a/hello-swift-java/hashing-app/build.gradle.kts +++ b/hello-swift-java/hashing-app/build.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) diff --git a/hello-swift-raw-jni-callback/build.gradle.kts b/hello-swift-raw-jni-callback/build.gradle.kts index 4ff1f49..5b189a7 100644 --- a/hello-swift-raw-jni-callback/build.gradle.kts +++ b/hello-swift-raw-jni-callback/build.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) @@ -45,4 +59,4 @@ dependencies { implementation(libs.androidx.appcompat) implementation(libs.material) implementation(libs.androidx.constraintlayout) -} \ No newline at end of file +} diff --git a/hello-swift-raw-jni-library/build.gradle.kts b/hello-swift-raw-jni-library/build.gradle.kts index d81a9f1..ef33d31 100644 --- a/hello-swift-raw-jni-library/build.gradle.kts +++ b/hello-swift-raw-jni-library/build.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) @@ -42,4 +56,4 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) -} \ No newline at end of file +} diff --git a/hello-swift-raw-jni/build.gradle.kts b/hello-swift-raw-jni/build.gradle.kts index 2eb9582..96c6582 100644 --- a/hello-swift-raw-jni/build.gradle.kts +++ b/hello-swift-raw-jni/build.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) @@ -47,4 +61,4 @@ dependencies { implementation(libs.androidx.appcompat) implementation(libs.material) implementation(libs.androidx.constraintlayout) -} \ No newline at end of file +} diff --git a/native-activity/build.gradle.kts b/native-activity/build.gradle.kts index a1c439a..5bb8cde 100644 --- a/native-activity/build.gradle.kts +++ b/native-activity/build.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) @@ -26,4 +40,4 @@ android { isJniDebuggable = false } } -} \ No newline at end of file +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 74ae8b6..a4f557b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + pluginManagement { repositories { mavenLocal() diff --git a/swift-android.gradle.kts b/swift-android.gradle.kts index 9b22916..f67b271 100644 --- a/swift-android.gradle.kts +++ b/swift-android.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + // File: swift-android.gradle.kts // Swift build script for Android projects using swiftly diff --git a/swift-java-weather-app/weather-app/build.gradle.kts b/swift-java-weather-app/weather-app/build.gradle.kts index 61d00b0..8c7d976 100644 --- a/swift-java-weather-app/weather-app/build.gradle.kts +++ b/swift-java-weather-app/weather-app/build.gradle.kts @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) From c0471bed6099160260f150e0d930e4476198605a Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 19:24:11 -0400 Subject: [PATCH 31/39] Update license headers for soundness license checks --- hello-cpp-swift/cpp-lib/build-android-static.sh | 13 +++++++++++++ hello-cpp-swift/cpp-lib/include/calculator.h | 13 +++++++++++++ hello-cpp-swift/cpp-lib/src/calculator.cpp | 14 ++++++++++++++ hello-cpp-swift/swift-lib/build.gradle | 14 ++++++++++++++ .../example/hashingapp/ExampleInstrumentedTest.kt | 12 +++++++----- .../java/com/example/hashingapp/MainActivity.kt | 12 +++++++----- .../java/com/example/hashingapp/ui/theme/Color.kt | 12 +++++++----- .../java/com/example/hashingapp/ui/theme/Theme.kt | 12 +++++++----- .../java/com/example/hashingapp/ui/theme/Type.kt | 12 +++++++----- .../java/com/example/hashingapp/ExampleUnitTest.kt | 12 +++++++----- .../Sources/SwiftHashing/SwiftHashing.swift | 10 ++++++---- .../SwiftHashingTests/SwiftHashingTests.swift | 10 ++++++---- hello-swift-java/hashing-lib/build.gradle | 14 ++++++++++++++ .../java/org/example/helloswift/MainActivity.kt | 10 ++++++---- .../hello-swift-callback.swift | 10 ++++++---- .../org/example/swiftlibrary/SwiftLibraryTest.kt | 10 ++++++---- .../java/org/example/swiftlibrary/SwiftLibrary.kt | 10 ++++++---- .../main/swift/Sources/helloswift/helloswift.swift | 10 ++++++---- .../java/org/example/helloswift/MainActivity.kt | 10 ++++++---- .../main/swift/Sources/helloswift/helloswift.swift | 10 ++++++---- .../Sources/native-activity/native-activity.swift | 10 ++++++---- .../example/weatherapp/ExampleInstrumentedTest.kt | 12 +++++++----- .../java/com/example/weatherapp/MainActivity.kt | 12 +++++++----- .../example/weatherapp/services/LocationService.kt | 10 ++++++---- .../java/com/example/weatherapp/ui/theme/Color.kt | 12 +++++++----- .../java/com/example/weatherapp/ui/theme/Theme.kt | 12 +++++++----- .../java/com/example/weatherapp/ui/theme/Type.kt | 12 +++++++----- .../weatherapp/viewmodel/WeatherViewModel.kt | 10 ++++++---- .../java/com/example/weatherapp/ExampleUnitTest.kt | 12 +++++++----- .../Sources/WeatherLibrary/LocationFetcher.swift | 10 ++++++---- .../Sources/WeatherLibrary/WeatherClient.swift | 10 ++++++---- .../Sources/WeatherLibrary/WeatherData.swift | 10 ++++++---- .../Sources/WeatherLibrary/WeatherError.swift | 10 ++++++---- swift-java-weather-app/weather-lib/build.gradle | 14 ++++++++++++++ 34 files changed, 262 insertions(+), 124 deletions(-) diff --git a/hello-cpp-swift/cpp-lib/build-android-static.sh b/hello-cpp-swift/cpp-lib/build-android-static.sh index cb75c4a..499e23a 100755 --- a/hello-cpp-swift/cpp-lib/build-android-static.sh +++ b/hello-cpp-swift/cpp-lib/build-android-static.sh @@ -1,4 +1,17 @@ #!/bin/bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift.org open source project +## +## Copyright (c) 2026 Apple Inc. and the Swift.org project authors +## Licensed under Apache License v2.0 +## +## See LICENSE.txt for license information +## See CONTRIBUTORS.txt for the list of Swift.org project authors +## +## SPDX-License-Identifier: Apache-2.0 +## +##===----------------------------------------------------------------------===## set -e diff --git a/hello-cpp-swift/cpp-lib/include/calculator.h b/hello-cpp-swift/cpp-lib/include/calculator.h index c84b9ae..4464cb6 100644 --- a/hello-cpp-swift/cpp-lib/include/calculator.h +++ b/hello-cpp-swift/cpp-lib/include/calculator.h @@ -1,3 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// #ifndef CALCULATOR_H #define CALCULATOR_H diff --git a/hello-cpp-swift/cpp-lib/src/calculator.cpp b/hello-cpp-swift/cpp-lib/src/calculator.cpp index ec000c3..bf1665c 100644 --- a/hello-cpp-swift/cpp-lib/src/calculator.cpp +++ b/hello-cpp-swift/cpp-lib/src/calculator.cpp @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + #include "calculator.h" int add(int a, int b) { diff --git a/hello-cpp-swift/swift-lib/build.gradle b/hello-cpp-swift/swift-lib/build.gradle index 1662e39..2d75bb4 100644 --- a/hello-cpp-swift/swift-lib/build.gradle +++ b/hello-cpp-swift/swift-lib/build.gradle @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + import java.nio.file.* plugins { diff --git a/hello-swift-java/hashing-app/src/androidTest/java/com/example/hashingapp/ExampleInstrumentedTest.kt b/hello-swift-java/hashing-app/src/androidTest/java/com/example/hashingapp/ExampleInstrumentedTest.kt index 1bcc13c..4ab5ebb 100644 --- a/hello-swift-java/hashing-app/src/androidTest/java/com/example/hashingapp/ExampleInstrumentedTest.kt +++ b/hello-swift-java/hashing-app/src/androidTest/java/com/example/hashingapp/ExampleInstrumentedTest.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -33,4 +35,4 @@ class ExampleInstrumentedTest { val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("com.example.hashingapp", appContext.packageName) } -} \ No newline at end of file +} diff --git a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/MainActivity.kt b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/MainActivity.kt index 24cd5c8..a9f343a 100644 --- a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/MainActivity.kt +++ b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/MainActivity.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -91,4 +93,4 @@ fun HashScreen() { ) } } -} \ No newline at end of file +} diff --git a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Color.kt b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Color.kt index f5705ba..2128565 100644 --- a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Color.kt +++ b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Color.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -20,4 +22,4 @@ val Pink80 = Color(0xFFEFB8C8) val Purple40 = Color(0xFF6650a4) val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) \ No newline at end of file +val Pink40 = Color(0xFF7D5260) diff --git a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Theme.kt b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Theme.kt index 8c20865..b87b288 100644 --- a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Theme.kt +++ b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Theme.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -67,4 +69,4 @@ fun HashingAppTheme( typography = Typography, content = content ) -} \ No newline at end of file +} diff --git a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Type.kt b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Type.kt index 336c677..8634ed4 100644 --- a/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Type.kt +++ b/hello-swift-java/hashing-app/src/main/java/com/example/hashingapp/ui/theme/Type.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -43,4 +45,4 @@ val Typography = Typography( letterSpacing = 0.5.sp ) */ -) \ No newline at end of file +) diff --git a/hello-swift-java/hashing-app/src/test/java/com/example/hashingapp/ExampleUnitTest.kt b/hello-swift-java/hashing-app/src/test/java/com/example/hashingapp/ExampleUnitTest.kt index 1c94d5d..cf1079c 100644 --- a/hello-swift-java/hashing-app/src/test/java/com/example/hashingapp/ExampleUnitTest.kt +++ b/hello-swift-java/hashing-app/src/test/java/com/example/hashingapp/ExampleUnitTest.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -26,4 +28,4 @@ class ExampleUnitTest { fun addition_isCorrect() { assertEquals(4, 2 + 2) } -} \ No newline at end of file +} diff --git a/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift b/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift index f6565b1..3e6aa40 100644 --- a/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift +++ b/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift b/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift index 6a4b429..55b1f95 100644 --- a/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift +++ b/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-java/hashing-lib/build.gradle b/hello-swift-java/hashing-lib/build.gradle index 58416f0..29f75bc 100644 --- a/hello-swift-java/hashing-lib/build.gradle +++ b/hello-swift-java/hashing-lib/build.gradle @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + import java.nio.file.* import org.gradle.internal.os.OperatingSystem import groovy.json.JsonSlurper diff --git a/hello-swift-raw-jni-callback/src/main/java/org/example/helloswift/MainActivity.kt b/hello-swift-raw-jni-callback/src/main/java/org/example/helloswift/MainActivity.kt index 69a49a1..bf9471e 100644 --- a/hello-swift-raw-jni-callback/src/main/java/org/example/helloswift/MainActivity.kt +++ b/hello-swift-raw-jni-callback/src/main/java/org/example/helloswift/MainActivity.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift b/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift index 2e76e4f..cfa9fa9 100644 --- a/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift +++ b/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-raw-jni-library/src/androidTest/java/org/example/swiftlibrary/SwiftLibraryTest.kt b/hello-swift-raw-jni-library/src/androidTest/java/org/example/swiftlibrary/SwiftLibraryTest.kt index a70905f..a437a8c 100644 --- a/hello-swift-raw-jni-library/src/androidTest/java/org/example/swiftlibrary/SwiftLibraryTest.kt +++ b/hello-swift-raw-jni-library/src/androidTest/java/org/example/swiftlibrary/SwiftLibraryTest.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-raw-jni-library/src/main/java/org/example/swiftlibrary/SwiftLibrary.kt b/hello-swift-raw-jni-library/src/main/java/org/example/swiftlibrary/SwiftLibrary.kt index 4298b84..5db93e6 100644 --- a/hello-swift-raw-jni-library/src/main/java/org/example/swiftlibrary/SwiftLibrary.kt +++ b/hello-swift-raw-jni-library/src/main/java/org/example/swiftlibrary/SwiftLibrary.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift b/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift index d943e8e..422b178 100644 --- a/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift +++ b/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-raw-jni/src/main/java/org/example/helloswift/MainActivity.kt b/hello-swift-raw-jni/src/main/java/org/example/helloswift/MainActivity.kt index c864dbf..4b5d374 100644 --- a/hello-swift-raw-jni/src/main/java/org/example/helloswift/MainActivity.kt +++ b/hello-swift-raw-jni/src/main/java/org/example/helloswift/MainActivity.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift b/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift index b7cd274..ca1d355 100644 --- a/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift +++ b/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/native-activity/src/main/swift/Sources/native-activity/native-activity.swift b/native-activity/src/main/swift/Sources/native-activity/native-activity.swift index 1dc27d0..e01b696 100644 --- a/native-activity/src/main/swift/Sources/native-activity/native-activity.swift +++ b/native-activity/src/main/swift/Sources/native-activity/native-activity.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/swift-java-weather-app/weather-app/src/androidTest/java/com/example/weatherapp/ExampleInstrumentedTest.kt b/swift-java-weather-app/weather-app/src/androidTest/java/com/example/weatherapp/ExampleInstrumentedTest.kt index 94455b3..04bfc50 100644 --- a/swift-java-weather-app/weather-app/src/androidTest/java/com/example/weatherapp/ExampleInstrumentedTest.kt +++ b/swift-java-weather-app/weather-app/src/androidTest/java/com/example/weatherapp/ExampleInstrumentedTest.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -33,4 +35,4 @@ class ExampleInstrumentedTest { val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("com.example.weatherapp", appContext.packageName) } -} \ No newline at end of file +} diff --git a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/MainActivity.kt b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/MainActivity.kt index c773b4d..e7a520e 100644 --- a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/MainActivity.kt +++ b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/MainActivity.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -90,4 +92,4 @@ fun WeatherScreen(viewModel: WeatherViewModel, onFetchWeatherClick: () -> Unit) Text("Error: $it", color = MaterialTheme.colorScheme.error) } } -} \ No newline at end of file +} diff --git a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/services/LocationService.kt b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/services/LocationService.kt index 56ee7ca..b453ad4 100644 --- a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/services/LocationService.kt +++ b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/services/LocationService.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Color.kt b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Color.kt index f9c0931..d161657 100644 --- a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Color.kt +++ b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Color.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -20,4 +22,4 @@ val Pink80 = Color(0xFFEFB8C8) val Purple40 = Color(0xFF6650a4) val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) \ No newline at end of file +val Pink40 = Color(0xFF7D5260) diff --git a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Theme.kt b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Theme.kt index 61ed15c..1c9a2ba 100644 --- a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Theme.kt +++ b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Theme.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -67,4 +69,4 @@ fun WeatherAppTheme( typography = Typography, content = content ) -} \ No newline at end of file +} diff --git a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Type.kt b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Type.kt index 318c6f2..1893c2e 100644 --- a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Type.kt +++ b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/ui/theme/Type.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -43,4 +45,4 @@ val Typography = Typography( letterSpacing = 0.5.sp ) */ -) \ No newline at end of file +) diff --git a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/viewmodel/WeatherViewModel.kt b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/viewmodel/WeatherViewModel.kt index ec05e31..64d2f1e 100644 --- a/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/viewmodel/WeatherViewModel.kt +++ b/swift-java-weather-app/weather-app/src/main/java/com/example/weatherapp/viewmodel/WeatherViewModel.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/swift-java-weather-app/weather-app/src/test/java/com/example/weatherapp/ExampleUnitTest.kt b/swift-java-weather-app/weather-app/src/test/java/com/example/weatherapp/ExampleUnitTest.kt index 70b33de..1eec944 100644 --- a/swift-java-weather-app/weather-app/src/test/java/com/example/weatherapp/ExampleUnitTest.kt +++ b/swift-java-weather-app/weather-app/src/test/java/com/example/weatherapp/ExampleUnitTest.kt @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @@ -26,4 +28,4 @@ class ExampleUnitTest { fun addition_isCorrect() { assertEquals(4, 2 + 2) } -} \ No newline at end of file +} diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift index f7fcbcd..4b7881c 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift index a2cca67..e6bcd79 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift index aae7946..c5086bd 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift index 2659c47..36995a2 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/swift-java-weather-app/weather-lib/build.gradle b/swift-java-weather-app/weather-lib/build.gradle index ce3a838..3a12500 100644 --- a/swift-java-weather-app/weather-lib/build.gradle +++ b/swift-java-weather-app/weather-lib/build.gradle @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + import java.nio.file.* import org.gradle.internal.os.OperatingSystem import groovy.json.JsonSlurper From 67966149da341712cd8103cd51ba5578f5c915d4 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 19:26:53 -0400 Subject: [PATCH 32/39] Update license headers for soundness license checks --- .licenseignore | 7 ++++--- .../Sources/AndroidOpenGL/include/umbrella.h | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.licenseignore b/.licenseignore index 212c684..8eb015e 100644 --- a/.licenseignore +++ b/.licenseignore @@ -12,11 +12,11 @@ .github/* .idea/icon.svg gradle/libs.versions.toml -gradle-wrapper.properties -gradle.properties +**/gradle-wrapper.properties +**/gradle.properties gradlew gradlew.bat -proguard-rules.pro +**/proguard-rules.pro *.xml *.webp *.png @@ -52,3 +52,4 @@ dev/git.commit.template *.der **/*.der native-app-glue/Sources/AndroidNativeAppGlue/android_native_app_glue.c +native-app-glue/Sources/AndroidNativeAppGlue/include/android_native_app_glue.h diff --git a/native-app-glue/Sources/AndroidOpenGL/include/umbrella.h b/native-app-glue/Sources/AndroidOpenGL/include/umbrella.h index cff1295..5bc8c05 100644 --- a/native-app-glue/Sources/AndroidOpenGL/include/umbrella.h +++ b/native-app-glue/Sources/AndroidOpenGL/include/umbrella.h @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + #include #include -#include \ No newline at end of file +#include From 0b2a09c8fa88e63034031a27d110ea688928fdad Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Wed, 6 May 2026 19:28:40 -0400 Subject: [PATCH 33/39] Update license headers for soundness license checks --- .licenseignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.licenseignore b/.licenseignore index 8eb015e..fdc5728 100644 --- a/.licenseignore +++ b/.licenseignore @@ -14,6 +14,7 @@ gradle/libs.versions.toml **/gradle-wrapper.properties **/gradle.properties +gradle.properties gradlew gradlew.bat **/proguard-rules.pro From 98a34bf2532a3aaeda05da93235cbbdd57306d3d Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 7 May 2026 10:15:59 -0400 Subject: [PATCH 34/39] Enable format_check_enabled --- .github/workflows/ci.yml | 1 - .swift-format | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .swift-format diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e431994..061841c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,6 @@ jobs: uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main with: license_header_check_project_name: "Swift.org" - format_check_enabled: false # aspire to true build-examples: strategy: diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..fafb52b --- /dev/null +++ b/.swift-format @@ -0,0 +1,5 @@ +{ + "rules": { + "AlwaysUseLowerCamelCase": false + } +} From ededcfbe1cdcb1d201de74fe9ca71594baeaacdf Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 7 May 2026 10:22:48 -0400 Subject: [PATCH 35/39] Update swift code formatting to satisfy swift-format --- hello-cpp-swift/swift-lib/Package.swift | 4 +- .../Sources/HelloCppSwift/Calculator.swift | 8 +- hello-swift-java/hashing-lib/Package.swift | 4 +- .../Sources/SwiftHashing/SwiftHashing.swift | 6 +- .../SwiftHashingTests/SwiftHashingTests.swift | 4 +- .../src/main/swift/Package.swift | 16 +- .../hello-swift-callback.swift | 72 +-- .../src/main/swift/Package.swift | 15 +- .../swift/Sources/helloswift/helloswift.swift | 12 +- .../src/main/swift/Package.swift | 14 +- .../swift/Sources/helloswift/helloswift.swift | 12 +- native-activity/src/main/swift/Package.swift | 44 +- .../native-activity/native-activity.swift | 421 +++++++++--------- native-app-glue/Package.swift | 20 +- .../weather-lib/Package.swift | 32 +- .../WeatherLibrary/LocationFetcher.swift | 14 +- .../WeatherLibrary/WeatherClient.swift | 85 ++-- .../Sources/WeatherLibrary/WeatherData.swift | 6 +- .../Sources/WeatherLibrary/WeatherError.swift | 18 +- 19 files changed, 413 insertions(+), 394 deletions(-) diff --git a/hello-cpp-swift/swift-lib/Package.swift b/hello-cpp-swift/swift-lib/Package.swift index b58d4cf..681b9aa 100644 --- a/hello-cpp-swift/swift-lib/Package.swift +++ b/hello-cpp-swift/swift-lib/Package.swift @@ -13,7 +13,7 @@ let package = Package( targets: ["HelloCppSwift"]) ], dependencies: [ - .package(url: "https://github.com/swiftlang/swift-java", from: "0.1.2"), + .package(url: "https://github.com/swiftlang/swift-java", from: "0.1.2") ], targets: [ .binaryTarget( @@ -27,7 +27,7 @@ let package = Package( .product(name: "SwiftJava", package: "swift-java"), ], swiftSettings: [ - .swiftLanguageMode(.v5), + .swiftLanguageMode(.v5) ], plugins: [ .plugin(name: "JExtractSwiftPlugin", package: "swift-java") diff --git a/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift b/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift index 45b0ed6..fb8b7a5 100644 --- a/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift +++ b/hello-cpp-swift/swift-lib/Sources/HelloCppSwift/Calculator.swift @@ -12,16 +12,16 @@ // //===----------------------------------------------------------------------===// #if canImport(FoundationEssentials) -import FoundationEssentials + import FoundationEssentials #else -import Foundation + import Foundation #endif import HelloWorldCpp public func addNumbers(_ a: Int32, _ b: Int32) -> Int32 { - return add(a, b) + return add(a, b) } public func multiplyNumbers(_ a: Int32, _ b: Int32) -> Int32 { - return multiply(a, b) + return multiply(a, b) } diff --git a/hello-swift-java/hashing-lib/Package.swift b/hello-swift-java/hashing-lib/Package.swift index 9719605..d2c36ba 100644 --- a/hello-swift-java/hashing-lib/Package.swift +++ b/hello-swift-java/hashing-lib/Package.swift @@ -23,10 +23,10 @@ let package = Package( name: "SwiftHashing", dependencies: [ .product(name: "Crypto", package: "swift-crypto"), - .product(name: "SwiftJava", package: "swift-java") + .product(name: "SwiftJava", package: "swift-java"), ], swiftSettings: [ - .swiftLanguageMode(.v5), + .swiftLanguageMode(.v5) ], plugins: [ .plugin(name: "JExtractSwiftPlugin", package: "swift-java") diff --git a/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift b/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift index 3e6aa40..f38ae2e 100644 --- a/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift +++ b/hello-swift-java/hashing-lib/Sources/SwiftHashing/SwiftHashing.swift @@ -14,11 +14,11 @@ import Crypto #if canImport(FoundationEssentials) -import FoundationEssentials + import FoundationEssentials #else -import Foundation + import Foundation #endif public func hash(_ input: String) -> String { - SHA256.hash(data: Data(input.utf8)).description + SHA256.hash(data: Data(input.utf8)).description } diff --git a/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift b/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift index 55b1f95..908cc06 100644 --- a/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift +++ b/hello-swift-java/hashing-lib/Tests/SwiftHashingTests/SwiftHashingTests.swift @@ -16,5 +16,7 @@ import Testing @testable import SwiftHashing @Test func hashing() throws { - #expect(hash("Hello from Swift!") == "SHA256 digest: a642e7aa389325056cdf5e54a2b6e0a0214b4810fe87e1370063d9e17f8d6ed6") + #expect( + hash("Hello from Swift!") + == "SHA256 digest: a642e7aa389325056cdf5e54a2b6e0a0214b4810fe87e1370063d9e17f8d6ed6") } diff --git a/hello-swift-raw-jni-callback/src/main/swift/Package.swift b/hello-swift-raw-jni-callback/src/main/swift/Package.swift index 84c2b44..806417b 100644 --- a/hello-swift-raw-jni-callback/src/main/swift/Package.swift +++ b/hello-swift-raw-jni-callback/src/main/swift/Package.swift @@ -4,11 +4,13 @@ import PackageDescription let package = Package( - name: "hello-swift-raw-jni-callback", - products: [ - .library(name: "hello-swift-raw-jni-callback", type: .dynamic, targets: ["hello-swift-raw-jni-callback"]), - ], - targets: [ - .target(name: "hello-swift-raw-jni-callback") - ] + name: "hello-swift-raw-jni-callback", + products: [ + .library( + name: "hello-swift-raw-jni-callback", type: .dynamic, + targets: ["hello-swift-raw-jni-callback"]) + ], + targets: [ + .target(name: "hello-swift-raw-jni-callback") + ] ) diff --git a/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift b/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift index cfa9fa9..76fe075 100644 --- a/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift +++ b/hello-swift-raw-jni-callback/src/main/swift/Sources/hello-swift-callback/hello-swift-callback.swift @@ -19,17 +19,19 @@ import Dispatch private var gJavaVM: UnsafeMutablePointer? @_cdecl("JNI_OnLoad") -public func JNI_OnLoad(vm: UnsafeMutablePointer, reserved: UnsafeMutableRawPointer?) -> jint { - gJavaVM = vm - return jint(JNI_VERSION_1_6) +public func JNI_OnLoad(vm: UnsafeMutablePointer, reserved: UnsafeMutableRawPointer?) + -> jint +{ + gJavaVM = vm + return jint(JNI_VERSION_1_6) } struct JGlobalObject: @unchecked Sendable { - let ref: jobject + let ref: jobject } struct JMethodID: @unchecked Sendable { - let id: jmethodID + let id: jmethodID } let queue = DispatchQueue(label: "hello-swift-raw-jni-callback") @@ -37,46 +39,46 @@ var workItem: DispatchWorkItem? = nil var activityRef: jobject? = nil private func getEnvForCurrentThread(block: (UnsafeMutablePointer?) -> Void) { - var env: UnsafeMutablePointer? - let attachCode = gJavaVM!.pointee!.pointee.AttachCurrentThread(gJavaVM, &env, nil) - guard attachCode == 0 else { return } - block(env) - _ = gJavaVM!.pointee!.pointee.DetachCurrentThread(gJavaVM) + var env: UnsafeMutablePointer? + let attachCode = gJavaVM!.pointee!.pointee.AttachCurrentThread(gJavaVM, &env, nil) + guard attachCode == 0 else { return } + block(env) + _ = gJavaVM!.pointee!.pointee.DetachCurrentThread(gJavaVM) } @_cdecl("Java_org_example_helloswift_MainActivity_startTicks") public func MainActivity_startTicks(env: UnsafeMutablePointer, thiz: jobject) { - guard let globalRef = env.pointee!.pointee.NewGlobalRef(env, thiz) else { return } - guard let cls = env.pointee!.pointee.GetObjectClass(env, thiz) else { return } - defer { env.pointee!.pointee.DeleteLocalRef(env, cls) } - guard let mid = env.pointee!.pointee.GetMethodID(env, cls, "updateTimer", "()V") else { return } + guard let globalRef = env.pointee!.pointee.NewGlobalRef(env, thiz) else { return } + guard let cls = env.pointee!.pointee.GetObjectClass(env, thiz) else { return } + defer { env.pointee!.pointee.DeleteLocalRef(env, cls) } + guard let mid = env.pointee!.pointee.GetMethodID(env, cls, "updateTimer", "()V") else { return } - let activityHandle = JGlobalObject(ref: globalRef) - let methodHandle = JMethodID(id: mid) + let activityHandle = JGlobalObject(ref: globalRef) + let methodHandle = JMethodID(id: mid) - queue.async { - workItem?.cancel() - workItem = DispatchWorkItem { - getEnvForCurrentThread { env in - env?.pointee!.pointee.CallVoidMethodA(env, activityHandle.ref, methodHandle.id, nil) - } - if let workItem = workItem, workItem.isCancelled == false { - queue.asyncAfter(deadline: .now() + 1, execute: workItem) - } - } - queue.async(execute: workItem!) + queue.async { + workItem?.cancel() + workItem = DispatchWorkItem { + getEnvForCurrentThread { env in + env?.pointee!.pointee.CallVoidMethodA(env, activityHandle.ref, methodHandle.id, nil) + } + if let workItem = workItem, workItem.isCancelled == false { + queue.asyncAfter(deadline: .now() + 1, execute: workItem) + } } + queue.async(execute: workItem!) + } } @_cdecl("Java_org_example_helloswift_MainActivity_stopTicks") public func MainActivity_stopTicks(env: UnsafeMutablePointer, jthis: jobject) { - queue.async { - workItem?.cancel() - workItem = nil - if let activityRef = activityRef { - getEnvForCurrentThread { env in - env?.pointee!.pointee.DeleteGlobalRef(env, activityRef) - } - } + queue.async { + workItem?.cancel() + workItem = nil + if let activityRef = activityRef { + getEnvForCurrentThread { env in + env?.pointee!.pointee.DeleteGlobalRef(env, activityRef) + } } + } } diff --git a/hello-swift-raw-jni-library/src/main/swift/Package.swift b/hello-swift-raw-jni-library/src/main/swift/Package.swift index ad9d3b4..ce70ef2 100644 --- a/hello-swift-raw-jni-library/src/main/swift/Package.swift +++ b/hello-swift-raw-jni-library/src/main/swift/Package.swift @@ -4,11 +4,12 @@ import PackageDescription let package = Package( - name: "hello-swift-raw-jni-library", - products: [ - .library(name: "hello-swift-raw-jni-library", type: .dynamic, targets: ["hello-swift-raw-jni-library"]), - ], - targets: [ - .target(name: "hello-swift-raw-jni-library") - ] + name: "hello-swift-raw-jni-library", + products: [ + .library( + name: "hello-swift-raw-jni-library", type: .dynamic, targets: ["hello-swift-raw-jni-library"]) + ], + targets: [ + .target(name: "hello-swift-raw-jni-library") + ] ) diff --git a/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift b/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift index 422b178..b63f108 100644 --- a/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift +++ b/hello-swift-raw-jni-library/src/main/swift/Sources/helloswift/helloswift.swift @@ -15,9 +15,11 @@ import Android @_cdecl("Java_org_example_swiftlibrary_SwiftLibrary_stringFromSwift") -public func SwiftLibrary_stringFromSwift(env: UnsafeMutablePointer, clazz: jclass) -> jstring { - let hello = "Hello from Swift" - return hello.withCString { ptr in - env.pointee!.pointee.NewStringUTF(env, ptr)! - } +public func SwiftLibrary_stringFromSwift(env: UnsafeMutablePointer, clazz: jclass) + -> jstring +{ + let hello = "Hello from Swift" + return hello.withCString { ptr in + env.pointee!.pointee.NewStringUTF(env, ptr)! + } } diff --git a/hello-swift-raw-jni/src/main/swift/Package.swift b/hello-swift-raw-jni/src/main/swift/Package.swift index a039d87..a46960e 100644 --- a/hello-swift-raw-jni/src/main/swift/Package.swift +++ b/hello-swift-raw-jni/src/main/swift/Package.swift @@ -4,11 +4,11 @@ import PackageDescription let package = Package( - name: "helloswift", - products: [ - .library(name: "helloswift", type: .dynamic, targets: ["helloswift"]), - ], - targets: [ - .target(name: "helloswift") - ] + name: "helloswift", + products: [ + .library(name: "helloswift", type: .dynamic, targets: ["helloswift"]) + ], + targets: [ + .target(name: "helloswift") + ] ) diff --git a/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift b/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift index ca1d355..968af5e 100644 --- a/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift +++ b/hello-swift-raw-jni/src/main/swift/Sources/helloswift/helloswift.swift @@ -15,9 +15,11 @@ import Android @_cdecl("Java_org_example_helloswift_MainActivity_stringFromSwift") -public func MainActivity_stringFromSwift(env: UnsafeMutablePointer, clazz: jclass) -> jstring { - let hello = ["Hello", "from", "Swift", "❤️"].joined(separator: " ") - return hello.withCString { ptr in - env.pointee!.pointee.NewStringUTF(env, ptr)! - } +public func MainActivity_stringFromSwift(env: UnsafeMutablePointer, clazz: jclass) + -> jstring +{ + let hello = ["Hello", "from", "Swift", "❤️"].joined(separator: " ") + return hello.withCString { ptr in + env.pointee!.pointee.NewStringUTF(env, ptr)! + } } diff --git a/native-activity/src/main/swift/Package.swift b/native-activity/src/main/swift/Package.swift index eab71ff..62ca26d 100644 --- a/native-activity/src/main/swift/Package.swift +++ b/native-activity/src/main/swift/Package.swift @@ -4,26 +4,26 @@ import PackageDescription let package = Package( - name: "native-activity", - products: [ - .library(name: "native-activity", type: .dynamic, targets: ["native-activity"]), - ], - dependencies: [ - .package(path: "../../../../native-app-glue") - ], - targets: [ - .target( - name: "native-activity", - dependencies: [ - .product(name: "AndroidNativeAppGlue", package: "native-app-glue"), - .product(name: "AndroidOpenGL", package: "native-app-glue") - ], - linkerSettings: [ - .linkedLibrary("android"), - .linkedLibrary("EGL"), - .linkedLibrary("GLESv1_CM"), - .linkedLibrary("log") - ] - ) - ] + name: "native-activity", + products: [ + .library(name: "native-activity", type: .dynamic, targets: ["native-activity"]) + ], + dependencies: [ + .package(path: "../../../../native-app-glue") + ], + targets: [ + .target( + name: "native-activity", + dependencies: [ + .product(name: "AndroidNativeAppGlue", package: "native-app-glue"), + .product(name: "AndroidOpenGL", package: "native-app-glue"), + ], + linkerSettings: [ + .linkedLibrary("android"), + .linkedLibrary("EGL"), + .linkedLibrary("GLESv1_CM"), + .linkedLibrary("log"), + ] + ) + ] ) diff --git a/native-activity/src/main/swift/Sources/native-activity/native-activity.swift b/native-activity/src/main/swift/Sources/native-activity/native-activity.swift index e01b696..3677d71 100644 --- a/native-activity/src/main/swift/Sources/native-activity/native-activity.swift +++ b/native-activity/src/main/swift/Sources/native-activity/native-activity.swift @@ -17,247 +17,248 @@ import AndroidNativeAppGlue import AndroidOpenGL public struct SavedState { - public var angle: Float = 0 - public var x: Int32 = 0 - public var y: Int32 = 0 + public var angle: Float = 0 + public var x: Int32 = 0 + public var y: Int32 = 0 } public final class Engine { - public var app: UnsafeMutablePointer? - - public var display: EGLDisplay? - public var surface: EGLSurface? - public var context: EGLContext? - public var width: Int32 = 0 - public var height: Int32 = 0 - public var state = SavedState() - - private var running_ = false - - public init(app: UnsafeMutablePointer?) { - self.app = app - } - - /** - * Initialize an EGL context for the current display. + public var app: UnsafeMutablePointer? + + public var display: EGLDisplay? + public var surface: EGLSurface? + public var context: EGLContext? + public var width: Int32 = 0 + public var height: Int32 = 0 + public var state = SavedState() + + private var running_ = false + + public init(app: UnsafeMutablePointer?) { + self.app = app + } + + /** + * Initialize an EGL context for the current display. + */ + public func initDisplay() -> Int32 { + guard let win = app?.pointee.window else { return -1 } + // initialize OpenGL ES and EGL + + /* + * Here specify the attributes of the desired configuration. + * Below, we select an EGLConfig with at least 8 bits per color + * component compatible with on-screen windows + */ + let attribs: [EGLint] = [ + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_NONE, + ] + + let display: EGLDisplay! = eglGetDisplay(nil) + _ = eglInitialize(display, nil, nil) + + var numConfigs: EGLint = 0 + _ = eglChooseConfig(display, attribs, nil, 0, &numConfigs) + if numConfigs <= 0 { return -1 } + let cfgBuf = UnsafeMutablePointer.allocate(capacity: Int(numConfigs)) + defer { cfgBuf.deallocate() } + + /* Here, the application chooses the configuration it desires. + * find the best match if possible, otherwise use the very first one */ - public func initDisplay() -> Int32 { - guard let win = app?.pointee.window else { return -1 } - // initialize OpenGL ES and EGL - - /* - * Here specify the attributes of the desired configuration. - * Below, we select an EGLConfig with at least 8 bits per color - * component compatible with on-screen windows - */ - let attribs: [EGLint] = [ - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_NONE - ] - - let display: EGLDisplay! = eglGetDisplay(nil) - _ = eglInitialize(display, nil, nil) - - var numConfigs: EGLint = 0 - _ = eglChooseConfig(display, attribs, nil, 0, &numConfigs) - if numConfigs <= 0 { return -1 } - let cfgBuf = UnsafeMutablePointer.allocate(capacity: Int(numConfigs)) - defer { cfgBuf.deallocate() } - - /* Here, the application chooses the configuration it desires. - * find the best match if possible, otherwise use the very first one - */ - _ = eglChooseConfig(display, attribs, cfgBuf, numConfigs, &numConfigs) - - // Pick the best match: R=G=B=8, DEPTH=0 - var chosen: EGLConfig? = nil - for i in 0.. 1 { - state.angle = 0 - } + } + + /// Pauses ticking the application (Choreographer). + public func pause() { + running_ = false + } + + /** + * Tear down the EGL context currently associated with the display. + */ + public func termDisplay() { + if let dpy = self.display { + _ = eglMakeCurrent(dpy, nil, nil, nil) + if let ctx = self.context { + _ = eglDestroyContext(dpy, ctx) + } + if let surf = self.surface { + _ = eglDestroySurface(dpy, surf) + } + _ = eglTerminate(dpy) + } + self.pause() + self.display = nil + self.context = nil + self.surface = nil + } + + private func scheduleNextTick() { + let choreo = AChoreographer_getInstance() + AChoreographer_postFrameCallback(choreo, Engine_Tick, Unmanaged.passUnretained(self).toOpaque()) + } + + fileprivate func doTick() { + guard running_ else { return } + + // Choreographer does not continuously schedule the callback. We have to re- + // register the callback each time we're ticked. + scheduleNextTick() + update() + drawFrame() + } + + private func update() { + state.angle += 0.01 + if state.angle > 1 { + state.angle = 0 } + } - private func drawFrame() { - guard display != nil, surface != nil else { - // No display/surface yet. - return - } + private func drawFrame() { + guard display != nil, surface != nil else { + // No display/surface yet. + return + } - // Just fill the screen with a color - let r = Float(state.x) / Float(max(1, width)) - let g = Float(state.y) / Float(max(1, height)) - let b = state.angle + // Just fill the screen with a color + let r = Float(state.x) / Float(max(1, width)) + let g = Float(state.y) / Float(max(1, height)) + let b = state.angle - glClearColor(r, g, b, 1) - glClear(GLbitfield(GL_COLOR_BUFFER_BIT)) + glClearColor(r, g, b, 1) + glClear(GLbitfield(GL_COLOR_BUFFER_BIT)) - _ = eglSwapBuffers(display, surface) - } + _ = eglSwapBuffers(display, surface) + } } @_cdecl("Engine_Tick") public func Engine_Tick(_ frameTimeNanos: Int, _ data: UnsafeMutableRawPointer?) { - guard let data else { return } - let engine = Unmanaged.fromOpaque(data).takeUnretainedValue() - engine.doTick() + guard let data else { return } + let engine = Unmanaged.fromOpaque(data).takeUnretainedValue() + engine.doTick() } @_silgen_name("android_main") public func android_main(_ app: UnsafeMutablePointer) { - let engine = Engine(app: app) - app.pointee.userData = Unmanaged.passRetained(engine).toOpaque() - - app.pointee.onAppCmd = { app, cmd in - // unwrap the optional android_app* and userData - guard let opaque = app?.pointee.userData else { return } - - // turn void* back into Engine - let engine = Unmanaged.fromOpaque(opaque).takeUnretainedValue() - - switch Int(cmd) { - case APP_CMD_INIT_WINDOW: - _ = engine.initDisplay() - case APP_CMD_TERM_WINDOW: - engine.termDisplay() - case APP_CMD_GAINED_FOCUS: - engine.resume() - case APP_CMD_LOST_FOCUS: - engine.pause() - default: - print("Unsupported command \(cmd)") - } + let engine = Engine(app: app) + app.pointee.userData = Unmanaged.passRetained(engine).toOpaque() + + app.pointee.onAppCmd = { app, cmd in + // unwrap the optional android_app* and userData + guard let opaque = app?.pointee.userData else { return } + + // turn void* back into Engine + let engine = Unmanaged.fromOpaque(opaque).takeUnretainedValue() + + switch Int(cmd) { + case APP_CMD_INIT_WINDOW: + _ = engine.initDisplay() + case APP_CMD_TERM_WINDOW: + engine.termDisplay() + case APP_CMD_GAINED_FOCUS: + engine.resume() + case APP_CMD_LOST_FOCUS: + engine.pause() + default: + print("Unsupported command \(cmd)") } + } - while app.pointee.destroyRequested == 0 { - var outData: UnsafeMutableRawPointer? = nil + while app.pointee.destroyRequested == 0 { + var outData: UnsafeMutableRawPointer? = nil - let r = ALooper_pollOnce(-1, nil, nil, &outData) - if r == ALOOPER_POLL_ERROR { - fatalError("ALooper_pollOnce returned an error") - } + let r = ALooper_pollOnce(-1, nil, nil, &outData) + if r == ALOOPER_POLL_ERROR { + fatalError("ALooper_pollOnce returned an error") + } - if let outData { - let source = outData.assumingMemoryBound(to: android_poll_source.self) - source.pointee.process(app, source) - } + if let outData { + let source = outData.assumingMemoryBound(to: android_poll_source.self) + source.pointee.process(app, source) } + } - engine.termDisplay() + engine.termDisplay() } diff --git a/native-app-glue/Package.swift b/native-app-glue/Package.swift index 7a96a86..5c9f120 100644 --- a/native-app-glue/Package.swift +++ b/native-app-glue/Package.swift @@ -4,14 +4,14 @@ import PackageDescription let package = Package( - name: "AndroidNativeAppGlue", - products: [ - .library(name: "AndroidNativeAppGlue", targets: ["AndroidNativeAppGlue"]), - .library(name: "AndroidOpenGL", targets: ["AndroidOpenGL"]) - ], - targets: [ - .target(name: "AndroidNativeAppGlue"), - .target(name: "AndroidOpenGL") - ], - cxxLanguageStandard: .cxx98 + name: "AndroidNativeAppGlue", + products: [ + .library(name: "AndroidNativeAppGlue", targets: ["AndroidNativeAppGlue"]), + .library(name: "AndroidOpenGL", targets: ["AndroidOpenGL"]), + ], + targets: [ + .target(name: "AndroidNativeAppGlue"), + .target(name: "AndroidOpenGL"), + ], + cxxLanguageStandard: .cxx98 ) diff --git a/swift-java-weather-app/weather-lib/Package.swift b/swift-java-weather-app/weather-lib/Package.swift index 0675e72..44ebee0 100644 --- a/swift-java-weather-app/weather-lib/Package.swift +++ b/swift-java-weather-app/weather-lib/Package.swift @@ -23,20 +23,24 @@ let package = Package( ], targets: [ .target( - name: "WeatherLibrary", - dependencies: [ - .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"), - .product(name: "OpenAPIURLSession", package: "swift-openapi-urlsession", condition: .when(platforms: [.macOS, .iOS])), - .product(name: "OpenAPIAsyncHTTPClient", package: "swift-openapi-async-http-client", condition: .when(platforms: [.android])), - .product(name: "SwiftJava", package: "swift-java") - ], - swiftSettings: [ - .swiftLanguageMode(.v5) - ], - plugins: [ - .plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator"), - .plugin(name: "JExtractSwiftPlugin", package: "swift-java") - ] + name: "WeatherLibrary", + dependencies: [ + .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"), + .product( + name: "OpenAPIURLSession", package: "swift-openapi-urlsession", + condition: .when(platforms: [.macOS, .iOS])), + .product( + name: "OpenAPIAsyncHTTPClient", package: "swift-openapi-async-http-client", + condition: .when(platforms: [.android])), + .product(name: "SwiftJava", package: "swift-java"), + ], + swiftSettings: [ + .swiftLanguageMode(.v5) + ], + plugins: [ + .plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator"), + .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), + ] ) ] ) diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift index 4b7881c..395daad 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/LocationFetcher.swift @@ -13,16 +13,16 @@ //===----------------------------------------------------------------------===// public struct Location { - public let latitude: Double - public let longitude: Double + public let latitude: Double + public let longitude: Double - public init(latitude: Double, longitude: Double) { - self.latitude = latitude - self.longitude = longitude - } + public init(latitude: Double, longitude: Double) { + self.latitude = latitude + self.longitude = longitude + } } /// Responsible for fetching GPS locations public protocol LocationFetcher { - func currentLocation() -> Location + func currentLocation() -> Location } diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift index e6bcd79..9f4944d 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherClient.swift @@ -13,59 +13,62 @@ //===----------------------------------------------------------------------===// #if os(Android) -import OpenAPIAsyncHTTPClient + import OpenAPIAsyncHTTPClient #else -import OpenAPIURLSession + import OpenAPIURLSession #endif import OpenAPIRuntime import Foundation public final class WeatherClient { - private let client: Client - private let locationFetcher: any LocationFetcher + private let client: Client + private let locationFetcher: any LocationFetcher - public init(locationFetcher: any LocationFetcher) { - guard let serverURL = URL(string: "https://api.open-meteo.com") else { - fatalError("Could not create server URL.") - } - - self.locationFetcher = locationFetcher - self.client = Client( - serverURL: serverURL, - transport: WeatherClient.makeTransport() - ) + public init(locationFetcher: any LocationFetcher) { + guard let serverURL = URL(string: "https://api.open-meteo.com") else { + fatalError("Could not create server URL.") } - /// Fetches the current weather for a specific geographic location. - public func getWeather() async throws -> WeatherData { - let location = self.locationFetcher.currentLocation() - let response = try await client.getV1Forecast(.init(query: .init(latitude: location.latitude, longitude: location.longitude, currentWeather: true))) + self.locationFetcher = locationFetcher + self.client = Client( + serverURL: serverURL, + transport: WeatherClient.makeTransport() + ) + } - switch response { - case .ok(let okResponse): - switch okResponse.body { - case .json(let forecast): - guard let current = forecast.currentWeather else { - throw WeatherError.unexpectedResponse - } + /// Fetches the current weather for a specific geographic location. + public func getWeather() async throws -> WeatherData { + let location = self.locationFetcher.currentLocation() + let response = try await client.getV1Forecast( + .init( + query: .init( + latitude: location.latitude, longitude: location.longitude, currentWeather: true))) - return WeatherData( - temperature: current.temperature, - windSpeed: current.windspeed, - windDirection: current.winddirection - ) - } - - default: - throw WeatherError.apiError("Received an API error: \(response)") + switch response { + case .ok(let okResponse): + switch okResponse.body { + case .json(let forecast): + guard let current = forecast.currentWeather else { + throw WeatherError.unexpectedResponse } - } - private static func makeTransport() -> some ClientTransport { -#if os(Android) - return AsyncHTTPClientTransport(configuration: .init()) -#else - return URLSessionTransport() -#endif + return WeatherData( + temperature: current.temperature, + windSpeed: current.windspeed, + windDirection: current.winddirection + ) + } + + default: + throw WeatherError.apiError("Received an API error: \(response)") } + } + + private static func makeTransport() -> some ClientTransport { + #if os(Android) + return AsyncHTTPClientTransport(configuration: .init()) + #else + return URLSessionTransport() + #endif + } } diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift index c5086bd..76447ef 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherData.swift @@ -14,7 +14,7 @@ /// Represents the current weather conditions for a specific location. public struct WeatherData: Hashable { - public let temperature: Double - public let windSpeed: Double - public let windDirection: Double + public let temperature: Double + public let windSpeed: Double + public let windDirection: Double } diff --git a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift index 36995a2..64225c8 100644 --- a/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift +++ b/swift-java-weather-app/weather-lib/Sources/WeatherLibrary/WeatherError.swift @@ -13,15 +13,15 @@ //===----------------------------------------------------------------------===// public enum WeatherError: Error { - case apiError(String) - case unexpectedResponse + case apiError(String) + case unexpectedResponse - public var description: String { - switch self { - case .apiError(let message): - return "API Error: \(message)" - case .unexpectedResponse: - return "The server returned an invalid or unexpected response." - } + public var description: String { + switch self { + case .apiError(let message): + return "API Error: \(message)" + case .unexpectedResponse: + return "The server returned an invalid or unexpected response." } + } } From 7de27b9a71ff19686177489aee0d2c85a5b72fa5 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 7 May 2026 22:29:09 -0400 Subject: [PATCH 36/39] Add swift_version nightly-6.3 and ndk_version r29 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 061841c..ada9bcd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,8 +25,8 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ["6.3", "nightly-main"] - ndk_version: ['r27d', 'r30-beta1'] + swift_version: ['6.3', 'nightly-6.3', 'nightly-main'] + ndk_version: ['r27d', 'r29', 'r30-beta1'] os: ['ubuntu-latest', 'macos-latest'] configuration: ['Debug', 'Release'] runs-on: ${{ matrix.os }} From 874cb5b1f264a92ed4148ccee8c42bb35909704f Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Fri, 8 May 2026 11:56:55 -0400 Subject: [PATCH 37/39] Separate soundness and ci into separate actions --- .github/workflows/ci.yml | 7 +------ .github/workflows/soundness.yml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/soundness.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ada9bcd..493702e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,7 @@ name: ci on: push: + # branches: [ main ] pull_request: schedule: - cron: '0 0 * * *' @@ -15,12 +16,6 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - soundness: - name: Soundness - uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main - with: - license_header_check_project_name: "Swift.org" - build-examples: strategy: fail-fast: false diff --git a/.github/workflows/soundness.yml b/.github/workflows/soundness.yml new file mode 100644 index 0000000..3822fb6 --- /dev/null +++ b/.github/workflows/soundness.yml @@ -0,0 +1,15 @@ +name: soundness + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + soundness: + name: Soundness + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + with: + license_header_check_project_name: "Swift.org" From a0f1132f8052d85fae770851f4e9956b6bd20051 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Fri, 8 May 2026 15:32:27 -0400 Subject: [PATCH 38/39] Only run on push to main and update the cron schedule --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 493702e..5dba49b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,10 +2,10 @@ name: ci on: push: - # branches: [ main ] + branches: [ main ] pull_request: schedule: - - cron: '0 0 * * *' + - cron: '0 4 * * *' workflow_dispatch: permissions: From c3a3862b340d94d81705fec9f49fbba2ae1a3c9c Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Fri, 8 May 2026 15:35:11 -0400 Subject: [PATCH 39/39] Fix yaml formatting --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5dba49b..f91c3d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: ci on: push: - branches: [ main ] + branches: [main] pull_request: schedule: - cron: '0 4 * * *'