From d7c14b6f3a58661fd609d703dca1ba70596d4483 Mon Sep 17 00:00:00 2001 From: yhirose Date: Tue, 11 Feb 2025 17:48:31 -0500 Subject: [PATCH] Add API compatibility check tool --- test/Makefile | 3 + test/check-abi-compatibility.sh | 59 +++++++++++++++++++ .../check-shared-library-abi-compatibility.sh | 58 ++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100755 test/check-abi-compatibility.sh create mode 100755 test/check-shared-library-abi-compatibility.sh diff --git a/test/Makefile b/test/Makefile index 587a675..081feb9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -42,6 +42,9 @@ test : test.cc include_httplib.cc ../httplib.h Makefile cert.pem test_split : test.cc ../httplib.h httplib.cc Makefile cert.pem $(CXX) -o $@ $(CXXFLAGS) test.cc httplib.cc $(TEST_ARGS) +check_abi: + @./check-shared-library-abi-compatibility.sh + test_proxy : test_proxy.cc ../httplib.h Makefile cert.pem $(CXX) -o $@ -I.. $(CXXFLAGS) test_proxy.cc $(TEST_ARGS) diff --git a/test/check-abi-compatibility.sh b/test/check-abi-compatibility.sh new file mode 100755 index 0000000..a7d9f87 --- /dev/null +++ b/test/check-abi-compatibility.sh @@ -0,0 +1,59 @@ +#!/bin/bash +if [ "$#" -ne 2 ]; then + echo "Usage: $0 old_library.so new_library.so" + exit 1 +fi + +OLD_LIB=$1 +NEW_LIB=$2 + +OLD_FUNCS=_old_funcs.txt +NEW_FUNCS=_new_funcs.txt +OLD_VARS=_old_vars.txt +NEW_VARS=_new_vars.txt + +# Extract function symbols from the old and new libraries +nm -C --defined-only $OLD_LIB | c++filt | awk '$2 ~ /[TW]/ {print substr($0, index($0,$3))}' | sort > $OLD_FUNCS +nm -C --defined-only $NEW_LIB | c++filt | awk '$2 ~ /[TW]/ {print substr($0, index($0,$3))}' | sort > $NEW_FUNCS + +# Extract variable symbols from the old and new libraries +nm -C --defined-only $OLD_LIB | c++filt | awk '$2 ~ /[BDG]/ {print substr($0, index($0,$3))}' | sort > $OLD_VARS +nm -C --defined-only $NEW_LIB | c++filt | awk '$2 ~ /[BDG]/ {print substr($0, index($0,$3))}' | sort > $NEW_VARS + +# Initialize error flag and message +error_flag=0 +error_message="" + +# Check for removed function symbols +removed_funcs=$(comm -23 $OLD_FUNCS $NEW_FUNCS) +if [ -n "$removed_funcs" ]; then + error_flag=1 + error_message+="[Removed Functions]\n$removed_funcs\n" +fi + +# Check for removed variable symbols +removed_vars=$(comm -23 $OLD_VARS $NEW_VARS) +if [ -n "$removed_vars" ]; then + error_flag=1 + error_message+="[Removed Variables]\n$removed_vars\n" +fi + +# Check for added variable symbols +added_vars=$(comm -13 $OLD_VARS $NEW_VARS) +if [ -n "$added_vars" ]; then + error_flag=1 + error_message+="[Added Variables]\n$added_vars\n" +fi + +# Remove temporary files +rm -f $NEW_FUNCS $OLD_FUNCS $OLD_VARS $NEW_VARS + +# Display error messages if any +if [ "$error_flag" -eq 1 ]; then + echo -e "$error_message" + echo "ABI compatibility check failed." + exit 1 +fi + +echo "ABI compatibility check passed: No variable symbols were removed or added, and no function symbols were removed." +exit 0 diff --git a/test/check-shared-library-abi-compatibility.sh b/test/check-shared-library-abi-compatibility.sh new file mode 100755 index 0000000..08c403c --- /dev/null +++ b/test/check-shared-library-abi-compatibility.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +CURRENT_COMMIT=$(git rev-parse HEAD) +PREVIOUS_VERSION=$(git describe --tags --abbrev=0 $CURRENT_COMMIT) + +BUILD_DIR=_build_for_is_abi_compatible + +# Make the build directory +rm -rf $BUILD_DIR +mkdir -p $BUILD_DIR/new +mkdir -p $BUILD_DIR/old + +cd $BUILD_DIR + +# Build the current commit +cd new + +cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_FLAGS="-g -Og" \ + -DBUILD_SHARED_LIBS=ON \ + -DHTTPLIB_COMPILE=ON \ + -DCMAKE_INSTALL_PREFIX=./out \ + ../../.. > /dev/null + +cmake --build . --target install > /dev/null +cmake --build . --target clean > /dev/null + +cd .. + +# Build the nearest vesion +cd old +cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_FLAGS="-g -Og" \ + -DBUILD_SHARED_LIBS=ON \ + -DHTTPLIB_COMPILE=ON \ + -DCMAKE_INSTALL_PREFIX=./out \ + ../../.. > /dev/null + +git checkout -q "${PREVIOUS_VERSION}" +cmake --build . --target install > /dev/null +cmake --build . --target clean > /dev/null + +cd .. + +# Checkout the original commit +if [ "$CURRENT_COMMIT" = "$(git rev-parse master)" ]; then + git checkout -q master +else + git checkout -q "${CURRENT_COMMIT}" +fi + +# ABI compatibility check +../check-abi-compatibility.sh ./old/out/lib/libcpp-httplib.so ./new/out/lib/libcpp-httplib.so + +# Clean the build directory +cd .. +rm -rf $BUILD_DIR