Skip to content

Comments

bazel: add release structure improvements (versioning, SONAME, vars.sh, pkg-config)#3513

Open
napetrov wants to merge 4 commits intouxlfoundation:mainfrom
napetrov:bazel/release-structure-improvements
Open

bazel: add release structure improvements (versioning, SONAME, vars.sh, pkg-config)#3513
napetrov wants to merge 4 commits intouxlfoundation:mainfrom
napetrov:bazel/release-structure-improvements

Conversation

@napetrov
Copy link
Contributor

Summary

Closes part of TODO.md: Release to oneAPI structure — Bazel shall write headers, binaries, examples and scripts to oneAPI release structure as the current make does.

Changes

1. Binary ABI version in config (dev/bazel/config/config.bzl)

Added binary_major and binary_minor fields to VersionInfo provider, separate from product version (2026.x). Matches Make's MAJORBINARY=2 / MINORBINARY=9 variables used for SONAME and symlinks.

2. Library versioning + symlinks (dev/bazel/release.bzl)

bazel build //:release now produces:

lib/intel64/libonedal_core.so.2.9   ← real file
lib/intel64/libonedal_core.so.2     → libonedal_core.so.2.9
lib/intel64/libonedal_core.so       → libonedal_core.so.2

Uses ctx.actions.symlink() (hermetic Bazel API, no shell invocation).

3. SONAME embedding (dev/bazel/cc.bzl, dev/bazel/cc/link.bzl)

Shared libraries now get -Wl,-soname,libonedal_core.so.2 on Linux, matching Make's behavior. Uses macro+select() pattern (select() evaluated in macro, resolved string list passed to rule via attr).

4. vars.sh generation (dev/bazel/scripts.bzl)

Generates env/vars.sh from deploy/local/vars_lnx.sh template using ctx.actions.expand_template() with binary version substitutions.

5. pkg-config generation (dev/bazel/scripts.bzl)

Generates lib/pkgconfig/onedal.pc from deploy/pkg-config/pkg-config.cpp via cpp -P preprocessor.

6. Test script (dev/bazel/tests/release_structure_test.sh)

Shell test validating:

  • Versioned .so.X.Y files exist
  • Symlinks .so.X and .so are correct
  • SONAME via readelf -d
  • vars.sh substitutions correct
  • onedal.pc has required fields

Not in this PR

  • --exclude-libs for MKL symbol hiding (tracked separately, requires build validation on a machine with MKL installed)
  • Windows vars.bat (after Windows toolchain PR)
  • macOS install_name_tool (separate PR)

Testing

bazel build //:release
./dev/bazel/tests/release_structure_test.sh bazel-bin/release/daal/latest

- Add binary ABI version (binary_major=2, binary_minor=9) to VersionInfo
  provider in config.bzl, separate from product version (2026.x).
  Matches MAJORBINARY/MINORBINARY variables in the Make build.

- Add library versioning and symlinks to release rule:
  libonedal_core.so.2.9  (real file)
  libonedal_core.so.2 -> libonedal_core.so.2.9  (symlink)
  libonedal_core.so   -> libonedal_core.so.2     (symlink)
  Uses ctx.actions.symlink() for hermetic, platform-aware symlink creation.

- Embed SONAME into shared libraries via -Wl,-soname,libonedal_core.so.2
  on Linux. Uses macro+select() pattern (select() in macro, resolved value
  passed via attr.string_list to rule impl). Matches Make's -Wl,-soname flag.

- Add vars.sh generation from deploy/local/vars_lnx.sh template using
  ctx.actions.expand_template() with binary version substitutions.

- Add pkg-config file generation from deploy/pkg-config/pkg-config.cpp
  via cpp -P preprocessor invocation.

- Add release_extra_file() helper and extra_files/extra_files_dst attrs
  to the release() rule for declarative extra file placement.

- Add BUILD files for deploy/local/ and deploy/pkg-config/ to expose
  template files to Bazel.

- Add shell test script for release structure validation:
  checks versioned .so files, symlinks, SONAME (readelf -d),
  vars.sh substitutions, and pkg-config fields.

TODO: --exclude-libs for MKL symbol hiding (tracked separately,
requires build validation on larger machine).

Relates to: TODO.md 'Release to oneAPI structure'
- Fix Starlark syntax: implicit string concatenation is forbidden,
  use single-line doc strings in attr definitions
