diff --git a/.codecov.yml b/.codecov.yml index 91866425b..2e9fff3f5 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -8,4 +8,4 @@ coverage: comment: layout: "diff" require_changes: true - after_n_builds: 4 # linux llvm-cov, linux arm64 llvm-cov, linux kcov, mac llvm-cov + after_n_builds: 5 # linux llvm-cov, linux arm64 llvm-cov, linux kcov, mac llvm-cov, windows clangcl llvm-cov diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e0f8ffac..7481b98da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,9 +196,10 @@ jobs: - name: Windows (latest, ninja + sccache) os: windows-latest USE_SCCACHE: 1 - - name: Windows ClangCL (2022) + - name: Windows ClangCL (2022 + llvm-cov) os: windows-2022 VS_GENERATOR_TOOLSET: ClangCL + RUN_ANALYZER: llvm-cov - name: LLVM-Mingw os: windows-latest TEST_MINGW: 1 @@ -367,6 +368,15 @@ jobs: if: ${{ runner.os == 'macOS' }} run: echo "SDKROOT=$(xcrun --sdk macosx --show-sdk-path)" >> "$GITHUB_ENV" + - name: Set VS LLVM tools for ClangCL + if: ${{ runner.os == 'Windows' && env['VS_GENERATOR_TOOLSET'] == 'ClangCL' && contains(env['RUN_ANALYZER'], 'llvm-cov') }} + shell: powershell + run: | + $vs = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath + $llvm = Join-Path $vs "VC\Tools\Llvm\x64\bin" + "LLVM_PROFDATA=$llvm\llvm-profdata.exe" >> $env:GITHUB_ENV + "LLVM_COV=$llvm\llvm-cov.exe" >> $env:GITHUB_ENV + - name: Remove Strawberry Perl from PATH if: ${{ runner.os == 'Windows' }} shell: powershell diff --git a/tests/cmake.py b/tests/cmake.py index 5d6287f17..5cc6e80f5 100644 --- a/tests/cmake.py +++ b/tests/cmake.py @@ -72,6 +72,17 @@ def destroy(self): os.mkdir(coveragedir) if "llvm-cov" in os.environ.get("RUN_ANALYZER", ""): + + def exe_name(name): + return name + ".exe" if sys.platform == "win32" else name + + def lib_name(name): + if sys.platform == "win32": + return name + ".dll" + elif sys.platform == "darwin": + return "lib" + name + ".dylib" + return "lib" + name + ".so" + for i, (d, _) in enumerate(self.runs.values()): # first merge the raw profiling runs files = [f for f in os.listdir(d) if f.endswith(".profraw")] @@ -90,10 +101,10 @@ def destroy(self): # then export lcov from the profiling data, since this needs access # to the object files, we need to do it per-test objects = [ - "sentry_example", - "sentry_test_unit", - "libsentry.dylib" if sys.platform == "darwin" else "libsentry.so", - "sentry-crash", + exe_name("sentry_example"), + exe_name("sentry_test_unit"), + lib_name("sentry"), + exe_name("sentry-crash"), ] cmd = [ os.environ.get("LLVM_COV", "llvm-cov"), @@ -343,6 +354,14 @@ def configure_llvm_cov(config_cmd: list[str]): config_cmd.append(f"-DCMAKE_MODULE_LINKER_FLAGS='{profile_lib}'") else: flags = "-fprofile-instr-generate -fcoverage-mapping" + if os.environ.get("VS_GENERATOR_TOOLSET") == "ClangCL": + # clang-cl source-based coverage needs the profile runtime explicitly linked. + # The flags above enable instrumentation; the runtime library merges and + # writes the raw profile at process exit. + profile_lib = "clang_rt.profile-x86_64.lib" + config_cmd.append(f"-DCMAKE_EXE_LINKER_FLAGS={profile_lib}") + config_cmd.append(f"-DCMAKE_SHARED_LINKER_FLAGS={profile_lib}") + config_cmd.append(f"-DCMAKE_MODULE_LINKER_FLAGS={profile_lib}") config_cmd.append("-DCMAKE_C_FLAGS='{}'".format(flags)) # Since we overwrite `CXXFLAGS` below, we must add the experimental library here for the GHA runner that builds