botan icon indicating copy to clipboard operation
botan copied to clipboard

CI: Use GitHub Actions for Windows builds

Open reneme opened this issue 1 year ago • 9 comments

Description

This did escalate quite a bit from "just adding windows" to "overhauling the CI". So please don't hesitate to call me out for going too far with it. I'm using the opportunity to do a deep-dive on GitHub Actions and splitting this up into several PRs or rolling back most of the changes shouldn't be too hard.

As a side-note: While experimenting, I found a few buggy build configurations and documented them below. I would suggest to keep them in mind and fix them after this is integrated.

The pipeline as it is now should provide at least as much coverage as before, plus some extra configurations. Some new bits and pieces bump the minimal requirements up, though. Below is an overview:

Requirements

  • Boost 1.69 (released on christmas 2018)

    • no more linking of libboost_system (header-only as of 1.69)
  • Visual Studio 2019

    • because of /external:I
  • Not sure about clang's --system-header-prefix=

    • though that is only used in the CI not in production

Build Configurations

Basic Matrices

  • Windows 32-Bit/64-Bit, Linux, macOS
  • static, shared, amalgamation
  • including most external dependency integrations on all platforms (particularly boost)
  • some configs are disabled (see "Build Failures" below)

Specials and Metrics

  • coverage build (with basically everything included)
  • MinGW smoke test
  • sanitizer (windows)
  • minimized
  • bsi
  • fuzzers
  • valgrind
  • emscripten
  • baremetal
  • lint

Cross-Compilation

  • same configurations as before

Components

setup_gh_actions.ps1/sh

This didn't change much. The windows flavour of the script basically just installs jom and sccache. One thing was added: The scripts now find out where the compiler cache is located and communicates this upstream via an environment variable. Hence, no more hard-coded cache paths in actions/cache.

setup_gh_actions_after_vsvars.ps1

A new script installing 3rd-party dependencies via nuget (is there a better way?) after the Visual Studio environment was set up. That setup should also facilitate caching the windows dependencies, as nuget takes like 4 to 5 minutes to install boost. -.-

Multiple Matrices

Windows brought more complexity into the ci.yml than expected. Mainly due to platform-dependent setup steps, handling vcvarsall.bat, extra build configuration variables (make_tool, arch) and their inter-dependency. Also the list of build configurations became hard to grasp, so I grouped the configurations into several build matrices. As a side effect, we can now actually use the "matrix" feature effectively. E.g. to build static, shared and amalgamation on all major platforms.

Custom Actions

VS-Shell

This is a small 3rd-party action by @egor-tensin. I figured that it would be easier to copy the code and adapt it here, instead of relying on the 3rd-party repo. It basically locates vsvarsall.bat and slurps it into the build agent's environment. Currently, the newest Visual Studio version available is selected. Though, it should be extensible to configure older VS versions as well.

Setup Build Agent

This is a tiny custom action that I extracted to re-use the platform dependent agent setup steps. Mainly, it takes care of interacting with the setup_gh_actions script, set up compiler caching and calling VS-Shell (see above) on Windows.

ci_build.py

As the only new thing, this script can now auto-detect sccache on Windows machines.

Production Code Changes

To make this compile, a few changes to the production code were required. Most notably, the boost module does not link against libboost_system anymore. This boost library is effectively header-only since Boost 1.69 and only shipped with an empty compatibity library we were linking against. For reference: Boost 1.69 was released in the end of 2018 making this effectively the oldest supported version.

Build Infrastructure Changes

This introduces a notion of "system headers" (-isystem on gcc/clang and /external:I on msvc). That way, we can suppress warnings in external header files like boost.

TODO

  • [x] Remove trailing dash from cache restore key
  • [x] Make sure Boost works on windows
  • [x] Add older versions of Visual Studio to the pipeline
  • [x] Clean-up the commit history
  • [x] Sunset AppVeyor

TODO -- Build Failures in Specific Configurations

Nice to have

  • [ ] Clang sanitizers
  • [ ] Custom error/warning messages in the Checks summary
  • [x] Maybe group individual build jobs
    • e.g. "standard builds" (static, shared, amalg.), "analysis" (coverage, static analy. linting, ...), "cross compilation"
  • [ ] Maybe have a "smoke test" stage run first, and deeper analysis later, to save on free-tier GitHub runners?
  • [ ] Cache installed dependency (particularly nuget install boost takes long)

reneme avatar Jul 15 '22 15:07 reneme

Giving up for today.

Current problem: The shell that executes ci_build.py does not have the Visual Studio vcvarsall.bat context. Hence, cl.exe is not found and the build fails.

There's a third-party action to pull the Visual Studio context into the GH Actions workflow (ilammy/msvc-dev-cmd), but this repo's security settingr prevent it from running. I tried it in the R&S fork and it worked well.

Nevertheless, I'm all in favor of pulling in as little 3rdparty code as possible. Will look into this next week. Frankly, I think its terrible that Microsoft's GitHub Actions make it so hard to compile stuff with MSVC. :(

reneme avatar Jul 15 '22 16:07 reneme

Thanks for looking into this. AppVeyor's serial execution really hurts CI times and as a result over time the number of Windows configurations being tested has been pruned.

randombit avatar Jul 15 '22 22:07 randombit

Codecov Report

Merging #3007 (34d26ab) into master (c6870fe) will decrease coverage by 0.01%. The diff coverage is n/a.

:exclamation: Current head 34d26ab differs from pull request most recent head ae97dff. Consider uploading reports for the commit ae97dff to get more accurate results

@@            Coverage Diff             @@
##           master    #3007      +/-   ##
==========================================
- Coverage   92.62%   92.60%   -0.02%     
==========================================
  Files         596      596              
  Lines       69776    69776              
  Branches     6614     6614              
==========================================
- Hits        64627    64616      -11     
- Misses       5116     5127      +11     
  Partials       33       33              
Impacted Files Coverage Δ
src/lib/utils/cpuid/cpuid_x86.cpp 76.62% <0.00%> (-11.69%) :arrow_down:
src/lib/pubkey/elgamal/elgamal.cpp 95.94% <0.00%> (-1.36%) :arrow_down:
src/lib/pubkey/mce/mceliece_key.cpp 83.24% <0.00%> (-1.05%) :arrow_down:
src/lib/tls/tls12/tls_channel_impl_12.cpp 89.33% <0.00%> (+0.28%) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update c6870fe...ae97dff. Read the comment docs.

codecov-commenter avatar Jul 18 '22 16:07 codecov-commenter

This is getting to a state where some feedback would be appreciated. :) Cleanup still needs to be done and the last configurations still need some T.L.C, but I'm confident that this is now converging and provides at least as much coverage as before. As mentioned above: I think it isn't a big deal to pull those changes apart into multiple patches.

reneme avatar Jul 19 '22 15:07 reneme

@reneme Sounds good. Please split into 3 PRs as you outlined.

randombit avatar Jul 20 '22 15:07 randombit

@randombit This is now based on #3010 and #3011. Note that I integrated the changes in my self-review into the respective commits.

reneme avatar Jul 20 '22 17:07 reneme

Rebased to master to pick up the emscripten fix.

reneme avatar Jul 29 '22 09:07 reneme

Rebased to master to pick up the emscripten fix.

reneme avatar Jul 29 '22 09:07 reneme