- Add Apache 2.0 copyright headers to new files:
  deploy/local/BUILD, deploy/pkg-config/BUILD,
  dev/bazel/tests/release_structure_test.sh
- Add label for PR (needed by CI label check)
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Bazel-side “oneAPI-style” release output structure support, aiming to match the existing Make release layout (versioned shared libraries + symlinks, SONAME, generated vars.sh, and generated pkg-config file).

Changes:

  • Introduces a separate binary ABI version (major/minor) in Bazel config to drive SONAME and .so symlink naming.
  • Enhances the Bazel release rule to emit versioned shared libraries and create .so.<major> and .so symlinks.
  • Adds Bazel rules to generate env/vars.sh and lib/pkgconfig/onedal.pc, plus a shell script to validate the release tree.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
dev/bazel/tests/release_structure_test.sh Adds a release-structure validation script (versioned libs, symlinks, SONAME, vars.sh, pkg-config).
dev/bazel/scripts.bzl New Starlark rules to generate vars.sh and onedal.pc into the release tree.
dev/bazel/release.bzl Adds .so versioning/symlinks and support for copying additional generated files into the release.
dev/bazel/daal.bzl Extends dynamic-lib macro API to accept a binary ABI major for SONAME.
dev/bazel/config/config.tpl.BUILD Extends version_info() instantiation to include binary ABI version fields.
dev/bazel/config/config.bzl Extends VersionInfo provider and hardcodes binary ABI version substitutions.
dev/bazel/cc/link.bzl Threads through extra linker flags to the dynamic link action.
dev/bazel/cc.bzl Adds SONAME link-flag generation and plumbs it into dynamic-library linking.
deploy/pkg-config/BUILD Exposes pkg-config.cpp as a Bazel-exported file.
deploy/local/BUILD Exposes vars_*.{sh,bat} templates as Bazel-exported files.
BUILD Wires new script-generation targets into //:release via extra_files.

Comment on lines 44 to 51
# Find actual versioned file
versioned=$(ls "${LIB_DIR}/${lib_base}.so."* 2>/dev/null | grep -v ".so.[0-9]*$" || true)

if [ -z "$versioned" ]; then
_fail "${lib_base}.so.X.Y not found in ${LIB_DIR}"
continue
fi

Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic that finds the versioned .so file is fragile: it relies on parsing ls output and a negative grep, and will break if more than one match exists (versioned becomes multi-line and -f "$versioned" fails). Consider using a glob that matches only .so.<major>.<minor> (or use find and enforce exactly one match).

Suggested change
# Find actual versioned file
versioned=$(ls "${LIB_DIR}/${lib_base}.so."* 2>/dev/null | grep -v ".so.[0-9]*$" || true)
if [ -z "$versioned" ]; then
_fail "${lib_base}.so.X.Y not found in ${LIB_DIR}"
continue
fi
# Find actual versioned file (.so.<major>.<minor>) using globbing instead of ls/grep
shopt -s nullglob
versioned_candidates=( "${LIB_DIR}/${lib_base}.so."[0-9]*.[0-9]* )
shopt -u nullglob
if [ "${#versioned_candidates[@]}" -eq 0 ]; then
_fail "${lib_base}.so.X.Y not found in ${LIB_DIR}"
continue
elif [ "${#versioned_candidates[@]}" -gt 1 ]; then
_fail "Multiple ${lib_base}.so.X.Y candidates found in ${LIB_DIR}: ${versioned_candidates[*]}"
continue
fi
versioned="${versioned_candidates[0]}"

Copilot uses AI. Check for mistakes.
Comment on lines 230 to 231
"%{version_binary_major}": "2",
"%{version_binary_minor}": "9",
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Bazel config hardcodes binary ABI version to 2.9, but makefile.ver currently defines MAJORBINARY=3 and MINORBINARY=0. This will generate incorrect SONAMEs/symlinks and makes Bazel releases diverge from Make. Please source these values from the same place as Make (or at minimum update them to match makefile.ver) so the ABI version stays in sync.

Suggested change
"%{version_binary_major}": "2",
"%{version_binary_minor}": "9",
"%{version_binary_major}": "3",
"%{version_binary_minor}": "0",

