From 752cef943cecc46b0483a0fa0bda4649c74447dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Tue, 20 Jan 2026 10:32:55 +0100 Subject: [PATCH 1/5] Add Windows release artifacts --- .github/workflows/windows-release-build.yml | 94 +++++++++++++++++++++ Package.swift | 17 +++- Platforms/Windows/SwiftLint.wixproj | 15 ++++ Platforms/Windows/SwiftLint.wxs | 70 +++++++++++++++ 4 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/windows-release-build.yml create mode 100644 Platforms/Windows/SwiftLint.wixproj create mode 100644 Platforms/Windows/SwiftLint.wxs diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml new file mode 100644 index 0000000000..4bd39b2c21 --- /dev/null +++ b/.github/workflows/windows-release-build.yml @@ -0,0 +1,94 @@ +name: Windows Release Build + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + build-windows: + name: Build Static Windows ${{ matrix.arch-display-name }} Binary and Installer + runs-on: windows-${{ matrix.windows-version }} + env: + SWIFT_VERSION: development + SWIFT_BUILD: DEVELOPMENT-SNAPSHOT-2026-01-09-a + strategy: + fail-fast: false + matrix: + include: + - windows-version: 2025 + windows-display-name: "Server 2025" + arch: amd64 + arch-display-name: AMD64 + wix-platform: x64 + target-triple: x86_64-unknown-windows-msvc + - windows-version: "11-arm" + windows-display-name: "11 ARM" + arch: arm64 + arch-display-name: ARM64 + wix-platform: arm64 + target-triple: aarch64-unknown-windows-msvc + steps: + - name: Enable long path support + run: reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f + - name: Set up Swift + uses: compnerd/gha-setup-swift@main + with: + swift-version: ${{ env.SWIFT_VERSION }} + swift-build: ${{ env.SWIFT_BUILD }} + build_arch: ${{ matrix.arch }} + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + - name: Build static executable + shell: pwsh + env: + SWIFTLINT_STATIC_WINDOWS_BUILD: 1 + run: | + $sdk = Join-Path (Split-Path -Path $env:SDKROOT -Parent) 'WindowsExperimental.sdk' + $archDir = ('${{ matrix.target-triple }}'.Split('-')[0]) + $staticLibDir = Join-Path $sdk (Join-Path 'usr\lib\swift_static\windows' $archDir) + Copy-Item -Path (Join-Path $staticLibDir 'libcurl.lib') -Destination (Join-Path $staticLibDir 'curl.lib') -Force + Copy-Item -Path (Join-Path $staticLibDir 'libxml2s.lib') -Destination (Join-Path $staticLibDir 'xml2.lib') -Force + swift build ` + -c release ` + --product swiftlint ` + --triple ${{ matrix.target-triple }} ` + -debug-info-format none ` + -Xswiftc -static-stdlib ` + -Xswiftc -sdk ` + -Xswiftc $sdk ` + -Xlinker /LIBPATH:"$staticLibDir" + - name: Prepare artifacts directory + shell: pwsh + run: | + New-Item -ItemType Directory -Path artifacts -Force | Out-Null + Copy-Item ".build/${{ matrix.target-triple }}/release/swiftlint.exe" "artifacts/swiftlint.exe" -Force + - name: Create portable zip + shell: pwsh + run: | + Compress-Archive -Path "artifacts/swiftlint.exe" -DestinationPath "artifacts/swiftlint-portable-${{ matrix.arch }}.zip" -Force + - name: Setup MSBuild + uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + - name: Build WiX MSI + shell: pwsh + run: | + & msbuild -nologo -restore ` + Platforms\Windows\SwiftLint.wixproj ` + -p:Configuration=Release ` + -p:InstallerPlatform=${{ matrix.wix-platform }} ` + -p:ProductVersion=0.63.1.${{ github.run_number }} ` + -p:SwiftLintBuildDir=${{ github.workspace }}\.build\${{ matrix.target-triple }}\release ` + -p:OutputPath=${{ github.workspace }}\artifacts ` + -p:RunWixToolsOutOfProc=true + Move-Item -Path "artifacts\SwiftLint.msi" -Destination "artifacts\SwiftLint.${{ matrix.arch }}.msi" -Force + - name: Upload artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: artifacts-${{ matrix.arch }} + path: artifacts + if-no-files-found: error + retention-days: 2 diff --git a/Package.swift b/Package.swift index 96a1df644b..32ab39118f 100644 --- a/Package.swift +++ b/Package.swift @@ -1,5 +1,6 @@ // swift-tools-version:5.9 import CompilerPluginSupport +import Foundation import PackageDescription let swiftFeatures: [SwiftSetting] = [ @@ -25,6 +26,19 @@ swiftLintPluginDependencies = [.target(name: "SwiftLintBinary")] swiftLintPluginDependencies = [.target(name: "swiftlint")] #endif +// Linker flags for static Windows builds. +let windowsStaticLinkerFlags: [LinkerSetting] = + if ProcessInfo.processInfo.environment["SWIFTLINT_STATIC_WINDOWS_BUILD"] == nil { + [] + } else { + [ + .linkedLibrary("libcurl.lib"), + .linkedLibrary("zlibstatic.lib"), + .linkedLibrary("brotlicommon.lib"), + .linkedLibrary("brotlidec.lib"), + ] + } + let package = Package( name: "SwiftLint", platforms: [.macOS(.v13)], @@ -53,7 +67,8 @@ let package = Package( "SwiftLintFramework", "SwiftyTextTable", ], - swiftSettings: swiftFeatures + strictConcurrency + swiftSettings: swiftFeatures + strictConcurrency, + linkerSettings: windowsStaticLinkerFlags ), .executableTarget( name: "swiftlint-dev", diff --git a/Platforms/Windows/SwiftLint.wixproj b/Platforms/Windows/SwiftLint.wixproj new file mode 100644 index 0000000000..66ccd83ee5 --- /dev/null +++ b/Platforms/Windows/SwiftLint.wixproj @@ -0,0 +1,15 @@ + + + Package + SwiftLint + SwiftLint + + ProductVersion=$(ProductVersion); + SwiftLintBuildDir=$(SwiftLintBuildDir) + + + + + + + diff --git a/Platforms/Windows/SwiftLint.wxs b/Platforms/Windows/SwiftLint.wxs new file mode 100644 index 0000000000..2e6742a40c --- /dev/null +++ b/Platforms/Windows/SwiftLint.wxs @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 837d4770232bf7b3e42da61b0aafbdaea0dbac1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Wed, 21 Jan 2026 20:05:05 +0100 Subject: [PATCH 2/5] Compile with static linking --- .github/workflows/windows-release-build.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml index 4bd39b2c21..e0360337db 100644 --- a/.github/workflows/windows-release-build.yml +++ b/.github/workflows/windows-release-build.yml @@ -45,14 +45,8 @@ jobs: persist-credentials: false - name: Build static executable shell: pwsh - env: - SWIFTLINT_STATIC_WINDOWS_BUILD: 1 run: | $sdk = Join-Path (Split-Path -Path $env:SDKROOT -Parent) 'WindowsExperimental.sdk' - $archDir = ('${{ matrix.target-triple }}'.Split('-')[0]) - $staticLibDir = Join-Path $sdk (Join-Path 'usr\lib\swift_static\windows' $archDir) - Copy-Item -Path (Join-Path $staticLibDir 'libcurl.lib') -Destination (Join-Path $staticLibDir 'curl.lib') -Force - Copy-Item -Path (Join-Path $staticLibDir 'libxml2s.lib') -Destination (Join-Path $staticLibDir 'xml2.lib') -Force swift build ` -c release ` --product swiftlint ` @@ -61,7 +55,8 @@ jobs: -Xswiftc -static-stdlib ` -Xswiftc -sdk ` -Xswiftc $sdk ` - -Xlinker /LIBPATH:"$staticLibDir" + -Xcc -DCURL_STATICLIB ` + -Xcc -DLIBXML_STATIC - name: Prepare artifacts directory shell: pwsh run: | From 0c2c66f80ca80c92193ee50cc0ee9b1a11632197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Wed, 21 Jan 2026 21:31:30 +0100 Subject: [PATCH 3/5] Disable support for long paths --- .github/workflows/windows-release-build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml index e0360337db..0f0134dde3 100644 --- a/.github/workflows/windows-release-build.yml +++ b/.github/workflows/windows-release-build.yml @@ -31,8 +31,6 @@ jobs: wix-platform: arm64 target-triple: aarch64-unknown-windows-msvc steps: - - name: Enable long path support - run: reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f - name: Set up Swift uses: compnerd/gha-setup-swift@main with: From 7f338486d4771e8e2bd7f5443274f8b2ae82da5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Fri, 23 Jan 2026 10:54:39 +0100 Subject: [PATCH 4/5] Explicitly link to static libraries --- .github/workflows/windows-release-build.yml | 7 +++++-- Package.swift | 17 +---------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml index 0f0134dde3..39fdaf1cfa 100644 --- a/.github/workflows/windows-release-build.yml +++ b/.github/workflows/windows-release-build.yml @@ -53,8 +53,11 @@ jobs: -Xswiftc -static-stdlib ` -Xswiftc -sdk ` -Xswiftc $sdk ` - -Xcc -DCURL_STATICLIB ` - -Xcc -DLIBXML_STATIC + -Xlinker /NODEFAULTLIB:curl -Xlinker libcurl.lib ` + -Xlinker /NODEFAULTLIB:xml2 -Xlinker libxml2s.lib ` + -Xlinker zlibstatic.lib ` + -Xlinker brotlidec.lib ` + -Xlinker brotlicommon.lib - name: Prepare artifacts directory shell: pwsh run: | diff --git a/Package.swift b/Package.swift index 32ab39118f..96a1df644b 100644 --- a/Package.swift +++ b/Package.swift @@ -1,6 +1,5 @@ // swift-tools-version:5.9 import CompilerPluginSupport -import Foundation import PackageDescription let swiftFeatures: [SwiftSetting] = [ @@ -26,19 +25,6 @@ swiftLintPluginDependencies = [.target(name: "SwiftLintBinary")] swiftLintPluginDependencies = [.target(name: "swiftlint")] #endif -// Linker flags for static Windows builds. -let windowsStaticLinkerFlags: [LinkerSetting] = - if ProcessInfo.processInfo.environment["SWIFTLINT_STATIC_WINDOWS_BUILD"] == nil { - [] - } else { - [ - .linkedLibrary("libcurl.lib"), - .linkedLibrary("zlibstatic.lib"), - .linkedLibrary("brotlicommon.lib"), - .linkedLibrary("brotlidec.lib"), - ] - } - let package = Package( name: "SwiftLint", platforms: [.macOS(.v13)], @@ -67,8 +53,7 @@ let package = Package( "SwiftLintFramework", "SwiftyTextTable", ], - swiftSettings: swiftFeatures + strictConcurrency, - linkerSettings: windowsStaticLinkerFlags + swiftSettings: swiftFeatures + strictConcurrency ), .executableTarget( name: "swiftlint-dev", From ae395523304e9996ed6a40b0f7ccdcfed71b18f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Fri, 23 Jan 2026 18:36:31 +0100 Subject: [PATCH 5/5] Move steps into release workflow --- .github/workflows/release.yml | 95 ++++++++++++++++++++- .github/workflows/windows-release-build.yml | 90 ------------------- tools/create-github-release.sh | 6 +- 3 files changed, 97 insertions(+), 94 deletions(-) delete mode 100644 .github/workflows/windows-release-build.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68c0bfbeb1..aa7f299b0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,11 +4,11 @@ on: workflow_dispatch: inputs: version: - description: 'Release version' + description: "Release version" required: true type: string title: - description: 'Release title' + description: "Release title" required: true type: string @@ -198,6 +198,88 @@ jobs: retention-days: 2 if-no-files-found: error + build-windows: + name: Build Windows ${{ matrix.arch-display-name }} Installer + needs: prepare-release + runs-on: windows-${{ matrix.windows-version }} + env: + SWIFT_VERSION: development + SWIFT_BUILD: DEVELOPMENT-SNAPSHOT-2026-01-09-a + strategy: + fail-fast: false + matrix: + include: + - windows-version: 2025 + arch-display-name: AMD64 + arch: amd64 + wix-platform: x64 + target-triple: x86_64-unknown-windows-msvc + - windows-version: "11-arm" + arch-display-name: ARM64 + arch: arm64 + wix-platform: arm64 + target-triple: aarch64-unknown-windows-msvc + permissions: + contents: read + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ env.RELEASE_BRANCH }} + persist-credentials: false + - name: Set up Swift + uses: compnerd/gha-setup-swift@main + with: + swift-version: ${{ env.SWIFT_VERSION }} + swift-build: ${{ env.SWIFT_BUILD }} + build_arch: ${{ matrix.arch }} + - name: Build static executable + shell: pwsh + run: | + $sdk = Join-Path (Split-Path -Path $env:SDKROOT -Parent) 'WindowsExperimental.sdk' + swift build ` + -c release ` + --product swiftlint ` + --triple ${{ matrix.target-triple }} ` + -debug-info-format none ` + -Xswiftc -static-stdlib ` + -Xswiftc -sdk ` + -Xswiftc $sdk ` + -Xlinker /NODEFAULTLIB:curl -Xlinker libcurl.lib ` + -Xlinker /NODEFAULTLIB:xml2 -Xlinker libxml2s.lib ` + -Xlinker zlibstatic.lib ` + -Xlinker brotlidec.lib ` + -Xlinker brotlicommon.lib + - name: Prepare artifacts directory + shell: pwsh + run: | + New-Item -ItemType Directory -Path artifacts -Force | Out-Null + Copy-Item ".build/${{ matrix.target-triple }}/release/swiftlint.exe" "artifacts/swiftlint.exe" -Force + - name: Create portable zip + shell: pwsh + run: | + Compress-Archive -Path "artifacts/swiftlint.exe" -DestinationPath "artifacts/SwiftLint.${{ matrix.arch }}.zip" -Force + - name: Setup MSBuild + uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + - name: Build WiX MSI + shell: pwsh + run: | + & msbuild -nologo ` + Platforms\Windows\SwiftLint.wixproj ` + -p:Configuration=Release ` + -p:InstallerPlatform=${{ matrix.wix-platform }} ` + -p:ProductVersion=${{ inputs.version }} ` + -p:SwiftLintBuildDir=${{ github.workspace }}\.build\${{ matrix.target-triple }}\release ` + -p:OutputPath=${{ github.workspace }}\artifacts ` + -p:RunWixToolsOutOfProc=true + Move-Item -Path "artifacts\SwiftLint.msi" -Destination "artifacts\SwiftLint.${{ matrix.arch }}.msi" -Force + - name: Upload artifacts + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: swiftlint-windows-${{ matrix.arch }} + path: artifacts + retention-days: 2 + if-no-files-found: error + create-release: name: Create Release needs: @@ -206,6 +288,7 @@ jobs: - build-linux - build-static-linux - build-macos + - build-windows runs-on: macOS-26 permissions: actions: read @@ -223,7 +306,10 @@ jobs: uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - name: Move artifacts run: | + # Move macOS artifacts. mv -f swiftlint-macos/* . + + # Move Linux artifacts. mv -f swiftlint-linux-amd64/swiftlint swiftlint_linux_amd64 mv -f swiftlint-linux-arm64/swiftlint swiftlint_linux_arm64 mv -f swiftlint-static-amd64/swiftlint swiftlint_static_amd64 @@ -231,9 +317,12 @@ jobs: # Just pick one of the licenses. mv -f swiftlint-static-amd64/LICENSE.mimalloc . + + # Move Windows artifacts. + mv -f swiftlint-windows-{arm,amd}64/*.{msi,zip} . - name: Make binaries executable run: chmod +x swiftlint* - - name: Create artifacts + - name: Package artifacts run: | make --debug spm_artifactbundle make --debug package diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml deleted file mode 100644 index 39fdaf1cfa..0000000000 --- a/.github/workflows/windows-release-build.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: Windows Release Build - -on: - pull_request: - workflow_dispatch: - -permissions: - contents: read - -jobs: - build-windows: - name: Build Static Windows ${{ matrix.arch-display-name }} Binary and Installer - runs-on: windows-${{ matrix.windows-version }} - env: - SWIFT_VERSION: development - SWIFT_BUILD: DEVELOPMENT-SNAPSHOT-2026-01-09-a - strategy: - fail-fast: false - matrix: - include: - - windows-version: 2025 - windows-display-name: "Server 2025" - arch: amd64 - arch-display-name: AMD64 - wix-platform: x64 - target-triple: x86_64-unknown-windows-msvc - - windows-version: "11-arm" - windows-display-name: "11 ARM" - arch: arm64 - arch-display-name: ARM64 - wix-platform: arm64 - target-triple: aarch64-unknown-windows-msvc - steps: - - name: Set up Swift - uses: compnerd/gha-setup-swift@main - with: - swift-version: ${{ env.SWIFT_VERSION }} - swift-build: ${{ env.SWIFT_BUILD }} - build_arch: ${{ matrix.arch }} - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - persist-credentials: false - - name: Build static executable - shell: pwsh - run: | - $sdk = Join-Path (Split-Path -Path $env:SDKROOT -Parent) 'WindowsExperimental.sdk' - swift build ` - -c release ` - --product swiftlint ` - --triple ${{ matrix.target-triple }} ` - -debug-info-format none ` - -Xswiftc -static-stdlib ` - -Xswiftc -sdk ` - -Xswiftc $sdk ` - -Xlinker /NODEFAULTLIB:curl -Xlinker libcurl.lib ` - -Xlinker /NODEFAULTLIB:xml2 -Xlinker libxml2s.lib ` - -Xlinker zlibstatic.lib ` - -Xlinker brotlidec.lib ` - -Xlinker brotlicommon.lib - - name: Prepare artifacts directory - shell: pwsh - run: | - New-Item -ItemType Directory -Path artifacts -Force | Out-Null - Copy-Item ".build/${{ matrix.target-triple }}/release/swiftlint.exe" "artifacts/swiftlint.exe" -Force - - name: Create portable zip - shell: pwsh - run: | - Compress-Archive -Path "artifacts/swiftlint.exe" -DestinationPath "artifacts/swiftlint-portable-${{ matrix.arch }}.zip" -Force - - name: Setup MSBuild - uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 - - name: Build WiX MSI - shell: pwsh - run: | - & msbuild -nologo -restore ` - Platforms\Windows\SwiftLint.wixproj ` - -p:Configuration=Release ` - -p:InstallerPlatform=${{ matrix.wix-platform }} ` - -p:ProductVersion=0.63.1.${{ github.run_number }} ` - -p:SwiftLintBuildDir=${{ github.workspace }}\.build\${{ matrix.target-triple }}\release ` - -p:OutputPath=${{ github.workspace }}\artifacts ` - -p:RunWixToolsOutOfProc=true - Move-Item -Path "artifacts\SwiftLint.msi" -Destination "artifacts\SwiftLint.${{ matrix.arch }}.msi" -Force - - name: Upload artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: artifacts-${{ matrix.arch }} - path: artifacts - if-no-files-found: error - retention-days: 2 diff --git a/tools/create-github-release.sh b/tools/create-github-release.sh index d02d160241..b6dfe6c856 100755 --- a/tools/create-github-release.sh +++ b/tools/create-github-release.sh @@ -16,9 +16,13 @@ gh release create "$version" --title "$release_title" -F "$release_notes" --draf "bazel.tar.gz" \ "bazel.tar.gz.sha256" \ "portable_swiftlint.zip#Universal macOS Binary" \ + "SwiftLint.pkg#Universal macOS Installer" \ "swiftlint_linux_amd64.zip#AMD64 Linux Binary" \ "swiftlint_linux_arm64.zip#ARM64 Linux Binary" \ - "SwiftLint.pkg#Universal macOS Installer" \ + "SwiftLint.amd64.zip#AMD64 Windows Binary" \ + "SwiftLint.arm64.zip#ARM64 Windows Binary" \ + "SwiftLint.amd64.msi#AMD64 Windows Installer" \ + "SwiftLint.arm64.msi#ARM64 Windows Installer" \ "SwiftLintBinary.artifactbundle.zip" rm "$release_notes"