Skip to content

Commit

Permalink
build: Test ABI compliance (AcademySoftwareFoundation#3983)
Browse files Browse the repository at this point in the history
This patch adds a new test to the CI matrix: verifying that we do not
break the ABI during releases.

Basically, in addition to building the current checkout, it also builds
a checkout of the designated "ABI standard" (generally, the first
non-beta release of a major version), then generates ABI dumps of both
versions and runs the ABI compliance checker using the tools from
https://github.com/lvc

Making two builds sounds expensive, but both builds are rigged to be
minimal, since only the main two libraries are needed for ABI checks (we
can turn off the binary tools, unit tests, python bindings, and support
for many formats), and of course the test suite need not run. So
actually, it's less expensive than most of the test matrix entries, and
it helps ensure that we don't accidentally break ABI when we don't mean
to.

I'm not sure how many false positives we'll have. We might need to
adjust the methodology slightly as we gain experience with this.

Signed-off-by: Larry Gritz <[email protected]>
  • Loading branch information
lgritz committed Sep 17, 2023
1 parent 082b360 commit a4a1622
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 5 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,27 @@ jobs:
setenvs: export BUILDTARGET=clang-format
OIIO_CMAKE_FLAGS=-DUSE_PYTHON=0

# Test ABI stability. `abi_check` is the version or commit that we
# believe is the current standard against which we don't want to
# break the ABI. Basically, we will build that version as well as
# the current one, and compare the resulting libraries.
- desc: abi check
nametag: linux-vfx2023
os: ubuntu-latest
container: aswftesting/ci-osl:2023-clang15
vfxyear: 2023
cxx_std: 17
python_ver: "3.10"
simd: "avx2,f16c"
fmt_ver: 10.1.1
pybind11_ver: v2.10.0
skip_tests: 1
# abi_check: v2.4.15.0
abi_check: d795a3b2cceb471a3b4ab741b4a2665d07003887
setenvs: export OIIO_CMAKE_FLAGS="-DOIIO_BUILD_TOOLS=0 -DOIIO_BUILD_TESTS=0 -DUSE_PYTHON=0"
USE_OPENCV=0 USE_FFMPEG=0 USE_PYTHON=0
CMAKE_BUILD_TYPE=RelWithDebInfo

runs-on: ${{ matrix.os }}
container:
image: ${{ matrix.container }}
Expand All @@ -198,6 +219,7 @@ jobs:
OPENEXR_VERSION: ${{matrix.openexr_ver}}
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
PYTHON_VERSION: ${{matrix.python_ver}}
ABI_CHECK: ${{matrix.abi_check}}
steps:
# We would like to use harden-runner, but it flags too many false
# positives, every time we download a dependency. We should use it only
Expand Down Expand Up @@ -230,12 +252,30 @@ jobs:
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- name: Check out ABI standard
if: matrix.abi_check != ''
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
with:
ref: ${{matrix.abi_check}}
path: abi_standard
- name: Build ABI standard
if: matrix.abi_check != ''
run: |
mkdir -p abi_standard/build
pushd abi_standard
src/build-scripts/ci-build.bash
popd
- name: Check ABI
if: matrix.abi_check != ''
run: |
src/build-scripts/ci-abicheck.bash ./build abi_standard/build libOpenImageIO libOpenImageIO_Util
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
if: failure()
with:
name: oiio-${{github.job}}-${{matrix.nametag}}
path: |
build/cmake-save
build/compat_reports
build/testsuite/*/*.*
!build/testsuite/oiio-images
!build/testsuite/openexr-images
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ install (EXPORT OIIO_EXPORTED_TARGETS
NAMESPACE ${PROJECT_NAME}::)


if (PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
if (PROJECT_IS_TOP_LEVEL AND BUILD_TESTING AND ${PROJ_NAME}_BUILD_TESTS)
oiio_setup_test_data()
oiio_add_all_tests()
endif ()
Expand Down
31 changes: 31 additions & 0 deletions src/build-scripts/build_abi_tools.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash

# Utility script to download and build abi checking tools
#
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/OpenImageIO/oiio

# Exit the whole script if any command fails.
set -ex

# Where to install the final results
: ${LOCAL_DEPS_DIR:=${PWD}/ext}
: ${ABITOOLS_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}

mkdir -p ${LOCAL_DEPS_DIR}
pushd ${LOCAL_DEPS_DIR}

git clone https://github.com/lvc/vtable-dumper
pushd vtable-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd

git clone https://github.com/lvc/abi-dumper
pushd abi-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd

git clone https://github.com/lvc/abi-compliance-checker
pushd abi-compliance-checker ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd

popd

# ls -R ${LOCAL_DEPS_DIR}
export PATH=${PATH}:${ABITOOLS_INSTALL_DIR}/bin
54 changes: 54 additions & 0 deletions src/build-scripts/ci-abicheck.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env bash

# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/OpenImageIO/oiio

# Important: set -ex causes this whole script to terminate with error if
# any command in it fails. This is crucial for CI tests.
set -e

# Arguments to this script are:
# BUILDDIR_NEW BUILDDIR_OLD LIBRARIES...

BUILDDIR_NEW=$1
shift
BUILDDIR_OLD=$1
shift
LIBS=$*

#
# First, create ABI dumps from both builds
#
ABI_ARGS="-bin-only -skip-cxx -public-headers $PWD/dist/include/OpenImageIO "
echo "ABI_CHECK: PWD=${PWD} "
ls -l $BUILDDIR_NEW
ls -l $BUILDDIR_OLD
for dir in $BUILDDIR_NEW $BUILDDIR_OLD ; do
for lib in $LIBS ; do
abi-dumper $ABI_ARGS ${dir}/lib/${lib}.so -o ${dir}/abi-${lib}.dump
done
done
echo "Saved ABI dumps"

#
# Run the ABI compliance checker, saving the outputs to files
#
for lib in $LIBS ; do
abi-compliance-checker -l $lib -old $BUILDDIR_OLD/abi-$lib.dump -new $BUILDDIR_NEW/abi-$lib.dump | tee ${lib}-abi-results.txt || true
echo -e "\x1b[33;1m"
echo -e "$lib"
fgrep "Binary compatibility:" ${lib}-abi-results.txt
echo -e "\x1b[33;0m"
done

#
# If the "Binary compatibility" summary results say anything other than 100%,
# we fail!
#
for lib in $LIBS ; do
if [[ `fgrep "Binary compatibility:" ${lib}-abi-results.txt | grep -v 100\%` != "" ]] ; then
cp -r compat_reports ${BUILDDIR_NEW}/compat_reports
exit 1
fi
done
12 changes: 10 additions & 2 deletions src/build-scripts/gh-installdeps.bash
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ if [[ "$ASWF_ORG" != "" ]] ; then
#ls /etc/yum.repos.d

sudo yum install -y giflib giflib-devel && true
sudo yum install -y opencv opencv-devel && true
sudo yum install -y ffmpeg ffmpeg-devel && true
if [[ "${USE_OPENCV}" != "0" ]] ; then
sudo yum install -y opencv opencv-devel && true
fi
if [[ "${USE_FFMPEG}" != "0" ]] ; then
sudo yum install -y ffmpeg ffmpeg-devel && true
fi
if [[ "${EXTRA_DEP_PACKAGES}" != "" ]] ; then
time sudo yum install -y ${EXTRA_DEP_PACKAGES}
fi
Expand Down Expand Up @@ -193,6 +197,10 @@ if [[ "$PTEX_VERSION" != "" ]] ; then
source src/build-scripts/build_Ptex.bash
fi

if [[ "$ABI_CHECK" != "" ]] ; then
source src/build-scripts/build_abi_tools.bash
fi

if [[ "$USE_ICC" != "" ]] ; then
# We used gcc for the prior dependency builds, but use icc for OIIO itself
echo "which icpc:" $(which icpc)
Expand Down
2 changes: 1 addition & 1 deletion src/libOpenImageIO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ install_targets (OpenImageIO)

# Testing

if (OIIO_BUILD_TESTS)
if (OIIO_BUILD_TESTS AND BUILD_TESTING)

add_executable (color_test color_test.cpp)
target_link_libraries (color_test PRIVATE OpenImageIO)
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ install_targets (OpenImageIO_Util)



if (OIIO_BUILD_TESTS)
if (OIIO_BUILD_TESTS AND BUILD_TESTING)

add_executable (argparse_test argparse_test.cpp)
target_link_libraries (argparse_test PRIVATE OpenImageIO_Util)
Expand Down

0 comments on commit a4a1622

Please sign in to comment.