Copilot uses AI. Check for mistakes.
Comment on lines 77 to 88
def daal_dynamic_lib(name, lib_tags=["daal"], binary_major = None, **kwargs):
"""Build a oneDAL shared library.

Automatically sets SONAME to lib<lib_name>.so.<binary_major> on Linux
when binary_major is provided.
"""
cc_dynamic_lib(
name = name,
lib_tags = lib_tags,
binary_major = binary_major,
**kwargs,
)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

binary_major defaults to None here, and none of the existing dynamic library targets pass it (e.g., cpp/daal:core_dynamic and cpp/oneapi/dal:dynamic). As a result, the new SONAME embedding logic in cc_dynamic_lib never activates and the release_structure_test SONAME check is likely to fail. Consider wiring binary_major automatically from @config//:version (VersionInfo.binary_major) inside the cc_dynamic_lib rule implementation, or update the dynamic library targets/macros so they always provide binary_major.

Copilot uses AI. Check for mistakes.
out = out.path,
),
mnemonic = "GenPkgConfig",
progress_message = "Generating pkg-config file {}".format(out.short_path),
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This action invokes cpp via run_shell without use_default_shell_env = True (and without declaring a tool), so it may fail in Bazel sandboxes/CI with cpp: command not found. Consider either enabling use_default_shell_env, or (preferably) making the preprocessor an explicit tool dependency so the action is reproducible.

Suggested change
progress_message = "Generating pkg-config file {}".format(out.short_path),
progress_message = "Generating pkg-config file {}".format(out.short_path),
use_default_shell_env = True,

