name: CI on: pull_request: push: branches: - '**' tags-ignore: - '**' concurrency: group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }} cancel-in-progress: true env: ### compiler options HOST: WRAPPER_CMD: # Specific warnings can be disabled with -Wno-error=foo. # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. WERROR_CFLAGS: '-Werror -pedantic-errors' MAKEFLAGS: '-j4' BUILD: 'check' ### secp256k1 config ECMULTWINDOW: 'auto' ECMULTGENPRECISION: 'auto' ASM: 'no' WIDEMUL: 'auto' WITH_VALGRIND: 'yes' EXTRAFLAGS: ### secp256k1 modules EXPERIMENTAL: 'no' ECDH: 'no' RECOVERY: 'no' SCHNORRSIG: 'no' ELLSWIFT: 'no' ### test options SECP256K1_TEST_ITERS: BENCH: 'yes' SECP256K1_BENCH_ITERS: 2 CTIMETESTS: 'yes' # Compile and run the examples. EXAMPLES: 'yes' jobs: docker_cache: name: "Build Docker image" runs-on: ubuntu-latest steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: # See: https://github.com/moby/buildkit/issues/3969. driver-opts: | network=host - name: Build container uses: docker/build-push-action@v5 with: file: ./ci/linux-debian.Dockerfile tags: linux-debian-image cache-from: type=gha cache-to: type=gha,mode=min linux_debian: name: "x86_64: Linux (Debian stable)" runs-on: ubuntu-latest needs: docker_cache strategy: fail-fast: false matrix: configuration: - env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' } - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - env_vars: { WIDEMUL: 'int128' } - env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' } - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes' } - env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' } - env_vars: { RECOVERY: 'yes', SCHNORRSIG: 'yes' } - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', CPPFLAGS: '-DVERIFY' } - env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' } - env_vars: { CPPFLAGS: '-DDETERMINISTIC' } - env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' } - env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - env_vars: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - env_vars: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 } cc: - 'gcc' - 'clang' - 'gcc-snapshot' - 'clang-snapshot' env: CC: ${{ matrix.cc }} steps: - name: Checkout uses: actions/checkout@v4 - name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} i686_debian: name: "i686: Linux (Debian stable)" runs-on: ubuntu-latest needs: docker_cache strategy: fail-fast: false matrix: cc: - 'i686-linux-gnu-gcc' - 'clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include' env: HOST: 'i686-linux-gnu' ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CC: ${{ matrix.cc }} steps: - name: Checkout uses: actions/checkout@v4 - name: CI script uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} s390x_debian: name: "s390x (big-endian): Linux (Debian stable, QEMU)" runs-on: ubuntu-latest needs: docker_cache env: WRAPPER_CMD: 'qemu-s390x' SECP256K1_TEST_ITERS: 16 HOST: 's390x-linux-gnu' WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} arm32_debian: name: "ARM32: Linux (Debian stable, QEMU)" runs-on: ubuntu-latest needs: docker_cache strategy: fail-fast: false matrix: configuration: - env_vars: {} - env_vars: { EXPERIMENTAL: 'yes', ASM: 'arm32' } env: WRAPPER_CMD: 'qemu-arm' SECP256K1_TEST_ITERS: 16 HOST: 'arm-linux-gnueabihf' WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} arm64_debian: name: "ARM64: Linux (Debian stable, QEMU)" runs-on: ubuntu-latest needs: docker_cache env: WRAPPER_CMD: 'qemu-aarch64' SECP256K1_TEST_ITERS: 16 HOST: 'aarch64-linux-gnu' WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' strategy: fail-fast: false matrix: configuration: - env_vars: { } # gcc - env_vars: # clang CC: 'clang --target=aarch64-linux-gnu' - env_vars: # clang-snapshot CC: 'clang-snapshot --target=aarch64-linux-gnu' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} ppc64le_debian: name: "ppc64le: Linux (Debian stable, QEMU)" runs-on: ubuntu-latest needs: docker_cache env: WRAPPER_CMD: 'qemu-ppc64le' SECP256K1_TEST_ITERS: 16 HOST: 'powerpc64le-linux-gnu' WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} valgrind_debian: name: "Valgrind (memcheck)" runs-on: ubuntu-latest needs: docker_cache strategy: fail-fast: false matrix: configuration: - env_vars: { CC: 'clang', ASM: 'auto' } - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } env: # The `--error-exitcode` is required to make the test fail if valgrind found errors, # otherwise it will return 0 (https://www.valgrind.org/docs/manual/manual-core.html). WRAPPER_CMD: 'valgrind --error-exitcode=42' ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' SECP256K1_TEST_ITERS: 2 steps: - name: Checkout uses: actions/checkout@v4 - name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} sanitizers_debian: name: "UBSan, ASan, LSan" runs-on: ubuntu-latest needs: docker_cache strategy: fail-fast: false matrix: configuration: - env_vars: { CC: 'clang', ASM: 'auto' } - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } env: ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' CFLAGS: '-fsanitize=undefined,address -g' UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1' ASAN_OPTIONS: 'strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1' LSAN_OPTIONS: 'use_unaligned=1' SECP256K1_TEST_ITERS: 32 steps: - name: Checkout uses: actions/checkout@v4 - name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} msan_debian: name: "MSan" runs-on: ubuntu-latest needs: docker_cache strategy: fail-fast: false matrix: configuration: - env_vars: CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g' - env_vars: ECMULTGENPRECISION: 2 ECMULTWINDOW: 2 CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g -O3' env: ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'yes' CC: 'clang' SECP256K1_TEST_ITERS: 32 ASM: 'no' WITH_VALGRIND: 'no' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} mingw_debian: name: ${{ matrix.configuration.job_name }} runs-on: ubuntu-latest needs: docker_cache env: WRAPPER_CMD: 'wine' WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' strategy: fail-fast: false matrix: configuration: - job_name: 'x86_64 (mingw32-w64): Windows (Debian stable, Wine)' env_vars: HOST: 'x86_64-w64-mingw32' - job_name: 'i686 (mingw32-w64): Windows (Debian stable, Wine)' env_vars: HOST: 'i686-w64-mingw32' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} macos-native: name: "x86_64: macOS Monterey" # See: https://github.com/actions/runner-images#available-images. runs-on: macos-12 # Use M1 once available https://github.com/github/roadmap/issues/528 env: CC: 'clang' HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1 strategy: fail-fast: false matrix: env_vars: - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } - { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } - BUILD: 'distcheck' steps: - name: Checkout uses: actions/checkout@v4 - name: Install Homebrew packages run: | brew install automake libtool gcc ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc - name: Install and cache Valgrind uses: ./.github/actions/install-homebrew-valgrind - name: CI script env: ${{ matrix.env_vars }} run: ./ci/ci.sh - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} win64-native: name: ${{ matrix.configuration.job_name }} # See: https://github.com/actions/runner-images#available-images. runs-on: windows-2022 strategy: fail-fast: false matrix: configuration: - job_name: 'x64 (MSVC): Windows (VS 2022, shared)' cmake_options: '-A x64 -DBUILD_SHARED_LIBS=ON' - job_name: 'x64 (MSVC): Windows (VS 2022, static)' cmake_options: '-A x64 -DBUILD_SHARED_LIBS=OFF' - job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct)' cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct' - job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh)' cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct' cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE' - job_name: 'x86 (MSVC): Windows (VS 2022)' cmake_options: '-A Win32' steps: - name: Checkout uses: actions/checkout@v4 - name: Generate buildsystem run: cmake -E env CFLAGS="/WX ${{ matrix.configuration.cpp_flags }}" cmake -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON ${{ matrix.configuration.cmake_options }} - name: Build run: cmake --build build --config RelWithDebInfo -- /p:UseMultiToolTask=true /maxCpuCount - name: Binaries info # Use the bash shell included with Git for Windows. shell: bash run: | cd build/src/RelWithDebInfo && file *tests.exe bench*.exe libsecp256k1-*.dll || true - name: Check run: | ctest -C RelWithDebInfo --test-dir build -j ([int]$env:NUMBER_OF_PROCESSORS + 1) build\src\RelWithDebInfo\bench_ecmult.exe build\src\RelWithDebInfo\bench_internal.exe build\src\RelWithDebInfo\bench.exe win64-native-headers: name: "x64 (MSVC): C++ (public headers)" # See: https://github.com/actions/runner-images#available-images. runs-on: windows-2022 steps: - name: Checkout uses: actions/checkout@v4 - name: Add cl.exe to PATH uses: ilammy/msvc-dev-cmd@v1 - name: C++ (public headers) run: | cl.exe -c -WX -TP include/*.h cxx_fpermissive_debian: name: "C++ -fpermissive (entire project)" runs-on: ubuntu-latest needs: docker_cache env: CC: 'g++' CFLAGS: '-fpermissive -g' CPPFLAGS: '-DSECP256K1_CPLUSPLUS_TEST_OVERRIDE' WERROR_CFLAGS: ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - run: cat tests.log || true if: ${{ always() }} - run: cat noverify_tests.log || true if: ${{ always() }} - run: cat exhaustive_tests.log || true if: ${{ always() }} - run: cat ctime_tests.log || true if: ${{ always() }} - run: cat bench.log || true if: ${{ always() }} - run: cat config.log || true if: ${{ always() }} - run: cat test_env.log || true if: ${{ always() }} - name: CI env run: env if: ${{ always() }} cxx_headers_debian: name: "C++ (public headers)" runs-on: ubuntu-latest needs: docker_cache steps: - name: Checkout uses: actions/checkout@v4 - name: CI script uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image command: | g++ -Werror include/*.h clang -Werror -x c++-header include/*.h sage: name: "SageMath prover" runs-on: ubuntu-latest container: image: sagemath/sagemath:latest options: --user root steps: - name: Checkout uses: actions/checkout@v4 - name: CI script run: | cd sage sage prove_group_implementations.sage release: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - run: ./autogen.sh && ./configure --enable-dev-mode && make distcheck - name: Check installation with Autotools env: CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install run: | ./autogen.sh && ./configure --prefix=${{ env.CI_INSTALL }} && make clean && make install && ls -RlAh ${{ env.CI_INSTALL }} gcc -o ecdsa examples/ecdsa.c $(PKG_CONFIG_PATH=${{ env.CI_INSTALL }}/lib/pkgconfig pkg-config --cflags --libs libsecp256k1) -Wl,-rpath,"${{ env.CI_INSTALL }}/lib" && ./ecdsa - name: Check installation with CMake env: CI_BUILD: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/build CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install run: | cmake -B ${{ env.CI_BUILD }} -DCMAKE_INSTALL_PREFIX=${{ env.CI_INSTALL }} && cmake --build ${{ env.CI_BUILD }} --target install && ls -RlAh ${{ env.CI_INSTALL }} gcc -o ecdsa examples/ecdsa.c -I ${{ env.CI_INSTALL }}/include -L ${{ env.CI_INSTALL }}/lib*/ -l secp256k1 -Wl,-rpath,"${{ env.CI_INSTALL }}/lib",-rpath,"${{ env.CI_INSTALL }}/lib64" && ./ecdsa