From 3498edb9205d4fb3c727302b5e34a686693ee473 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 24 Jul 2026 15:13:20 +0000 Subject: [PATCH 1/5] Add Bazel code coverage build flag Signed-off-by: Ubuntu --- .bazelrc | 1 + .ci/pipeline/ci.yml | 3 ++ INSTALL.md | 8 ++++ dev/bazel/README.md | 15 +++++++ dev/bazel/cc.bzl | 68 +++++++++++++++++++++++++++++-- dev/bazel/config/config.tpl.BUILD | 8 ++++ 6 files changed, 99 insertions(+), 4 deletions(-) diff --git a/.bazelrc b/.bazelrc index e53174d04fc..bb65ea21af5 100644 --- a/.bazelrc +++ b/.bazelrc @@ -18,6 +18,7 @@ build --flag_alias=release_dpc=@config//:release_dpc build --flag_alias=device=@config//:device build --flag_alias=cpu=@config//:cpu build --flag_alias=enable_assert=@config//:enable_assert +build --flag_alias=code_coverage=@config//:code_coverage # Always pass this env variable to test rules, because SYCL # OpenCL backend uses it to determine available devices diff --git a/.ci/pipeline/ci.yml b/.ci/pipeline/ci.yml index 95d34a2c8b8..16b0ffecc0d 100755 --- a/.ci/pipeline/ci.yml +++ b/.ci/pipeline/ci.yml @@ -440,6 +440,9 @@ jobs: echo "Checking Bazel config: dev" bazel build --nobuild //cpp/oneapi/dal:tests --config=dev + + echo "Checking typed code-coverage flag (host and DPC++ analysis)" + bazel build --nobuild :release --code_coverage=true displayName: 'Bazel config smoke checks' - script: | diff --git a/INSTALL.md b/INSTALL.md index 39352da396a..0233dfa687e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -232,6 +232,14 @@ It is possible to integrate various sanitizers by specifying the REQSAN flag, av make -f makefile daal oneapi_c PLAT=lnx32e CODE_COVERAGE=yes + The equivalent Bazel build is default-off and uses a typed Boolean flag: + + bazel build //:release --code_coverage=true + + Bazel coverage instrumentation is supported only on Linux with the Intel + ICX/DPC++ toolchain. It applies only to oneDAL-owned compile and link + actions; external dependencies are not instrumented. + - To build oneDAL with kernel profiling information (`REQPROFILE=yes`): _Note: if you used the general oneAPI setvars script from a Base Toolkit installation, those steps will not be necessary as Intel(R) VTune(TM) Profiler will already have been set up._ diff --git a/dev/bazel/README.md b/dev/bazel/README.md index c415e0dc28a..8147a13d380 100644 --- a/dev/bazel/README.md +++ b/dev/bazel/README.md @@ -631,8 +631,23 @@ build --linkopt=-your-link-flag | `REQSAN=undefined` | `--config=ubsan` | UBSan | | `REQSAN=memory` | `--config=msan` | MemorySanitizer (Clang/LLVM + lld; instrumented dependencies recommended) | | `REQSAN=type` | `--config=type` | TypeSanitizer; Clang-only; GCC/ICPX unsupported | +| `CODE_COVERAGE=yes` | `--code_coverage=true` | Linux ICX/DPC++ only; adds `GCOV_BUILD` and Make-equivalent coverage flags | | `COMPILER=gnu` | `CC=gcc bazel build ...` | Override compiler via `CC` env | | `OPTFLAG=O2` | `--copt=-O2` | Override optimization level | | `COPT=-flag` | `--copt=-flag` (C+C++) / `--cxxopt=-flag` (C++ only) | Arbitrary compiler flag | | `PLAT=` | `--cpu=` | ISA selection | | Full CPU ISA release coverage | `bazel build //:release --cpu=all` | Build all supported CPU ISA variants | + +With `--code_coverage=true`, Bazel keeps instrumentation on oneDAL-owned +actions instead of forwarding global `--copt`/`--linkopt` values into external +dependencies. The action-level parity is: + +| oneDAL action | Added options | +|---------------|---------------| +| ICX compile | `-DGCOV_BUILD -coverage` | +| ICX link | `-coverage` | +| DPC++ compile | `-DGCOV_BUILD` (no coverage driver option, matching Make) | +| DPC++ link | `-Xscoverage` | + +The flag is rejected on non-Linux platforms and when the selected host compiler +is not ICX. Static-library archive actions receive no linker coverage option. diff --git a/dev/bazel/cc.bzl b/dev/bazel/cc.bzl index fc9c123d878..e66b3f4da28 100644 --- a/dev/bazel/cc.bzl +++ b/dev/bazel/cc.bzl @@ -22,6 +22,7 @@ load("@onedal//dev/bazel:utils.bzl", load("@rules_cc//cc:defs.bzl", "cc_library") load("@onedal//dev/bazel/config:config.bzl", + "ConfigFlagInfo", "CpuInfo", "VersionInfo", ) @@ -83,8 +84,37 @@ def _init_cc_rule(ctx, features=[], disable_features=[]): ) return cc_toolchain, feature_config + +def _coverage_options(ctx, cc_toolchain, feature_config): + """Return Make-compatible coverage options for oneDAL-owned actions.""" + if not ctx.attr._code_coverage[ConfigFlagInfo].flag: + return struct(compile_flags = [], local_defines = [], link_flags = []) + + is_linux = ctx.target_platform_has_constraint( + ctx.attr._linux_constraint[platform_common.ConstraintValueInfo], + ) + compiler_id = cc_toolchain.compiler.split("-")[0] + if not is_linux or compiler_id != "icx": + fail("--code_coverage=true is supported only on Linux with the Intel " + + "icx/icpx toolchain (selected compiler: '{}')".format( + cc_toolchain.compiler, + )) + + is_dpc = cc_common.is_enabled( + feature_configuration = feature_config, + feature_name = "dpc++", + ) + # Make adds -coverage to ICX compile and link actions. DPC++ compile + # actions are unchanged, while DPC++ link actions receive -Xscoverage. + return struct( + compile_flags = [] if is_dpc else ["-coverage"], + local_defines = ["GCOV_BUILD"], + link_flags = ["-Xscoverage"] if is_dpc else ["-coverage"], + ) + def _cc_module_impl(ctx): toolchain, feature_config = _init_cc_rule(ctx) + coverage = _coverage_options(ctx, toolchain, feature_config) dep_compilation_contexts = onedal_cc_common.collect_compilation_contexts(ctx.attr.deps) is_windows = ctx.target_platform_has_constraint( ctx.attr._windows_constraint[platform_common.ConstraintValueInfo], @@ -103,8 +133,8 @@ def _cc_module_impl(ctx): public_hdrs = ctx.files.hdrs, private_hdrs = ctx.files.private_hdrs, defines = ctx.attr.defines, - local_defines = ctx.attr.local_defines, - user_compile_flags = ctx.attr.copts, + local_defines = ctx.attr.local_defines + coverage.local_defines, + user_compile_flags = ctx.attr.copts + coverage.compile_flags, includes = ctx.attr.includes, system_includes = ctx.attr.system_includes, quote_includes = ctx.attr.quote_includes, @@ -162,6 +192,13 @@ _cc_module = rule( "_windows_constraint": attr.label( default = "@platforms//os:windows", ), + "_linux_constraint": attr.label( + default = "@platforms//os:linux", + ), + "_code_coverage": attr.label( + default = "@config//:code_coverage", + providers = [ConfigFlagInfo], + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], @@ -263,6 +300,7 @@ def _cc_dynamic_lib_impl(ctx): # resolved through the executable RUNPATH. "do_not_link_dynamic_dependencies", ]) + coverage = _coverage_options(ctx, toolchain, feature_config) compilation_context = onedal_cc_common.collect_and_merge_compilation_contexts(ctx.attr.deps) linking_contexts = onedal_cc_common.collect_and_filter_linking_contexts( ctx.attr.deps, ctx.attr.lib_tags) @@ -287,7 +325,7 @@ def _cc_dynamic_lib_impl(ctx): feature_configuration = feature_config, linking_contexts = linking_contexts, def_file = ctx.file.def_file, - user_link_flags = linux_soname_flags + linux_linker_script_flags + (["-Wl,--exclude-libs=ALL"] if not is_windows else []) + ctx.attr.linkopts, + user_link_flags = linux_soname_flags + linux_linker_script_flags + (["-Wl,--exclude-libs=ALL"] if not is_windows else []) + ctx.attr.linkopts + coverage.link_flags, is_windows = is_windows, additional_inputs = ctx.files.linker_scripts, is_dpc = ctx.attr.lib_name.endswith("_dpc") or ctx.label.name.endswith("_dpc"), @@ -342,6 +380,13 @@ cc_dynamic_lib = rule( default = "@config//:version", providers = [VersionInfo], ), + "_linux_constraint": attr.label( + default = "@platforms//os:linux", + ), + "_code_coverage": attr.label( + default = "@config//:code_coverage", + providers = [ConfigFlagInfo], + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], @@ -352,6 +397,7 @@ def _cc_exec_impl(ctx): if not ctx.attr.deps: return toolchain, feature_config = _init_cc_rule(ctx) + coverage = _coverage_options(ctx, toolchain, feature_config) is_windows = ctx.target_platform_has_constraint( ctx.attr._windows_constraint[platform_common.ConstraintValueInfo], ) @@ -365,7 +411,7 @@ def _cc_exec_impl(ctx): cc_toolchain = toolchain, feature_configuration = feature_config, linking_contexts = linking_contexts, - user_link_flags = ctx.attr.user_link_flags, + user_link_flags = ctx.attr.user_link_flags + coverage.link_flags, ) runtime_files = _copy_windows_runtime_files(ctx, ctx.files.data, is_windows) default_info = DefaultInfo( @@ -388,6 +434,13 @@ cc_test = rule( "_windows_constraint": attr.label( default = "@platforms//os:windows", ), + "_linux_constraint": attr.label( + default = "@platforms//os:linux", + ), + "_code_coverage": attr.label( + default = "@config//:code_coverage", + providers = [ConfigFlagInfo], + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], @@ -405,6 +458,13 @@ cc_executable = rule( "_windows_constraint": attr.label( default = "@platforms//os:windows", ), + "_linux_constraint": attr.label( + default = "@platforms//os:linux", + ), + "_code_coverage": attr.label( + default = "@config//:code_coverage", + providers = [ConfigFlagInfo], + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], diff --git a/dev/bazel/config/config.tpl.BUILD b/dev/bazel/config/config.tpl.BUILD index da233e846f8..9cbd11da4e0 100644 --- a/dev/bazel/config/config.tpl.BUILD +++ b/dev/bazel/config/config.tpl.BUILD @@ -138,6 +138,13 @@ config_bool_flag( build_setting_default = False, ) +# Instrument oneDAL sources with the Intel coverage options used by Make. +# The implementation intentionally rejects unsupported OS/compiler pairs. +config_bool_flag( + name = "code_coverage", + build_setting_default = False, +) + config_setting( name = "assert_enabled", flag_values = { @@ -159,5 +166,6 @@ dump_config_info( flags = [ ":test_link_mode", ":test_thread_mode", + ":code_coverage", ], ) From d7002469af09b3f84cab54af2d57ed5df9f032c3 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 24 Jul 2026 15:50:00 +0000 Subject: [PATCH 2/5] bazel: align code coverage with Make scope Signed-off-by: Ubuntu --- .ci/pipeline/ci.yml | 10 +++++-- INSTALL.md | 11 +++++--- cpp/daal/BUILD | 2 ++ dev/bazel/README.md | 34 +++++++++++++++++------- dev/bazel/cc.bzl | 65 +++++++++++++++++++++++++++++++++------------ dev/bazel/daal.bzl | 4 ++- 6 files changed, 94 insertions(+), 32 deletions(-) diff --git a/.ci/pipeline/ci.yml b/.ci/pipeline/ci.yml index 16b0ffecc0d..3416184e0c8 100755 --- a/.ci/pipeline/ci.yml +++ b/.ci/pipeline/ci.yml @@ -441,8 +441,14 @@ jobs: echo "Checking Bazel config: dev" bazel build --nobuild //cpp/oneapi/dal:tests --config=dev - echo "Checking typed code-coverage flag (host and DPC++ analysis)" - bazel build --nobuild :release --code_coverage=true + echo "Checking code-coverage rejection with the GCC-only Bazel toolchain" + if coverage_error=$(bazel build --nobuild :release --code_coverage=true 2>&1); then + echo "ERROR: code coverage unexpectedly accepted the GCC host compiler" + exit 1 + fi + printf '%s\n' "${coverage_error}" + grep -F -- "--code_coverage=true requires host compiler ID 'icx'" <<< "${coverage_error}" + grep -F -- "detected compiler ID: 'gcc'" <<< "${coverage_error}" displayName: 'Bazel config smoke checks' - script: | diff --git a/INSTALL.md b/INSTALL.md index 0233dfa687e..e11724deb04 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -236,9 +236,14 @@ It is possible to integrate various sanitizers by specifying the REQSAN flag, av bazel build //:release --code_coverage=true - Bazel coverage instrumentation is supported only on Linux with the Intel - ICX/DPC++ toolchain. It applies only to oneDAL-owned compile and link - actions; external dependencies are not instrumented. + Bazel coverage instrumentation is supported only on Linux when the detected + host compiler ID is `icx`. It applies the Make compiler options to + oneDAL-owned actions only: host compilations and dynamic-library links are + instrumented, DPC++ dynamic-library links use `-Xscoverage`, and + `GCOV_BUILD` is limited to DAAL core sources. Static archives receive no + linker option; executable and test links receive the matching host or + DPC++ coverage driver option so instrumented objects resolve the coverage + runtime. - To build oneDAL with kernel profiling information (`REQPROFILE=yes`): diff --git a/cpp/daal/BUILD b/cpp/daal/BUILD index 78f6939dcad..a1fdad1a984 100644 --- a/cpp/daal/BUILD +++ b/cpp/daal/BUILD @@ -156,6 +156,8 @@ daal_module( daal_module( name = "threading_tbb", srcs = glob(["src/threading/**/*.cpp"]), + # Make builds these as THR_TBB.objs, outside GCOV_BUILD-scoped CORE.objs_a/y. + define_gcov_build = False, visibility_hidden = False, local_defines = [ "__TBB_NO_IMPLICIT_LINKAGE", diff --git a/dev/bazel/README.md b/dev/bazel/README.md index 8147a13d380..62be6a09a11 100644 --- a/dev/bazel/README.md +++ b/dev/bazel/README.md @@ -631,7 +631,7 @@ build --linkopt=-your-link-flag | `REQSAN=undefined` | `--config=ubsan` | UBSan | | `REQSAN=memory` | `--config=msan` | MemorySanitizer (Clang/LLVM + lld; instrumented dependencies recommended) | | `REQSAN=type` | `--config=type` | TypeSanitizer; Clang-only; GCC/ICPX unsupported | -| `CODE_COVERAGE=yes` | `--code_coverage=true` | Linux ICX/DPC++ only; adds `GCOV_BUILD` and Make-equivalent coverage flags | +| `CODE_COVERAGE=yes` | `--code_coverage=true` | Linux with host compiler ID `icx`; Make-equivalent action-local flags | | `COMPILER=gnu` | `CC=gcc bazel build ...` | Override compiler via `CC` env | | `OPTFLAG=O2` | `--copt=-O2` | Override optimization level | | `COPT=-flag` | `--copt=-flag` (C+C++) / `--cxxopt=-flag` (C++ only) | Arbitrary compiler flag | @@ -640,14 +640,30 @@ build --linkopt=-your-link-flag With `--code_coverage=true`, Bazel keeps instrumentation on oneDAL-owned actions instead of forwarding global `--copt`/`--linkopt` values into external -dependencies. The action-level parity is: +dependencies. The action-level parity with `makefile` and the compiler +definitions under `dev/make/compiler_definitions/` is: | oneDAL action | Added options | |---------------|---------------| -| ICX compile | `-DGCOV_BUILD -coverage` | -| ICX link | `-coverage` | -| DPC++ compile | `-DGCOV_BUILD` (no coverage driver option, matching Make) | -| DPC++ link | `-Xscoverage` | - -The flag is rejected on non-Linux platforms and when the selected host compiler -is not ICX. Static-library archive actions receive no linker coverage option. +| ICX compile | `-coverage` | +| DAAL core compile (the Bazel counterpart of Make `CORE.objs_a/y`) | `-DGCOV_BUILD` in addition to `-coverage` | +| DPC++ compile | None | +| ICX dynamic-library/module link | `-coverage` | +| DPC++ dynamic-library/module link | `-Xscoverage` | +| Static-library archive | None | +| ICX executable/test link | `-coverage` | +| DPC++ executable/test link | `-Xscoverage` | + +`GCOV_BUILD` is deliberately independent of compiler instrumentation: it is +opted in by `daal_module`, and explicitly excluded from separately built DAAL +threading modules. oneAPI DAL, DPC++, tests, examples, and tools use the default +off setting. This mirrors the Make target-specific assignment on +`CORE.objs_a/y`; Make's compiler-level coverage option still applies to other +host compilations. + +Make's compiler drivers add the coverage runtime on dynamic links. Bazel +applies the corresponding driver option to dynamic-library, module, executable, +and test link actions; executable/test links need it to resolve the coverage +runtime from instrumented objects. Static archives remain flag-free. The flag +is rejected on non-Linux platforms and unless the detected host compiler ID is +exactly `icx`. diff --git a/dev/bazel/cc.bzl b/dev/bazel/cc.bzl index e66b3f4da28..af87f21fd40 100644 --- a/dev/bazel/cc.bzl +++ b/dev/bazel/cc.bzl @@ -86,35 +86,56 @@ def _init_cc_rule(ctx, features=[], disable_features=[]): def _coverage_options(ctx, cc_toolchain, feature_config): - """Return Make-compatible coverage options for oneDAL-owned actions.""" + """Return Make-compatible coverage driver options for oneDAL actions.""" if not ctx.attr._code_coverage[ConfigFlagInfo].flag: - return struct(compile_flags = [], local_defines = [], link_flags = []) + return struct(compile_flags = [], link_flags = []) is_linux = ctx.target_platform_has_constraint( ctx.attr._linux_constraint[platform_common.ConstraintValueInfo], ) compiler_id = cc_toolchain.compiler.split("-")[0] - if not is_linux or compiler_id != "icx": - fail("--code_coverage=true is supported only on Linux with the Intel " + - "icx/icpx toolchain (selected compiler: '{}')".format( - cc_toolchain.compiler, - )) + if not is_linux: + fail("--code_coverage=true requires Linux (detected target OS is not Linux)") + if compiler_id != "icx": + fail("--code_coverage=true requires host compiler ID 'icx' " + + "(detected compiler ID: '{}')".format(compiler_id)) is_dpc = cc_common.is_enabled( feature_configuration = feature_config, feature_name = "dpc++", ) - # Make adds -coverage to ICX compile and link actions. DPC++ compile - # actions are unchanged, while DPC++ link actions receive -Xscoverage. + # Make adds -coverage to every ICX compilation and to dynamic links. + # DPC++ compilations are unchanged; DPC++ dynamic links use -Xscoverage. return struct( compile_flags = [] if is_dpc else ["-coverage"], - local_defines = ["GCOV_BUILD"], link_flags = ["-Xscoverage"] if is_dpc else ["-coverage"], ) +def _without_coverage_link_flags(linking_context, coverage_link_flags): + """Remove action-local coverage flags while preserving linker metadata.""" + linker_inputs = [] + for linker_input in linking_context.linker_inputs.to_list(): + linker_inputs.append(cc_common.create_linker_input( + owner = linker_input.owner, + libraries = depset(linker_input.libraries), + user_link_flags = [ + flag + for flag in linker_input.user_link_flags + if flag not in coverage_link_flags + ], + additional_inputs = depset(linker_input.additional_inputs), + linkstamps = depset(linker_input.linkstamps), + )) + return cc_common.create_linking_context( + linker_inputs = depset(linker_inputs), + ) + def _cc_module_impl(ctx): toolchain, feature_config = _init_cc_rule(ctx) coverage = _coverage_options(ctx, toolchain, feature_config) + coverage_defines = ["GCOV_BUILD"] if ( + ctx.attr.define_gcov_build and ctx.attr._code_coverage[ConfigFlagInfo].flag + ) else [] dep_compilation_contexts = onedal_cc_common.collect_compilation_contexts(ctx.attr.deps) is_windows = ctx.target_platform_has_constraint( ctx.attr._windows_constraint[platform_common.ConstraintValueInfo], @@ -133,7 +154,7 @@ def _cc_module_impl(ctx): public_hdrs = ctx.files.hdrs, private_hdrs = ctx.files.private_hdrs, defines = ctx.attr.defines, - local_defines = ctx.attr.local_defines + coverage.local_defines, + local_defines = ctx.attr.local_defines + coverage_defines, user_compile_flags = ctx.attr.copts + coverage.compile_flags, includes = ctx.attr.includes, system_includes = ctx.attr.system_includes, @@ -154,7 +175,13 @@ def _cc_module_impl(ctx): cc_toolchain = toolchain, feature_configuration = feature_config, compilation_outputs = compilation_outputs, + user_link_flags = coverage.link_flags, ) + # create_linking_context_from_compilation_outputs uses the flags for the + # module dynamic-link action and also puts them in its linking context. + # Keep module-action coverage flags from leaking transitively; + # executable and test actions add their own coverage driver option. + linking_context = _without_coverage_link_flags(linking_context, coverage.link_flags) tagged_linking_contexts.append(onedal_cc_common.create_tagged_linking_context( tag = ctx.attr.lib_tag, linking_context = linking_context, @@ -180,6 +207,10 @@ _cc_module = rule( "copts": attr.string_list(), "defines": attr.string_list(), "local_defines": attr.string_list(), + "define_gcov_build": attr.bool( + default = False, + doc = "Define GCOV_BUILD for Make CORE.objs_a/y-equivalent sources.", + ), "cpu_defines": attr.string_list_dict(), "fpt_defines": attr.string_list_dict(), "includes": attr.string_list(), @@ -431,9 +462,6 @@ cc_test = rule( "data": attr.label_list(allow_files=True), "user_link_flags": attr.string_list(), "_is_test": attr.bool(default=True), - "_windows_constraint": attr.label( - default = "@platforms//os:windows", - ), "_linux_constraint": attr.label( default = "@platforms//os:linux", ), @@ -441,6 +469,9 @@ cc_test = rule( default = "@config//:code_coverage", providers = [ConfigFlagInfo], ), + "_windows_constraint": attr.label( + default = "@platforms//os:windows", + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], @@ -455,9 +486,6 @@ cc_executable = rule( "data": attr.label_list(allow_files=True), "user_link_flags": attr.string_list(), "_is_test": attr.bool(default=False), - "_windows_constraint": attr.label( - default = "@platforms//os:windows", - ), "_linux_constraint": attr.label( default = "@platforms//os:linux", ), @@ -465,6 +493,9 @@ cc_executable = rule( default = "@config//:code_coverage", providers = [ConfigFlagInfo], ), + "_windows_constraint": attr.label( + default = "@platforms//os:windows", + ), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], diff --git a/dev/bazel/daal.bzl b/dev/bazel/daal.bzl index bd0d8379b12..3d0005468d7 100644 --- a/dev/bazel/daal.bzl +++ b/dev/bazel/daal.bzl @@ -30,7 +30,8 @@ load("@onedal//dev/bazel/config:config.bzl", def daal_module(name, features=[], lib_tag="daal", hdrs=[], srcs=[], auto=False, - local_defines=[], copts=[], visibility_hidden=True, **kwargs): + local_defines=[], copts=[], visibility_hidden=True, + define_gcov_build=True, **kwargs): if auto: auto_hdrs = native.glob(["**/*.h", "**/*.i"], allow_empty=True,) auto_srcs = native.glob(["**/*.cpp"], allow_empty=True,) @@ -59,6 +60,7 @@ def daal_module(name, features=[], lib_tag="daal", "@platforms//os:windows": ["/utf-8"], "//conditions:default": [], })), + define_gcov_build = define_gcov_build, local_defines = select({ "@config//:assert_enabled": local_defines + ["__DAAL_IMPLEMENTATION", "DEBUG_ASSERT=1"], "//conditions:default": local_defines + ["__DAAL_IMPLEMENTATION"], From 326b48bf09d5d8ff093697ec6403bd224f512b3e Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Sun, 26 Jul 2026 04:58:51 -0700 Subject: [PATCH 3/5] Add positive-path CI check for --code_coverage=true on icx The existing CI smoke check only exercised the rejection path (GCC host compiler). Add dev/bazel/tests/code_coverage_test.sh, run on the icx toolchain, which builds DAAL core and the separately built threading module with --code_coverage=true and inspects bazel aquery output to confirm the Make-equivalent -coverage/-DGCOV_BUILD flags are actually applied where documented, and only there. --- .ci/pipeline/ci.yml | 8 ++++ dev/bazel/README.md | 6 +++ dev/bazel/tests/BUILD | 1 + dev/bazel/tests/code_coverage_test.sh | 61 +++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100755 dev/bazel/tests/code_coverage_test.sh diff --git a/.ci/pipeline/ci.yml b/.ci/pipeline/ci.yml index 3416184e0c8..f027b1b92bb 100755 --- a/.ci/pipeline/ci.yml +++ b/.ci/pipeline/ci.yml @@ -388,6 +388,9 @@ jobs: - script: | .ci/env/apt.sh opencl displayName: 'install opencl' + - script: | + .ci/env/apt.sh dpcpp + displayName: 'dpcpp installation' - script: | # sourcing done to set bazel version value from script source .ci/env/bazelisk.sh @@ -451,6 +454,11 @@ jobs: grep -F -- "detected compiler ID: 'gcc'" <<< "${coverage_error}" displayName: 'Bazel config smoke checks' + - script: | + source /opt/intel/oneapi/setvars.sh + BAZEL=bazel dev/bazel/tests/code_coverage_test.sh + displayName: 'Bazel code-coverage icx smoke build' + - script: | bazel build :release --release_dpc=false displayName: 'release' diff --git a/dev/bazel/README.md b/dev/bazel/README.md index 62be6a09a11..000300cc096 100644 --- a/dev/bazel/README.md +++ b/dev/bazel/README.md @@ -667,3 +667,9 @@ and test link actions; executable/test links need it to resolve the coverage runtime from instrumented objects. Static archives remain flag-free. The flag is rejected on non-Linux platforms and unless the detected host compiler ID is exactly `icx`. + +CI uses `dev/bazel/tests/code_coverage_test.sh` on the icx toolchain to build +`//cpp/daal:core_static` and `//cpp/daal:thread_static` with +`--code_coverage=true`, then inspects `bazel aquery` output to confirm DAAL +core compile actions carry `-coverage`/`-DGCOV_BUILD` and the separately built +threading module does not. diff --git a/dev/bazel/tests/BUILD b/dev/bazel/tests/BUILD index 78fec0052a5..1c38aff476b 100644 --- a/dev/bazel/tests/BUILD +++ b/dev/bazel/tests/BUILD @@ -4,4 +4,5 @@ exports_files([ "release_structure_test.sh", "isa_coverage_test.sh", "mkl_linkage_test.sh", + "code_coverage_test.sh", ]) diff --git a/dev/bazel/tests/code_coverage_test.sh b/dev/bazel/tests/code_coverage_test.sh new file mode 100755 index 00000000000..4f973769b35 --- /dev/null +++ b/dev/bazel/tests/code_coverage_test.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +#=============================================================================== +# Copyright contributors to the oneDAL project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#=============================================================================== + +# Positive-path check for --code_coverage=true on the icx toolchain: builds +# DAAL core and confirms the actual compile actions carry the Make-equivalent +# coverage flags, and that the separately built threading module does not. +set -euo pipefail + +bazel_cmd="${BAZEL:-bazel}" +work="$(mktemp -d)" +trap 'rm -rf "${work}"' EXIT + +"${bazel_cmd}" build //cpp/daal:core_static --code_coverage=true + +"${bazel_cmd}" aquery 'mnemonic("CppCompile", deps(//cpp/daal:core_static))' \ + --code_coverage=true --output=jsonproto >"${work}/core_actions.json" +python3 -c " +import json, sys +with open('${work}/core_actions.json') as f: + data = json.load(f) +target_actions = [a for a in data.get('actions', []) + if any('error_handling.cpp' in arg for arg in a.get('arguments', []))] +if not target_actions: + sys.exit('ERROR: no compile action found for error_handling.cpp') +for action in target_actions: + args = action.get('arguments', []) + if '-coverage' not in args: + sys.exit('ERROR: -coverage missing from compile arguments: {}'.format(args)) + if '-DGCOV_BUILD' not in args: + sys.exit('ERROR: -DGCOV_BUILD missing from compile arguments: {}'.format(args)) +print('error_handling.cpp compile action carries -coverage and -DGCOV_BUILD') +" + +"${bazel_cmd}" build //cpp/daal:thread_static --code_coverage=true +"${bazel_cmd}" aquery 'mnemonic("CppCompile", deps(//cpp/daal:thread_static))' \ + --code_coverage=true --output=jsonproto >"${work}/thread_actions.json" +python3 -c " +import json, sys +with open('${work}/thread_actions.json') as f: + data = json.load(f) +for action in data.get('actions', []): + if '-DGCOV_BUILD' in action.get('arguments', []): + sys.exit('ERROR: threading_tbb compile action unexpectedly defines GCOV_BUILD') +print('threading_tbb compile actions do not define GCOV_BUILD') +" + +echo "code-coverage icx smoke checks passed" From 80a313c4da5b38f78b73e5d68c13491fbe7d361f Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Tue, 28 Jul 2026 22:03:48 -0700 Subject: [PATCH 4/5] ci: clean coverage smoke outputs before release build --- .ci/pipeline/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.ci/pipeline/ci.yml b/.ci/pipeline/ci.yml index f027b1b92bb..1d211d3dcf4 100755 --- a/.ci/pipeline/ci.yml +++ b/.ci/pipeline/ci.yml @@ -457,6 +457,11 @@ jobs: - script: | source /opt/intel/oneapi/setvars.sh BAZEL=bazel dev/bazel/tests/code_coverage_test.sh + # The coverage smoke uses a different compiler/configuration than the + # following GCC release build. Drop its large, non-reusable output tree + # before producing release artifacts on the space-constrained CI agent. + bazel clean + df -h . displayName: 'Bazel code-coverage icx smoke build' - script: | From 5329e7b44d59fec05ae31ec840f0084f222bb8ce Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Mon, 3 Aug 2026 11:38:51 +0000 Subject: [PATCH 5/5] bazel: preserve linker-input depsets Signed-off-by: Nikolay Petrov --- dev/bazel/cc.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/bazel/cc.bzl b/dev/bazel/cc.bzl index af87f21fd40..fee25a42d93 100644 --- a/dev/bazel/cc.bzl +++ b/dev/bazel/cc.bzl @@ -118,11 +118,11 @@ def _without_coverage_link_flags(linking_context, coverage_link_flags): linker_inputs.append(cc_common.create_linker_input( owner = linker_input.owner, libraries = depset(linker_input.libraries), - user_link_flags = [ + user_link_flags = depset([ flag for flag in linker_input.user_link_flags if flag not in coverage_link_flags - ], + ]), additional_inputs = depset(linker_input.additional_inputs), linkstamps = depset(linker_input.linkstamps), ))