Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .ci/scripts/abi_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,72 @@ do
# ignore a return value of 4 as it signifies a possibly compatible change
if [ $retVal != 4 ]; then RETURN_CODE=$(($RETURN_CODE+$retVal)); fi
done

# Cross-flavor public-symbol drift check.
#
# abidiff above catches per-library ABI changes. When debug info is stripped
# (the DPC++ libraries in CI to keep memory usage in check), abidiff falls
# back to symbol addition/removal and misses layout/return-type breaks. As a
# cheap supplement, diff the set of newly-exported symbols between the host
# (_c) and DPC++ flavors of the same library: if a PR adds a public symbol
# to one flavor but not the other, the public surface has diverged and a
# reviewer should look at it. This works on .dynsym alone, so debug info is
# not required.
if ! command -v nm >/dev/null 2>&1; then
echo "::error:: nm not found (required for cross-flavor symbol drift check)"
exit 1
fi

new_syms () {
# symbols present in $2 but not in $1, filtered to defined + external.
# nm errors are not suppressed: an ABI gate that silently degrades to an
# empty symbol set would report "no drift" on tool failure.
set -o pipefail
comm -13 \
<(nm -D --defined-only --extern-only "$1" | awk '{print $NF}' | sort -u) \
<(nm -D --defined-only --extern-only "$2" | awk '{print $NF}' | sort -u)
}

pairs=(
"libonedal.so:libonedal_dpc.so"
"libonedal_parameters.so:libonedal_parameters_dpc.so"
)

for pair in "${pairs[@]}"; do
host_lib=${pair%:*}
dpc_lib=${pair#*:}
if [ ! -f "$main_release_dir/$host_lib" ] || [ ! -f "$release_dir/$host_lib" ] || \
[ ! -f "$main_release_dir/$dpc_lib" ] || [ ! -f "$release_dir/$dpc_lib" ]; then
continue
fi
echo "======== cross-flavor symbol drift: ${host_lib} vs ${dpc_lib} ========"
if ! host_new=$(new_syms "$main_release_dir/$host_lib" "$release_dir/$host_lib"); then
echo "::error:: nm/comm failed for ${host_lib}"
RETURN_CODE=$((RETURN_CODE+1))
continue
fi
if ! dpc_new=$(new_syms "$main_release_dir/$dpc_lib" "$release_dir/$dpc_lib"); then
echo "::error:: nm/comm failed for ${dpc_lib}"
RETURN_CODE=$((RETURN_CODE+1))
continue
fi
# printf '%s' (not echo) so an empty set doesn't inject a spurious blank
# line into comm's input, which would produce false-positive drift.
only_in_dpc=$(comm -13 <(printf '%s' "$host_new") <(printf '%s' "$dpc_new"))
only_in_host=$(comm -23 <(printf '%s' "$host_new") <(printf '%s' "$dpc_new"))
if [ -n "$only_in_dpc" ]; then
echo "::error:: new public symbols in ${dpc_lib} with no counterpart in ${host_lib}:"
echo "$only_in_dpc"
RETURN_CODE=$((RETURN_CODE+1))
fi
if [ -n "$only_in_host" ]; then
echo "::error:: new public symbols in ${host_lib} with no counterpart in ${dpc_lib}:"
echo "$only_in_host"
RETURN_CODE=$((RETURN_CODE+1))
fi
if [ -z "$only_in_dpc" ] && [ -z "$only_in_host" ]; then
echo "no drift"
fi
done

exit ${RETURN_CODE}
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,17 @@ jobs:
- name: Make daal
run: |
source /opt/intel/oneapi/setvars.sh
.ci/scripts/build.sh --compiler icx --optimizations ${{ matrix.ISA }} --target daal --jobs 20
.ci/scripts/build.sh --compiler icx --optimizations ${{ matrix.ISA }} --target daal --debug symbols --jobs 20
rm -rf __work
- name: Make onedal
id: onedal-dbg
run: |
source /opt/intel/oneapi/setvars.sh
.ci/scripts/build.sh --compiler icx --optimizations ${{ matrix.ISA }} --target oneapi_c --jobs 20
.ci/scripts/build.sh --compiler icx --optimizations ${{ matrix.ISA }} --target oneapi_c --debug symbols --jobs 20
rm -rf __work
# TODO: enable --debug symbols for oneapi_dpc once CI memory pressure is addressed
# (e.g. suppress device DWARF via -Xarch_device -g0 / -fsycl-device-debug=none, or larger runner).
# Currently omitted because DPC++ device DWARF blows up per-object size and icx peak RSS at -j20.
.ci/scripts/build.sh --compiler icx --optimizations ${{ matrix.ISA }} --target oneapi_dpc --jobs 20
# clean up build directory due to space limitations
rm -rf __work
Expand Down Expand Up @@ -163,6 +166,10 @@ jobs:
- name: Check ABI conformance
run: |
echo "Note: This check uses abidiff to verify ABI compliance of an SSE/AVX512 oneDAL build."
echo "Host libraries (libonedal_core, libonedal, libonedal_thread, libonedal_parameters) are built"
echo "with --debug symbols so abidiff can use DWARF for full function/variable sub-type checks."
echo "The DPC++ libraries (libonedal_dpc, libonedal_parameters_dpc) are built without debug info"
echo "to keep CI memory usage in check; abidiff falls back to ELF-symbol addition/removal on them."
echo "It compares to the last completed main build, whose commit can be found in the 'Check Cache' step."
echo "The ABI for other ISAs are assumed to match the SSE or AVX512 version, any ISA-specific exported "
echo "information that is ISA unique must be manually checked. If no shared objects are found, then "
Expand Down
Loading