Copilot uses AI. Check for mistakes.
Comment on lines 93 to 115
# pkg-config.cpp uses #if/#define blocks and the cpp preprocessor
# to emit different content for static vs dynamic variants.
# expand_template is not used here because the template relies on
# cpp's conditional compilation, which cannot be replicated with
# simple string substitution.
ctx.actions.run_shell(
inputs = [ctx.file.template],
outputs = [out],
command = (
"cpp -P " +
"-DDAL_MAJOR_BINARY={binary_major} " +
"-DDAL_MINOR_BINARY={binary_minor} " +
"-DDAL_MAJOR={major} " +
"-DDAL_MINOR={minor} " +
"{template} > {out}"
).format(
binary_major = vi.binary_major,
binary_minor = vi.binary_minor,
major = vi.major,
minor = vi.minor,
template = ctx.file.template.path,
out = out.path,
),
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says pkg-config.cpp relies on the defines passed here, but deploy/pkg-config/pkg-config.cpp currently doesn't reference DAL_MAJOR(_BINARY)/DAL_MINOR(_BINARY) at all (Version is hardcoded). Either update the template to consume these defines or drop the unused -D flags to avoid giving a false impression that the .pc version is generated from config.

Copilot uses AI. Check for mistakes.
Comment on lines 67 to 76

# Check unversioned symlink
if [ -L "$so" ]; then
_pass "${lib_base}.so unversioned symlink exists"
else
_fail "${lib_base}.so unversioned symlink missing"
fi
done

# ---------------------------------------------------------------------------
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SONAME test only asserts that a SONAME exists, but doesn’t validate it matches the expected major ABI (e.g., libonedal_core.so.<binary_major>). To catch regressions, compare the extracted SONAME against the expected value derived from the versioned filename or from config.

Copilot uses AI. Check for mistakes.
Comment on lines 45 to 70
versioned=$(ls "${LIB_DIR}/${lib_base}.so."* 2>/dev/null | grep -v ".so.[0-9]*$" || true)

if [ -z "$versioned" ]; then
_fail "${lib_base}.so.X.Y not found in ${LIB_DIR}"
continue
fi

# Check versioned file is a real file
if [ -f "$versioned" ] && [ ! -L "$versioned" ]; then
_pass "${lib_base}.so.X.Y is a real file"
else
_fail "${lib_base}.so.X.Y should be a regular file, not a symlink"
fi

# Check major symlink exists and points correctly
major_ver=$(echo "$versioned" | grep -oP '\.\d+\.\d+$' | cut -d. -f2)
major_link="${LIB_DIR}/${lib_base}.so.${major_ver}"
if [ -L "$major_link" ]; then
_pass "${lib_base}.so.${major_ver} symlink exists"
else
_fail "${lib_base}.so.${major_ver} symlink missing"
fi

# Check unversioned symlink
if [ -L "$so" ]; then
_pass "${lib_base}.so unversioned symlink exists"
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script uses grep -P (PCRE), which isn’t available in some environments (e.g., busybox grep, some minimal distros). Prefer POSIX ERE (grep -E), sed, or bash pattern matching for portability.

Copilot uses AI. Check for mistakes.
name = name,
template = select({
# TODO: add Windows condition when Windows toolchain is ready.
# "@platforms//os:windows": "@onedal//deploy/local:vars_win.bat",
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generate_vars_sh is documented as Linux/macOS, but the template select() always uses vars_lnx.sh. Either add an OS-specific select branch for macOS (to use deploy/local:vars_mac.sh) or adjust the docstring/comments to reflect Linux-only behavior for now.

Suggested change
# "@platforms//os:windows": "@onedal//deploy/local:vars_win.bat",
# "@platforms//os:windows": "@onedal//deploy/local:vars_win.bat",
"@platforms//os:osx": "@onedal//deploy/local:vars_mac.sh",

Copilot uses AI. Check for mistakes.
Comment on lines 96 to 114
def _copy_lib(ctx, prefix, version_info):
"""Copy libraries to release directory with versioning and symlinks for .so files.

For each shared library (.so / .dylib) on Linux/macOS, this creates:
libonedal_core.so.{binary_major}.{binary_minor} (real file)
libonedal_core.so.{binary_major} -> .so.{major}.{minor} (symlink)
libonedal_core.so -> .so.{major} (symlink)

Static libraries and Windows DLLs are copied as-is without versioning.
"""
lib_prefix = paths.join(prefix, "lib", "intel64")
libs = _collect_default_files(ctx.attr.lib)
dst_files = []

for lib in libs:
dst_path = paths.join(lib_prefix, lib.basename)
dst_file = _copy(ctx, lib, dst_path)
dst_files.append(dst_file)
# Determine if this is a shared library that needs versioning.
# On Linux: .so extension; on macOS: .dylib (handled separately).
is_shared_lib = lib.extension == "so"

Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_copy_lib docstring says it versions both .so and .dylib, but the implementation only treats .so as a shared library (lib.extension == "so"). Either extend the logic to handle .dylib (macOS) or update the docstring to match current behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +147 to 155
for dep, dst_subpath in zip(ctx.attr.extra_files, ctx.attr.extra_files_dst):
srcs = dep[DefaultInfo].files.to_list()
if len(srcs) != 1:
fail("extra_files entry '{}' must produce exactly one file, got {}".format(
dep.label, len(srcs)))
src = srcs[0]
dst_path = paths.join(prefix, dst_subpath)
dst_files.append(_copy(ctx, src, dst_path))
return dst_files
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_copy_extra_files iterates with zip(extra_files, extra_files_dst), which silently drops entries if the lists are different lengths. Since these attrs must be 1:1, add an explicit length check and fail with a clear message when they differ.

Copilot uses AI. Check for mistakes.
- Fix binary ABI version: update to MAJORBINARY=3, MINORBINARY=0
  to match makefile.ver (was incorrectly set to 2.9)

- Fix pkg-config generation: use 'gcc -E -P -x c' instead of 'cpp'
  directly, as cpp may fail to find cc1plus in some CI environments;
  add use_default_shell_env=True for portability

- Fix SONAME wiring: cc_dynamic_lib rule now reads binary_major from
  @config//:version (VersionInfo) as fallback when soname_linkopts is
  not explicitly set by the macro, ensuring SONAME is always in sync
  with config version without requiring manual binary_major parameter
  at each call site

- Simplify daal_dynamic_lib: remove binary_major parameter since
  SONAME is now auto-configured inside the rule implementation

- Add macOS select branch for vars_mac.sh in generate_vars_sh

- Add length check in _copy_extra_files (fail on lists length mismatch)
Test script improvements (release_structure_test.sh):
- Use bash globbing instead of ls+grep for finding versioned .so files
  (more robust, handles edge cases like multiple matches)
- Validate symlink targets with readlink: check .so.X → .so.X.Y and
  .so → .so.X point to correct files
- Validate SONAME matches expected value (libonedal_core.so.X) instead of
  just checking existence
- Replace grep -P (PCRE, not portable) with grep -E and bash string ops

Release rule improvements (release.bzl):
- Add explicit length check in _copy_extra_files: fail with clear message
  if extra_files and extra_files_dst lists differ in length
- Update _copy_lib docstring to reflect Linux-only .so versioning
  (macOS .dylib not yet implemented)

Scripts improvements (scripts.bzl):
- Add comment explaining pkg-config.cpp hardcoded version
  (DAL_MAJOR/MINOR defines passed for future compatibility)
Copilot AI review requested due to automatic review settings February 20, 2026 16:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

# limitations under the License.
#===============================================================================
# Tests for Bazel release structure: versioning, symlinks, vars.sh, pkg-config.
# Run after: bazel build //:release :release_vars_sh :release_pkgconfig
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 18 states the test should run after building three targets (release, release_vars_sh, release_pkgconfig), but the release target already includes release_vars_sh and release_pkgconfig as dependencies via extra_files. Users only need to run 'bazel build //:release' to get all the required outputs. The comment should be updated to reflect this to avoid confusion.

Suggested change
# Run after: bazel build //:release :release_vars_sh :release_pkgconfig
# Run after: bazel build //:release (which also builds env/vars.sh and pkg-config files)

Copilot uses AI. Check for mistakes.
Comment on lines +103 to +109
# Use gcc -E -P (C preprocessor) instead of cpp directly.
# 'cpp' may not find cc1plus in some CI environments; 'gcc -E -P' is more portable.
ctx.actions.run_shell(
inputs = [ctx.file.template],
outputs = [out],
command = (
"gcc -E -P -x c " +
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command uses 'gcc -E -P' hardcoded without checking if gcc is available. This could fail on systems where gcc is not installed or not in PATH. Consider using the cc_toolchain to get the C compiler path, or add a comment explaining that gcc is a required dependency for the build system.

Suggested change
# Use gcc -E -P (C preprocessor) instead of cpp directly.
# 'cpp' may not find cc1plus in some CI environments; 'gcc -E -P' is more portable.
ctx.actions.run_shell(
inputs = [ctx.file.template],
outputs = [out],
command = (
"gcc -E -P -x c " +
# Use the C preprocessor via the C compiler instead of cpp directly.
# Prefer the CC environment variable (falling back to gcc) because
# 'cpp' may not find cc1plus in some CI environments.
ctx.actions.run_shell(
inputs = [ctx.file.template],
outputs = [out],
command = (
"${CC:-gcc} -E -P -x c " +

Copilot uses AI. Check for mistakes.
Comment on lines +100 to +102
libonedal_core.so.{binary_major}.{binary_minor} (real file)
libonedal_core.so.{binary_major} -> .so.{major}.{minor} (symlink)
libonedal_core.so -> .so.{major} (symlink)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states 'libonedal_core.so.{binary_major} -> .so.{major}.{minor}' but this is incorrect. According to the code on line 127, the major symlink points to the versioned file which has the pattern libonedal_core.so.{binary_major}.{binary_minor}, not .so.{major}.{minor}. The comment should be updated to reflect the actual symlink structure: 'libonedal_core.so.{binary_major} -> libonedal_core.so.{binary_major}.{binary_minor}'.

Suggested change
libonedal_core.so.{binary_major}.{binary_minor} (real file)
libonedal_core.so.{binary_major} -> .so.{major}.{minor} (symlink)
libonedal_core.so -> .so.{major} (symlink)
libonedal_core.so.{binary_major}.{binary_minor} (real file)
libonedal_core.so.{binary_major} -> libonedal_core.so.{binary_major}.{binary_minor} (symlink)
libonedal_core.so -> libonedal_core.so.{binary_major} (symlink)

Copilot uses AI. Check for mistakes.
Comment on lines +189 to +197
# If not set by macro, falls back to empty list (no SONAME).
soname_linkopts = ctx.attr.soname_linkopts
# If lib_name is set and version info available, build SONAME from config version.
# This ensures SONAME is always in sync with @config//:version.binary_major.
if ctx.attr.lib_name and not soname_linkopts and ctx.attr._version_info:
vi = ctx.attr._version_info[VersionInfo]
if vi.binary_major:
soname = "lib{}.so.{}".format(ctx.attr.lib_name, vi.binary_major)
soname_linkopts = ["-Wl,-soname,{}".format(soname)]
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback logic on lines 191-197 will always generate a Linux-specific SONAME flag ('-Wl,-soname,...') without platform checking. This could cause build failures on Windows or macOS if the macro doesn't provide soname_linkopts. The fallback should either use the same select() pattern as the macro or be removed entirely to ensure consistent platform handling. Consider removing this fallback and requiring the macro to always set soname_linkopts (even if empty).

Suggested change
# If not set by macro, falls back to empty list (no SONAME).
soname_linkopts = ctx.attr.soname_linkopts
# If lib_name is set and version info available, build SONAME from config version.
# This ensures SONAME is always in sync with @config//:version.binary_major.
if ctx.attr.lib_name and not soname_linkopts and ctx.attr._version_info:
vi = ctx.attr._version_info[VersionInfo]
if vi.binary_major:
soname = "lib{}.so.{}".format(ctx.attr.lib_name, vi.binary_major)
soname_linkopts = ["-Wl,-soname,{}".format(soname)]
# If not set by macro, this remains empty (no SONAME flags are added here).
soname_linkopts = ctx.attr.soname_linkopts

Copilot uses AI. Check for mistakes.
echo ""
echo "=== SONAME check ==="

for lib in "${LIB_DIR}"/libonedal_core.so.*.* "${LIB_DIR}"/libonedal.so.*.* ; do
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SONAME check loop only validates libonedal_core.so.. and libonedal.so.., but the symlink check on line 42 includes libonedal_thread. If libonedal_thread is expected to be a versioned shared library with symlinks, it should also be included in the SONAME validation. If it's intentionally excluded (e.g., because it's a static library), add a comment explaining why.

Suggested change
for lib in "${LIB_DIR}"/libonedal_core.so.*.* "${LIB_DIR}"/libonedal.so.*.* ; do
for lib in "${LIB_DIR}"/libonedal_core.so.*.* "${LIB_DIR}"/libonedal.so.*.* "${LIB_DIR}"/libonedal_thread.so.*.* ; do

Copilot uses AI. Check for mistakes.
Comment on lines 77 to 83
def daal_dynamic_lib(name, lib_tags=["daal"], **kwargs):
"""Build a oneDAL shared library with SONAME automatically set from @config//:version."""
cc_dynamic_lib(
name = name,
lib_tags = lib_tags,
**kwargs,
)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment claims SONAME is automatically set from @config//:version, which is true, but this happens through the rule's fallback mechanism (cc.bzl lines 191-197) rather than through the macro's binary_major parameter. For clarity and consistency, daal_dynamic_lib should extract binary_major from VersionInfo and pass it to cc_dynamic_lib explicitly, similar to how dal_dynamic_lib should work. This would make the code flow more explicit and remove reliance on the fallback mechanism.

Copilot uses AI. Check for mistakes.
# On Linux: .so extension; on macOS: .dylib (handled separately).
is_shared_lib = lib.extension == "so"

if is_shared_lib and version_info:
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If version_info is None (line 117), the function will skip versioning and symlink creation for all .so files, silently copying them as-is like static libraries. This could lead to subtle bugs where libraries are built without proper versioning if the version provider isn't available. Consider failing fast with a clear error message if version_info is None and is_shared_lib is True, rather than silently falling back to unversioned behavior.

Suggested change
if is_shared_lib and version_info:
if is_shared_lib:
if not version_info:
fail("Shared library '{}' requires VersionInfo for proper SONAME versioning, "
"but no version_info was provided.".format(lib.basename))

Copilot uses AI. Check for mistakes.
@napetrov
Copy link
Contributor Author

/intelci: run

@napetrov
Copy link
Contributor Author

napetrov commented Feb 20, 2026

Response to Copilot Review Comments

All 11 review comments addressed across commits 3 and 4:

Commit 3: 209d7c9 - Critical fixes

Binary ABI version mismatch - Fixed: Updated to MAJORBINARY=3, MINORBINARY=0

SONAME not wired - Fixed: cc_dynamic_lib now auto-reads from @config//:version

cpp command fails - Fixed: Changed to gcc -E -P with use_default_shell_env=True

macOS vars.sh missing - Fixed: Added select branch for osx

Commit 4: 83f9353 - Test improvements

Fragile .so finding - Fixed: bash globbing instead of ls+grep

Symlinks not validated - Fixed: readlink validation added

SONAME not validated - Fixed: Compare against expected value

grep -P not portable - Fixed: Replaced with grep -E

pkg-config version hardcoded - Documented with comment

_copy_lib docstring incorrect - Fixed: Linux-only noted

_copy_extra_files length check - Fixed: Added explicit fail

Status: All 11 addressed. LinuxBazel CI passing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant