xref: /curl/.github/workflows/windows.yml (revision 1a2d38c4)
1# Copyright (C) Viktor Szakats
2#
3# SPDX-License-Identifier: curl
4
5name: Windows
6
7'on':
8  push:
9    branches:
10      - master
11      - '*/ci'
12    paths-ignore:
13      - '**/*.md'
14      - '.circleci/**'
15      - 'appveyor.*'
16      - 'packages/**'
17      - 'plan9/**'
18      - 'projects/**'
19      - 'winbuild/**'
20  pull_request:
21    branches:
22      - master
23    paths-ignore:
24      - '**/*.md'
25      - '.circleci/**'
26      - 'appveyor.*'
27      - 'packages/**'
28      - 'plan9/**'
29      - 'projects/**'
30      - 'winbuild/**'
31
32concurrency:
33  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
34  cancel-in-progress: true
35
36permissions: {}
37
38jobs:
39  cygwin:
40    name: "cygwin, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.platform }} ${{ matrix.name }}"
41    runs-on: windows-latest
42    timeout-minutes: 45
43    defaults:
44      run:
45        shell: C:\cygwin\bin\bash.exe '{0}'
46    env:
47      SHELLOPTS: 'igncr'
48    strategy:
49      matrix:
50        include:
51          - { build: 'automake', platform: 'x86_64', tflags: 'skiprun', config: '', name: 'openssl R' }
52          - { build: 'cmake'   , platform: 'x86_64', tflags: ''       , config: '-DENABLE_DEBUG=ON -DCURL_USE_OPENSSL=ON -DENABLE_THREADED_RESOLVER=OFF', name: 'openssl' }
53      fail-fast: false
54    steps:
55      - run: git config --global core.autocrlf input
56        shell: pwsh
57      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
58      - uses: cygwin/cygwin-install-action@006ad0b0946ca6d0a3ea2d4437677fa767392401 # v4
59        with:
60          platform: ${{ matrix.platform }}
61          site: https://mirrors.kernel.org/sourceware/cygwin/
62          # https://cygwin.com/cgi-bin2/package-grep.cgi
63          packages: >-
64            autoconf libtool gcc-core gcc-g++ binutils
65            ${{ matrix.build }} make ninja
66            openssh
67            libssl-devel
68            libssh2-devel
69            libpsl-devel
70            zlib-devel
71            libbrotli-devel
72            libnghttp2-devel
73
74      - name: 'autotools autoreconf'
75        if: ${{ matrix.build == 'automake' }}
76        timeout-minutes: 2
77        run: autoreconf -fi
78
79      - name: 'autotools configure'
80        if: ${{ matrix.build == 'automake' }}
81        timeout-minutes: 5
82        run: |
83          PATH="/usr/bin:$(cygpath "${SYSTEMROOT}")/System32"
84          mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
85            --prefix="${HOME}"/install \
86            --with-openssl \
87            --with-libssh2 \
88            --disable-dependency-tracking \
89            ${{ matrix.config }}
90
91      - name: 'autotools configure log'
92        if: ${{ matrix.build == 'automake' && !cancelled() }}
93        run: cat bld/config.log 2>/dev/null || true
94
95      - name: 'curl_config.h'
96        if: ${{ matrix.build == 'automake' }}
97        run: |
98          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
99          grep -F '#define' bld/lib/curl_config.h | sort || true
100
101      - name: 'autotools build'
102        if: ${{ matrix.build == 'automake' }}
103        timeout-minutes: 10
104        run: make -C bld -j5 V=1 install
105
106      - name: 'curl version'
107        if: ${{ matrix.build == 'automake' }}
108        timeout-minutes: 1
109        run: |
110          find . -name '*.exe' -o -name '*.dll'
111          bld/src/curl.exe --disable --version
112
113      - name: 'autotools build tests'
114        if: ${{ matrix.build == 'automake' && matrix.tflags != 'skipall' }}
115        timeout-minutes: 15
116        run: make -C bld -j5 V=1 -C tests
117
118      - name: 'autotools run tests'
119        if: ${{ matrix.build == 'automake' && matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
120        timeout-minutes: 15
121        run: |
122          export TFLAGS='-j20 ${{ matrix.tflags }} ~615'
123          if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
124            TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
125          fi
126          make -C bld -j5 V=1 test-ci
127
128      - name: 'cmake configure'
129        if: ${{ matrix.build == 'cmake' }}
130        timeout-minutes: 5
131        run: |
132          PATH="/usr/bin:$(cygpath "${SYSTEMROOT}")/System32"
133          cmake -B bld -G Ninja ${options} \
134            -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
135            -DCURL_WERROR=ON \
136            -DCURL_BROTLI=ON \
137            ${{ matrix.config }}
138
139      - name: 'cmake configure log'
140        if: ${{ matrix.build == 'cmake' && !cancelled() }}
141        run: cat bld/CMakeFiles/CMake*.yaml 2>/dev/null || true
142
143      - name: 'curl_config.h'
144        if: ${{ matrix.build == 'cmake' }}
145        run: |
146          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
147          grep -F '#define' bld/lib/curl_config.h | sort || true
148
149      - name: 'cmake build'
150        if: ${{ matrix.build == 'cmake' }}
151        timeout-minutes: 10
152        run: cmake --build bld --config '${{ matrix.type }}'
153
154      - name: 'curl version'
155        if: ${{ matrix.build == 'cmake' }}
156        timeout-minutes: 1
157        run: |
158          find . -name '*.exe' -o -name '*.dll'
159          PATH="$PWD/bld/lib:$PATH"
160          bld/src/curl.exe --disable --version
161
162      - name: 'cmake build tests'
163        if: ${{ matrix.build == 'cmake' && matrix.tflags != 'skipall' }}
164        timeout-minutes: 15
165        run: cmake --build bld --config '${{ matrix.type }}' --target testdeps
166
167      - name: 'cmake run tests'
168        if: ${{ matrix.build == 'cmake' && matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
169        timeout-minutes: 15
170        run: |
171          export TFLAGS='-j8 ${{ matrix.tflags }} ~615'
172          if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
173            TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
174          fi
175          PATH="$PWD/bld/lib:$PATH"
176          cmake --build bld --config '${{ matrix.type }}' --target test-ci
177
178      - name: 'cmake build examples'
179        if: ${{ matrix.build == 'cmake' }}
180        timeout-minutes: 5
181        run: cmake --build bld --config '${{ matrix.type }}' --target curl-examples
182
183  msys2:  # both msys and mingw-w64
184    name: "${{ matrix.sys == 'msys' && 'msys2' || 'mingw' }}, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.env }} ${{ matrix.name }} ${{ matrix.test }}"
185    runs-on: windows-latest
186    timeout-minutes: 30
187    defaults:
188      run:
189        shell: msys2 {0}
190    strategy:
191      matrix:
192        include:
193          - { build: 'autotools', sys: 'msys'   , env: 'x86_64'      , tflags: '!19                !1233', config: '--enable-debug --disable-threaded-resolver --disable-proxy', name: '!proxy' }
194          - { build: 'autotools', sys: 'msys'   , env: 'x86_64'      , tflags: 'skiprun'                 , config: '--enable-debug --disable-threaded-resolver', name: 'default' }
195          - { build: 'cmake'    , sys: 'msys'   , env: 'x86_64'      , tflags: '!19 !504 !704 !705 !1233', config: '-DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF', name: 'default' }
196          - { build: 'autotools', sys: 'msys'   , env: 'x86_64'      , tflags: '!19 !504 !704 !705 !1233', config: '', name: 'default R' }
197          - { build: 'autotools', sys: 'mingw64', env: 'x86_64'      , tflags: 'skiprun'                 , config: '--enable-debug --disable-threaded-resolver --disable-curldebug --enable-static=no --without-zlib', name: 'default' }
198          - { build: 'autotools', sys: 'mingw64', env: 'x86_64'      , tflags: '~472 ~1299 ~1613'        , config: '--enable-debug --enable-windows-unicode --enable-ares', name: 'c-ares U' }
199          # FIXME: WebSockets test results ignored due to frequent failures on native Windows:
200          - { build: 'cmake'    , sys: 'mingw64', env: 'x86_64'      , tflags: '~2301 ~2302'             , config: '-DENABLE_DEBUG=ON  -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_ARES=ON', type: 'Debug', name: 'schannel c-ares U' }
201          - { build: 'cmake'    , sys: 'ucrt64' , env: 'ucrt-x86_64' , tflags: 'skiprun'                 , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON  -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_CURLDEBUG=ON', type: 'Release', name: 'schannel R TrackMemory' }
202          - { build: 'cmake'    , sys: 'clang64', env: 'clang-x86_64', tflags: 'skiprun'                 , config: '-DENABLE_DEBUG=ON  -DBUILD_SHARED_LIBS=OFF -DCURL_USE_OPENSSL=ON  -DENABLE_UNICODE=OFF', type: 'Release', name: 'openssl' }
203          - { build: 'cmake'    , sys: 'mingw64', env: 'x86_64'      , tflags: 'skiprun'                 , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON  -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON', type: 'Release', test: 'uwp', name: 'schannel R' }
204          - { build: 'cmake'    , sys: 'mingw64', env: 'x86_64'      , tflags: 'skiprun'                 , config: '-DENABLE_DEBUG=ON  -DBUILD_SHARED_LIBS=ON  -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DCMAKE_VERBOSE_MAKEFILE=ON', type: 'Debug', cflags: '-DCURL_SCHANNEL_DEV_DEBUG', name: 'schannel dev debug' }
205          - { build: 'cmake'    , sys: 'mingw32', env: 'i686'        , tflags: 'skiprun'                 , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON  -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON', type: 'Release', name: 'schannel R' }
206      fail-fast: false
207    steps:
208      - run: git config --global core.autocrlf input
209        shell: pwsh
210
211      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
212
213      - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # v2
214        if: ${{ matrix.sys == 'msys' }}
215        with:
216          msystem: ${{ matrix.sys }}
217          # https://packages.msys2.org/search
218          install: >-
219            gcc
220            ${{ matrix.build }} ${{ matrix.build == 'autotools' && 'make' || 'ninja' }}
221            openssh
222            openssl-devel
223            zlib-devel
224            brotli-devel
225            libnghttp2-devel
226            libpsl-devel
227            libssh2-devel
228
229      - uses: msys2/setup-msys2@ddf331adaebd714795f1042345e6ca57bd66cea8 # v2
230        if: ${{ matrix.sys != 'msys' }}
231        with:
232          msystem: ${{ matrix.sys }}
233          install: >-
234            mingw-w64-${{ matrix.env }}-cc
235            mingw-w64-${{ matrix.env }}-${{ matrix.build }} ${{ matrix.build == 'autotools' && 'make' || '' }}
236            openssh
237            mingw-w64-${{ matrix.env }}-openssl
238            mingw-w64-${{ matrix.env }}-libssh2
239            mingw-w64-${{ matrix.env }}-libpsl
240            mingw-w64-${{ matrix.env }}-c-ares
241
242      - name: 'autotools autoreconf'
243        if: ${{ matrix.build == 'autotools' }}
244        timeout-minutes: 2
245        run: autoreconf -fi
246
247      - name: 'autotools configure'
248        if: ${{ matrix.build == 'autotools' }}
249        timeout-minutes: 5
250        run: |
251          mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
252            --prefix="${HOME}"/install \
253            --with-openssl \
254            --with-libssh2 \
255            --disable-dependency-tracking \
256            ${{ matrix.config }}
257
258      - name: 'autotools configure log'
259        if: ${{ matrix.build == 'autotools' && !cancelled() }}
260        run: cat bld/config.log 2>/dev/null || true
261
262      - name: 'curl_config.h'
263        if: ${{ matrix.build == 'autotools' }}
264        run: |
265          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
266          grep -F '#define' bld/lib/curl_config.h | sort || true
267
268      - name: 'autotools build'
269        if: ${{ matrix.build == 'autotools' }}
270        timeout-minutes: 10
271        run: make -C bld -j5 V=1 install
272
273      - name: 'curl version'
274        if: ${{ matrix.build == 'autotools' }}
275        timeout-minutes: 1
276        run: |
277          # avoid libtool's curl.exe wrapper
278          mv bld/src/.libs/curl.exe bld/src/curl.exe
279          mv bld/lib/.libs/*.dll bld/src || true
280          find . -name '*.exe' -o -name '*.dll'
281          bld/src/curl.exe --disable --version
282
283      - name: 'autotools build tests'
284        if: ${{ matrix.build == 'autotools' && matrix.tflags != 'skipall' }}
285        timeout-minutes: 10
286        run: make -C bld -j5 V=1 -C tests
287
288      - name: 'install test prereqs'
289        if: ${{ matrix.build == 'autotools' && matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
290        timeout-minutes: 5
291        run: |
292          /c/ProgramData/chocolatey/choco.exe install --yes --no-progress --limit-output --timeout 180 --force stunnel || true
293          curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 60 --retry 3 https://live.sysinternals.com/handle64.exe --output /bin/handle64.exe
294
295      - name: 'autotools run tests'
296        if: ${{ matrix.build == 'autotools' && matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
297        timeout-minutes: 10
298        run: |
299          export TFLAGS='-j8 ${{ matrix.tflags }} ~SCP'
300          if [ '${{ matrix.sys }}' != 'msys' ]; then
301            TFLAGS+=' ~2301 ~2302'  # WebSockets'
302            TFLAGS+=' ~612 ~613 ~616 ~618'  # SFTP
303          else
304            TFLAGS+=' ~SFTP'
305          fi
306          if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
307            TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
308          fi
309          PATH="$PATH:/c/Program Files (x86)/stunnel/bin"
310          make -C bld -j5 V=1 test-ci
311
312      - name: 'autotools build examples'
313        if: ${{ matrix.build == 'autotools' && (matrix.tflags == 'skipall' || matrix.tflags == 'skiprun') }}
314        timeout-minutes: 5
315        run: make -C bld -j5 V=1 examples
316
317      - name: 'cmake configure'
318        if: ${{ matrix.build == 'cmake' }}
319        timeout-minutes: 5
320        run: |
321          if [[ '${{ matrix.env }}' = 'clang'* ]]; then
322            options='-DCMAKE_C_COMPILER=clang'
323          else
324            options='-DCMAKE_C_COMPILER=gcc'
325          fi
326          if [ '${{ matrix.test }}' = 'uwp' ]; then
327            options+=' -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0'
328            pacman --noconfirm --ask 20 --noprogressbar --sync --needed 'mingw-w64-${{ matrix.env }}-winstorecompat-git'
329            specs="$(realpath gcc-specs-uwp)"
330            gcc -dumpspecs | sed -e 's/-lmingwex/-lwindowsapp -lmingwex -lwindowsapp -lwindowsappcompat/' -e 's/-lmsvcrt/-lmsvcr120_app/' > "${specs}"
331            cflags="-specs=$(cygpath -w "${specs}") -DWINSTORECOMPAT -DWINAPI_FAMILY=WINAPI_FAMILY_APP"
332            # CMake (as of v3.26.4) gets confused and applies the MSVC rc.exe command-line
333            # template to windres. Reset it to the windres template manually:
334            rcopts='<CMAKE_RC_COMPILER> -O coff <DEFINES> <INCLUDES> <FLAGS> <SOURCE> <OBJECT>'
335          else
336            rcopts=''
337          fi
338          [ '${{ matrix.type }}' = 'Debug' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
339          [ '${{ matrix.type }}' = 'Release' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
340          cmake -B bld -G Ninja ${options} \
341            "-DCMAKE_C_FLAGS=${{ matrix.cflags }} ${cflags}" \
342            "-DCMAKE_RC_COMPILE_OBJECT=${rcopts}" \
343            '-DCMAKE_BUILD_TYPE=${{ matrix.type }}' \
344            -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
345            -DCURL_WERROR=ON \
346            -DCURL_BROTLI=ON \
347            ${{ matrix.config }}
348
349      - name: 'cmake configure log'
350        if: ${{ matrix.build == 'cmake' && !cancelled() }}
351        run: cat bld/CMakeFiles/CMake*.yaml 2>/dev/null || true
352
353      - name: 'curl_config.h'
354        if: ${{ matrix.build == 'cmake' }}
355        run: |
356          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
357          grep -F '#define' bld/lib/curl_config.h | sort || true
358
359      - name: 'cmake build'
360        if: ${{ matrix.build == 'cmake' }}
361        timeout-minutes: 10
362        run: cmake --build bld --config '${{ matrix.type }}'
363
364      - name: 'curl version'
365        if: ${{ matrix.build == 'cmake' }}
366        timeout-minutes: 1
367        run: |
368          find . -name '*.exe' -o -name '*.dll'
369          if [ '${{ matrix.test }}' != 'uwp' ]; then  # UWP missing 'msvcr120_app.dll', fails with exit code 0xc0000135
370            PATH="$PWD/bld/lib:$PATH"
371            bld/src/curl.exe --disable --version
372          fi
373
374      - name: 'cmake build tests'
375        if: ${{ matrix.build == 'cmake' && matrix.tflags != 'skipall' }}
376        timeout-minutes: 10
377        run: cmake --build bld --config '${{ matrix.type }}' --target testdeps
378
379      - name: 'install test prereqs'
380        if: ${{ matrix.build == 'cmake' && matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
381        timeout-minutes: 5
382        run: |
383          /c/ProgramData/chocolatey/choco.exe install --yes --no-progress --limit-output --timeout 180 --force stunnel || true
384          curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 60 --retry 3 https://live.sysinternals.com/handle64.exe --output /bin/handle64.exe
385
386      - name: 'cmake run tests'
387        if: ${{ matrix.build == 'cmake' && matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
388        timeout-minutes: 10
389        run: |
390          export TFLAGS='-j8 ${{ matrix.tflags }} ~SCP'
391          if [ '${{ matrix.sys }}' != 'msys' ]; then
392            TFLAGS+=' ~WebSockets'
393            TFLAGS+=' ~612 ~613 ~616 ~618'  # SFTP
394          else
395            TFLAGS+=' ~SFTP'
396          fi
397          if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
398            TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
399          fi
400          PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin"
401          cmake --build bld --config '${{ matrix.type }}' --target test-ci
402
403      - name: 'cmake build examples'
404        if: ${{ matrix.build == 'cmake' }}
405        timeout-minutes: 5
406        run: cmake --build bld --config '${{ matrix.type }}' --target curl-examples
407
408  old-mingw-w64:
409    name: 'old-mingw, CM ${{ matrix.env }} ${{ matrix.name }}'
410    runs-on: windows-latest
411    timeout-minutes: 30
412    defaults:
413      run:
414        shell: C:\msys64\usr\bin\bash.exe {0}
415    strategy:
416      matrix:
417        include:
418          - name: 'schannel'
419            env: '9.5.0-x86_64'
420            dir: 'mingw64'
421            url: 'https://github.com/brechtsanders/winlibs_mingw/releases/download/9.5.0-10.0.0-msvcrt-r1/winlibs-x86_64-posix-seh-gcc-9.5.0-mingw-w64msvcrt-10.0.0-r1.7z'
422            config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=OFF'
423            type: 'Release'
424            tflags: '~2301 ~2302 ~3027'
425          - name: 'schannel U'
426            env: '7.3.0-x86_64'
427            dir: 'mingw64'
428            url: 'https://downloads.sourceforge.net/mingw-w64/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/7.3.0/threads-win32/seh/x86_64-7.3.0-release-win32-seh-rt_v5-rev0.7z'
429            config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON'
430            type: 'Release'
431            tflags: '~2301 ~2302 ~3027 ~3023 ~3024 ~1451'
432          - name: 'schannel !unity'
433            env: '6.4.0-i686'
434            dir: 'mingw32'
435            url: 'https://downloads.sourceforge.net/mingw-w64/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/6.4.0/threads-win32/dwarf/i686-6.4.0-release-win32-dwarf-rt_v5-rev0.7z'
436            config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=OFF -DCMAKE_UNITY_BUILD=OFF'
437            type: 'Debug'
438            tflags: 'skiprun'
439      fail-fast: false
440    steps:
441      - name: 'cache compiler (gcc ${{ matrix.env }})'
442        uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4
443        id: cache-compiler
444        with:
445          path: ~\my-cache
446          key: ${{ runner.os }}-mingw-w64-${{ matrix.env }}
447
448      - name: 'install compiler (gcc ${{ matrix.env }})'
449        if: ${{ steps.cache-compiler.outputs.cache-hit != 'true' }}
450        timeout-minutes: 5
451        run: |
452          cd "${USERPROFILE}" || exit 1
453          mkdir my-cache
454          cd my-cache || exit 1
455          curl --fail --silent --show-error --retry 3 --retry-connrefused --output pack.bin --location --proto-redir =https '${{ matrix.url }}'
456          pwd
457          7z x -y pack.bin >/dev/null
458          rm -r -f pack.bin
459          ls -l
460
461      - run: git config --global core.autocrlf input
462      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
463
464      - name: 'cmake configure'
465        timeout-minutes: 5
466        run: |
467          PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
468          [ '${{ matrix.type }}' = 'Debug' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
469          [ '${{ matrix.type }}' = 'Release' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
470          cmake -B bld -G 'MSYS Makefiles' ${options} \
471            -DCMAKE_C_COMPILER=gcc \
472            '-DCMAKE_BUILD_TYPE=${{ matrix.type }}' \
473            -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
474            -DCURL_WERROR=ON \
475            -DCURL_USE_LIBPSL=OFF \
476            ${{ matrix.config }}
477
478      - name: 'cmake configure log'
479        if: ${{ !cancelled() }}
480        run: cat bld/CMakeFiles/CMake*.yaml 2>/dev/null || true
481
482      - name: 'curl_config.h'
483        run: |
484          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
485          grep -F '#define' bld/lib/curl_config.h | sort || true
486
487      - name: 'cmake build'
488        timeout-minutes: 5
489        run: |
490          PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
491          cmake --build bld --config '${{ matrix.type }}' --parallel 5
492
493      - name: 'curl version'
494        timeout-minutes: 1
495        run: |
496          PATH=/usr/bin find . -name '*.exe' -o -name '*.dll'
497          PATH="$PWD/bld/lib:$PATH"
498          bld/src/curl.exe --disable --version
499
500      - name: 'cmake build tests'
501        if: ${{ matrix.tflags != 'skipall' }}
502        timeout-minutes: 10
503        run: |
504          PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
505          cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target testdeps
506
507      - name: 'install test prereqs'
508        if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
509        timeout-minutes: 5
510        run: |
511          /c/ProgramData/chocolatey/choco.exe install --yes --no-progress --limit-output --timeout 180 --force stunnel || true
512          curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 60 --retry 3 https://live.sysinternals.com/handle64.exe --output /bin/handle64.exe
513          python3 -m pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary impacket
514
515      - name: 'cmake run tests'
516        if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
517        timeout-minutes: 10
518        run: |
519          PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
520          export TFLAGS='-j4 ~WebSockets ${{ matrix.tflags }}'
521          if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
522            TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
523          fi
524          PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin"
525          cmake --build bld --config '${{ matrix.type }}' --target test-ci
526
527      - name: 'cmake build examples'
528        timeout-minutes: 5
529        run: |
530          PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
531          cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target curl-examples
532
533  linux-cross-mingw-w64:
534    name: "linux-mingw, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }}"
535    runs-on: ubuntu-latest
536    timeout-minutes: 15
537    strategy:
538      fail-fast: false
539      matrix:
540        build: [autotools, cmake]
541        compiler: [gcc]
542    env:
543      TRIPLET: 'x86_64-w64-mingw32'
544    steps:
545      - name: 'install packages'
546        run: sudo apt-get --quiet 2 --option Dpkg::Use-Pty=0 install mingw-w64 ${{ matrix.build == 'cmake' && 'ninja-build' || '' }}
547
548      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
549
550      - name: 'autotools autoreconf'
551        if: ${{ matrix.build == 'autotools' }}
552        run: autoreconf -fi
553
554      - name: 'autotools configure'
555        if: ${{ matrix.build == 'autotools' }}
556        run: |
557          mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
558            --host=${TRIPLET} \
559            --with-schannel --with-winidn \
560            --without-libpsl \
561            --disable-dependency-tracking
562
563      - name: 'autotools configure log'
564        if: ${{ matrix.build == 'autotools' && !cancelled() }}
565        run: cat bld/config.log 2>/dev/null || true
566
567      - name: 'curl_config.h'
568        if: ${{ matrix.build == 'autotools' }}
569        run: |
570          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
571          grep -F '#define' bld/lib/curl_config.h | sort || true
572
573      - name: 'autotools build'
574        if: ${{ matrix.build == 'autotools' }}
575        run: make -C bld -j5
576
577      - name: 'autotools build examples'
578        if: ${{ matrix.build == 'autotools' }}
579        run: make -C bld -j5 examples
580
581      - name: 'cmake configure'
582        if: ${{ matrix.build == 'cmake' }}
583        run: |
584          cmake -B bld -G Ninja \
585            -DCMAKE_SYSTEM_NAME=Windows \
586            -DCMAKE_C_COMPILER_TARGET=${TRIPLET} \
587            -DCMAKE_C_COMPILER=${TRIPLET}-gcc \
588            -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
589            -DCURL_WERROR=ON \
590            -DCURL_USE_SCHANNEL=ON -DUSE_WIN32_IDN=ON \
591            -DCURL_USE_LIBPSL=OFF
592
593      - name: 'cmake configure log'
594        if: ${{ matrix.build == 'cmake' && !cancelled() }}
595        run: cat bld/CMakeFiles/CMake*.yaml 2>/dev/null || true
596
597      - name: 'curl_config.h'
598        if: ${{ matrix.build == 'cmake' }}
599        run: |
600          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
601          grep -F '#define' bld/lib/curl_config.h | sort || true
602
603      - name: 'cmake build'
604        if: ${{ matrix.build == 'cmake' }}
605        run: cmake --build bld
606
607      - name: 'cmake build tests'
608        if: ${{ matrix.build == 'cmake' }}
609        run: cmake --build bld --target testdeps
610
611      - name: 'cmake build examples'
612        if: ${{ matrix.build == 'cmake' }}
613        run: cmake --build bld --target curl-examples
614
615  msvc:
616    name: 'msvc, CM ${{ matrix.arch }}-${{ matrix.plat }} ${{ matrix.name }}'
617    runs-on: windows-latest
618    timeout-minutes: 55
619    defaults:
620      run:
621        shell: C:\msys64\usr\bin\bash.exe {0}
622    env:
623      VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite'
624      VCPKG_DISABLE_METRICS: '1'
625    strategy:
626      matrix:
627        include:
628          - name: 'schannel MultiSSL U'
629            install: 'brotli zlib zstd libpsl nghttp2 libssh2[core,zlib] pkgconf gsasl openssl mbedtls'
630            arch: 'x64'
631            plat: 'windows'
632            type: 'Debug'
633            tflags: '~1516 ~2301 ~2302 ~2303 ~2307'
634            config: >-
635              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=ON
636              -DCURL_USE_SCHANNEL=ON  -DCURL_USE_OPENSSL=ON -DCURL_USE_MBEDTLS=ON -DCURL_DEFAULT_SSL_BACKEND=schannel
637              -DCURL_USE_GSASL=ON -DUSE_WIN32_IDN=ON -DENABLE_UNICODE=ON
638
639          - name: 'openssl'
640            install: 'brotli zlib zstd libpsl nghttp2 nghttp3 openssl libssh2 pkgconf gsasl c-ares libuv'
641            arch: 'x64'
642            plat: 'windows'
643            type: 'Debug'
644            tflags: '~1516 ~2301 ~2302 ~2303 ~2307'
645            config: >-
646              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=ON
647              -DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON
648              -DCURL_USE_GSASL=ON -DENABLE_ARES=ON -DCURL_USE_LIBUV=ON
649
650          - name: 'openssl'
651            install: 'brotli zlib zstd        nghttp2 nghttp3 openssl libssh2'
652            arch: 'x64'
653            plat: 'uwp'
654            type: 'Debug'
655            tflags: 'skiprun'
656            config: >-
657              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=ON
658              -DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON
659              -DCURL_USE_LIBPSL=OFF
660
661          - name: 'libressl'
662            install: 'brotli zlib zstd libpsl nghttp2 libressl libssh2[core,zlib] pkgconf ngtcp2[libressl] nghttp3'
663            arch: 'x64'
664            plat: 'windows'
665            type: 'Debug'
666            tflags: '~1516 ~2301 ~2302 ~2303 ~2307'
667            config: >-
668              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=ON
669              -DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_NGTCP2=ON
670              -DCURL_CA_SEARCH_SAFE=ON
671
672          - name: 'boringssl-ECH'
673            install: 'brotli zlib zstd libpsl nghttp2 boringssl libssh2[core,zlib]'
674            arch: 'x64'
675            plat: 'windows'
676            type: 'Debug'
677            tflags: '~1516 ~2301 ~2302 ~2303 ~2307'
678            config: >-
679              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=ON
680              -DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON
681              -DUSE_HTTPSRR=ON -DUSE_ECH=ON
682
683          - name: 'wolfssl'
684            install: 'brotli zlib zstd libpsl nghttp2 wolfssl libssh2 pkgconf gsasl ngtcp2[wolfssl] nghttp3'
685            arch: 'x64'
686            plat: 'windows'
687            type: 'Debug'
688            tflags: '~1516'
689            config: >-
690              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=ON
691              -DCURL_USE_SCHANNEL=OFF -DCURL_USE_WOLFSSL=ON -DUSE_NGTCP2=ON
692              -DCURL_USE_GSASL=ON
693
694          - name: 'mbedtls'
695            install: 'brotli zlib zstd libpsl nghttp2 mbedtls libssh pkgconf gsasl'
696            arch: 'x64'
697            plat: 'windows'
698            type: 'Debug'
699            tflags: '~1516'
700            # WARNING: libssh uses hard-coded world-writable paths (/etc/..., ~/.ssh/) to
701            #          read its configuration from, making it vulnerable to attacks on
702            #          Windows. Do not use this component till there is a fix for these.
703            # https://github.com/curl/curl-for-win/blob/3951808deb04df9489ee17430f236ed54436f81a/libssh.sh#L6-L8
704            config: >-
705              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON
706              -DCURL_USE_SCHANNEL=OFF -DCURL_USE_MBEDTLS=ON
707              -DCURL_USE_GSASL=ON
708
709          - name: 'msh3'
710            install: 'brotli zlib zstd libpsl nghttp2 msh3 libssh2 pkgconf gsasl'
711            arch: 'x64'
712            plat: 'windows'
713            type: 'Debug'
714            tflags: 'skipall'
715            config: >-
716              -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_USE_LIBSSH2=ON
717              -DCURL_USE_SCHANNEL=OFF -DUSE_MSH3=ON
718              -DCURL_USE_GSASL=ON
719
720      fail-fast: false
721    steps:
722      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
723
724      - name: 'vcpkg cache setup'
725        uses: actions/github-script@v7
726        with:
727          script: |
728            core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
729            core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
730
731      - name: 'vcpkg versions'
732        timeout-minutes: 1
733        run: |
734          git -C "$VCPKG_INSTALLATION_ROOT" show --no-patch --format='%H %ai'
735          vcpkg version
736
737      - name: 'vcpkg build'
738        timeout-minutes: 35
739        run: vcpkg x-set-installed ${{ matrix.install }} '--triplet=${{ matrix.arch }}-${{ matrix.plat }}'
740
741      - name: 'cmake configure'
742        timeout-minutes: 5
743        run: |
744          PATH="/c/msys64/usr/bin:$PATH"
745          cmake -B bld ${options} \
746            "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" \
747            "-DVCPKG_INSTALLED_DIR=$VCPKG_INSTALLATION_ROOT/installed" \
748            '-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-${{ matrix.plat }}' \
749            -DCMAKE_VS_GLOBALS=TrackFileAccess=false \
750            '-DCMAKE_BUILD_TYPE=${{ matrix.type }}' \
751            -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
752            -DCURL_WERROR=ON \
753            -DBUILD_SHARED_LIBS=OFF \
754            -DENABLE_DEBUG=ON \
755            -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
756            -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE= \
757            ${{ matrix.config }}
758
759      - name: 'cmake configure log'
760        if: ${{ !cancelled() }}
761        run: cat bld/CMakeFiles/CMake*.yaml 2>/dev/null || true
762
763      - name: 'curl_config.h'
764        run: |
765          echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
766          grep -F '#define' bld/lib/curl_config.h | sort || true
767
768      - name: 'cmake build'
769        timeout-minutes: 5
770        run: |
771          PATH="/c/msys64/usr/bin:$PATH"
772          cmake --build bld --config '${{ matrix.type }}' --parallel 5
773
774      - name: 'curl version'
775        timeout-minutes: 1
776        run: |
777          find . -name '*.exe' -o -name '*.dll'
778          if [ '${{ matrix.plat }}' != 'uwp' ]; then
779            PATH="$PWD/bld/lib:$PATH"
780            bld/src/curl.exe --disable --version
781          fi
782
783      - name: 'cmake build tests'
784        if: ${{ matrix.tflags != 'skipall' }}
785        timeout-minutes: 10
786        run: |
787          PATH="/c/msys64/usr/bin:$PATH"
788          cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target testdeps
789
790      - name: 'install test prereqs'
791        if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
792        timeout-minutes: 5
793        run: |
794          # GnuTLS is not fully functional on Windows, so skip the tests
795          # https://github.com/ShiftMediaProject/gnutls/issues/23
796          if [[ '${{ matrix.name }}' != *'gnutls'* ]]; then
797            /c/ProgramData/chocolatey/choco.exe install --yes --no-progress --limit-output --timeout 180 --force stunnel openssh || true
798          fi
799          curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 60 --retry 3 https://live.sysinternals.com/handle64.exe --output /bin/handle64.exe
800          python3 -m pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary impacket
801
802      - name: 'cmake run tests'
803        if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
804        timeout-minutes: 10
805        run: |
806          export TFLAGS='-j8 ~WebSockets ~SCP ~612 ${{ matrix.tflags }}'
807          if [[ '${{ matrix.install }}' = *'libssh2[core,zlib]'* ]]; then
808            TFLAGS+=' ~SFTP'
809          elif [[ '${{ matrix.install }}' = *'libssh '* ]]; then
810            TFLAGS+=' ~614'  # 'SFTP pre-quote chmod' SFTP, pre-quote, directory
811          fi
812          PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin:/c/Program Files/OpenSSH-Win64"
813          PATH="/c/msys64/usr/bin:$PATH"
814          cmake --build bld --config '${{ matrix.type }}' --target test-ci
815
816      - name: 'cmake build examples'
817        timeout-minutes: 5
818        run: |
819          PATH="/c/msys64/usr/bin:$PATH"
820          cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target curl-examples
821