Buckets:
| # Check for backwards-incompatible API and ABI changes between two builds | |
| # | |
| # Backwards-incompatible API changes, such as removing a value from an enum, | |
| # are checked by abi-compliance-checker. Such changes can break compilation of | |
| # existing programs. | |
| # | |
| # Backwards-incompatible ABI changes, such as the removal of a public function, | |
| # are checked by libigail-tools. Such changes could break run-time dynamic | |
| # linking of existing binaries. (We don't use a-c-c for ABI checks because it | |
| # needs a debug build, whereas abigail does not.) | |
| # | |
| # Commands: | |
| # --generate <build-dir>: Creates API/ABI dumps in <build-dir> | |
| # <build-dir> is expected to be a CMake build result | |
| # --check <dir1> <dir2>: Compares dumps in <dir1> and <dir2> | |
| # Comparison exit codes | |
| # 0: all good | |
| # 1: backwards-incompatible changes found | |
| # | |
| # Options: | |
| # --include-path <dir>: a-c-c calls gcc on headers; use this option to add | |
| # directories to gcc's search path | |
| # | |
| # | |
| # This script would typically be used before cutting a release: | |
| # | |
| # 1. Generate API/ABI dump for the old version | |
| # | |
| # $ check-apiabi-compat.sh --generate <build-dir-old> libfoo [ libbar ...] | |
| # | |
| # 2. <update source> | |
| # | |
| # 3. Generate API/ABI dump for the new version | |
| # | |
| # $ check-apiabi-compat.sh --generate <build-dir-new> libfoo [ libbar ...] | |
| # | |
| # 4. Compare the two dumps | |
| # | |
| # $ check-apiabi-compat.sh --check <old-build-dir> <new-build-dir> | |
| # | |
| # If the check exits 0, all is fine. Otherwise, backwards-incompatible | |
| # changes were found, and the librar(ies) need a SOVER bump. | |
| set -eu | |
| # Preconditions | |
| if ! command -v abi-compliance-checker >/dev/null 2>&1; then | |
| echo "abi-compliance-checker is not installed." >&2 | |
| exit 1 | |
| elif ! command -v abidw >/dev/null 2>&1; then | |
| echo "abigail-tools are not installed." >&2 | |
| exit 1 | |
| fi | |
| # Some generic functions | |
| usage() { | |
| echo "Usage: $0 [ --include-path <dir> ] --generate <build-dir> libXXX [ libYYY ... ]" >&2 | |
| echo " $0 [ --strict ] --check <old-build-dir> <new-build-dir>" >&2 | |
| echo "" >&2 | |
| echo " --strict: fail on any API/ABI change, including backwards-compatible additions" >&2 | |
| } | |
| get_cmake_project_name() { | |
| sed -nr 's/^project\("(.*)".*$/\1/p' CMakeLists.txt | |
| } | |
| get_cmake_version() { | |
| major="$(sed -nr 's/^set\([A-Z]+_VERSION_MAJOR ([0-9]+)\)$/\1/p' CMakeLists.txt)" | |
| minor="$(sed -nr 's/^set\([A-Z]+_VERSION_MINOR ([0-9]+)\)$/\1/p' CMakeLists.txt)" | |
| patch="$(sed -nr 's/^set\([A-Z]+_VERSION_PATCH ([0-9]+)\)$/\1/p' CMakeLists.txt)" | |
| echo "$major.$minor.$patch" | |
| } | |
| # Option parsing and validation | |
| DO_GEN=0 | |
| DO_CHECK=0 | |
| STRICT=0 | |
| BUILD_DIR= | |
| BUILD_DIR_NEW= | |
| INCLUDE_PATHS= | |
| while [ "$#" -gt 0 ]; do | |
| case "$1" in | |
| --generate=*) | |
| DO_GEN=1 | |
| BUILD_DIR="${1#*=}" | |
| shift | |
| ;; | |
| --generate) | |
| DO_GEN=1 | |
| if [ -z "${2:-}" ]; then | |
| usage | |
| exit 1 | |
| fi | |
| BUILD_DIR="$2" | |
| shift 2 | |
| ;; | |
| --check) | |
| DO_CHECK=1 | |
| if [ -z "${2:-}" ] || [ -z "${3:-}" ]; then | |
| usage | |
| exit 1 | |
| elif ! [ -d "$2" ]; then | |
| echo "$2 is not a directory." >&2 | |
| exit 1 | |
| elif ! [ -d "$3" ]; then | |
| echo "$3 is not a directory." >&2 | |
| exit 1 | |
| fi | |
| BUILD_DIR="$2" | |
| BUILD_DIR_NEW="$3" | |
| shift 3 | |
| ;; | |
| --include-path=*) | |
| INCLUDE_PATHS="$INCLUDE_PATHS ${1#*=}" | |
| shift | |
| ;; | |
| --include-path) | |
| if [ -z "${2:-}" ]; then | |
| usage | |
| exit 1 | |
| fi | |
| INCLUDE_PATHS="$INCLUDE_PATHS $2" | |
| shift 2 | |
| ;; | |
| --strict) | |
| STRICT=1 | |
| shift | |
| ;; | |
| -h | --help) | |
| usage | |
| exit 1 | |
| ;; | |
| -?*) | |
| usage | |
| exit 1 | |
| ;; | |
| *) | |
| break | |
| ;; | |
| esac | |
| done | |
| if [ $((DO_GEN + DO_CHECK)) -gt 1 ]; then | |
| echo "Can only use one --command." >&2 | |
| exit | |
| fi | |
| PROJECT_NAME="$(get_cmake_project_name)" | |
| PROJECT_VERSION="$(get_cmake_version)" | |
| LIB_NAMES="" | |
| while [ "$#" -gt 0 ]; do | |
| if [ "${1#lib}" = "$1" ]; then | |
| echo "Library to check must start with libXXX." >&2 | |
| exit 1 | |
| fi | |
| LIB_NAMES="$LIB_NAMES $1" | |
| shift | |
| done | |
| dump_current_api() { | |
| echo "Dumping API..." | |
| DESCRIPTOR="$BUILD_DIR/apiabi/acc-descriptor.xml" | |
| mkdir -p "$BUILD_DIR/apiabi" | |
| cat >"$DESCRIPTOR" <<EOF | |
| <version>$PROJECT_VERSION</version> | |
| <headers>include</headers> | |
| <add_include_paths>$INCLUDE_PATHS</add_include_paths> | |
| EOF | |
| # This addresses a bug between a-c-c and universal-ctags, manifested when | |
| # a name is use both for a tag and a function name | |
| mkdir -p "$BUILD_DIR/apiabi/.ctags.d" | |
| echo "--fields=-t" >"$BUILD_DIR/apiabi/.ctags.d/acc.ctags" | |
| # Change HOME so that .ctags.d gets picked up by universal-ctags, if used | |
| HOME="$BUILD_DIR/apiabi" abi-compliance-checker \ | |
| -headers-only \ | |
| -lib "$PROJECT_NAME" \ | |
| -dump "$DESCRIPTOR" \ | |
| -log-path "$BUILD_DIR/apiabi/acc.log" \ | |
| -dump-path "$BUILD_DIR/apiabi/api.dump" | |
| # acc generates this file with an ancient timestamp, which confuses gzip | |
| touch "$BUILD_DIR/apiabi/api.dump" | |
| } | |
| dump_current_abi() { | |
| echo "Dumping ABIs ..." | |
| mkdir -p "$BUILD_DIR/apiabi" | |
| # The suppressions are needed to avoid including all the internal C++ | |
| # symbols, and system types | |
| cat >"$BUILD_DIR/apiabi/abidw.suppress" <<EOF | |
| [suppress_function] | |
| label = suppress internal C++ mangled functions | |
| symbol_name_regexp = ^_Z | |
| drop = yes | |
| [suppress_variable] | |
| label = suppress internal C++ mangled variables | |
| symbol_name_regexp = ^_Z | |
| drop = yes | |
| [suppress_type] | |
| label = Suppress types outside of our own source | |
| source_location_not_regexp = ^include/ | |
| drop = yes | |
| EOF | |
| # In abidw 2.5, handling of undefined stuff was changed a bit | |
| abidw_version="$(abidw --version | sed -r 's/^abidw: ([0-9]+\.[0-9]+).*$/\1/')" | |
| abidw_major="${abidw_version%.*}" | |
| abidw_minor="${abidw_version#*.}" | |
| if [ "$abidw_major" -gt 2 ] || [ "$abidw_minor" -gt 4 ]; then | |
| abidw_undefined_syms_options="--no-load-undefined-interfaces" | |
| else | |
| abidw_undefined_syms_options="--drop-undefined-syms" | |
| fi | |
| for lib_name in $LIB_NAMES; do | |
| # Depending on where add_library resides, the libraries can end up in | |
| # build/src or build/bin | |
| lib_path="$BUILD_DIR/src/$lib_name.so" | |
| if ! [ -f "$lib_path" ]; then | |
| lib_path="$BUILD_DIR/bin/$lib_name.so" | |
| if ! [ -f "$lib_path" ]; then | |
| echo "Cannot find library $lib_name.so" >&2 | |
| exit 1 | |
| fi | |
| fi | |
| abidw \ | |
| --headers-dir include \ | |
| "$abidw_undefined_syms_options" \ | |
| --suppressions "$BUILD_DIR/apiabi/abidw.suppress" \ | |
| --out-file "${BUILD_DIR}/apiabi/$lib_name.abi.xml" \ | |
| "$lib_path" | |
| done | |
| } | |
| # Run the actual commands | |
| if [ "$DO_GEN" -eq 1 ]; then | |
| dump_current_api | |
| dump_current_abi | |
| exit 0 | |
| elif [ "$DO_CHECK" -eq 1 ]; then | |
| # From here on, we don't want to exit on first error | |
| set +e | |
| ACC_STRICT= | |
| [ "$STRICT" -eq 0 ] || ACC_STRICT="-strict" | |
| abi-compliance-checker \ | |
| $ACC_STRICT \ | |
| -source \ | |
| -library "$PROJECT_NAME" \ | |
| -old "$BUILD_DIR/apiabi/api.dump" \ | |
| -new "$BUILD_DIR_NEW/apiabi/api.dump" \ | |
| -src-report-path "$BUILD_DIR_NEW/apiabi/api_compat_report.html" | |
| API_RESULT=$? | |
| ABI_RESULT=0 | |
| for xml_file in "$BUILD_DIR/apiabi/"lib*.abi.xml; do | |
| xml_file_new="$BUILD_DIR_NEW/apiabi/$(basename "$xml_file")" | |
| if ! [ -f "$xml_file_new" ]; then | |
| echo "Cannot compare, missing file: $xml_file_new" >&2 | |
| exit 1 | |
| fi | |
| abidiff "$xml_file" "$xml_file_new" | |
| res=$? | |
| [ "$((res & 8))" -ne 0 ] && ABI_RESULT=1 | |
| # check bit 2 for compatible ABI changes (like new symbols) and if | |
| # STRICT is set then handle this as an error. | |
| [ "$STRICT" -eq 1 ] && [ "$((res & 4))" -ne 0 ] && ABI_RESULT=1 | |
| done | |
| if [ "$API_RESULT" -gt 0 ]; then | |
| if [ "$STRICT" -eq 1 ]; then | |
| echo "ERROR: API changed — a minor version bump is required." >&2 | |
| else | |
| echo "ERROR: API changed with backwards-incompatible problems — a major version bump is required." >&2 | |
| fi | |
| fi | |
| if [ "$ABI_RESULT" -gt 0 ]; then | |
| if [ "$STRICT" -eq 1 ]; then | |
| echo "ERROR: ABI changed — a minor version bump is required." >&2 | |
| else | |
| echo "ERROR: ABI changed with backwards-incompatible problems — a major version bump is required." >&2 | |
| fi | |
| fi | |
| if [ "$((API_RESULT + ABI_RESULT))" -gt 0 ]; then | |
| exit 1 | |
| fi | |
| fi | |
Xet Storage Details
- Size:
- 8.84 kB
- Xet hash:
- 20c63da36fbaa8e0e27e354ca7354a266a6302cb36c5b46c1235d75887c2cc35
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.