build FEATURE ABI check (#1143)
* build FEATURE dump and check ABI information to have a proper version
* travis CHANGE integrate ABI check into Travis CI
* travis CHANGE remove unnecessary libpcre2-dev install
Xenial includes old version in packages, so we have to install pcre2 from sources
* travis CHANGE install cmocka in OSX from package
diff --git a/.travis.yml b/.travis.yml
index 3b6b121..1447a3a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,12 @@
- name: Coverity
if: type = cron
+addons:
+ homebrew:
+ packages:
+ - cmocka
+ update: true
+
jobs:
include:
- stage: Coverity
@@ -33,7 +39,6 @@
build_command: "make"
branch_pattern: libyang2
before_install:
- - sudo apt-get install libpcre2-dev
# check if something changed from the last coverity build
- echo "Last coverity build on revision" `cat $HOME/cache/coveritybuild 2>/dev/null`
- echo "Current revision" `git rev-parse HEAD`
@@ -84,16 +89,23 @@
after_success:
- bash <(curl -s https://codecov.io/bash)
- stage: Test
+ name: ABI check
+ os: linux
+ compiled: gcc
+ before_install:
+ - sudo apt-get update -qq && sudo apt-get install -y abi-dumper abi-compliance-checker
+ - sudo snap install core universal-ctags
+ - wget https://ftp.pcre.org/pub/pcre/pcre2-10.30.tar.gz
+ - tar -xzf pcre2-10.30.tar.gz
+ - cd pcre2-10.30 && ./configure && make -j2 && sudo make install && cd ..
+ script:
+ - mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=ABICheck .. && LC_ALL=C.UTF-8 PATH=/snap/bin:$PATH make abi-check && cd -
+ - stage: Test
name: OS X with GCC
os: osx
compiler: gcc
allow_failures:
- os: osx
- before_install:
- - wget https://cmocka.org/files/1.1/cmocka-1.1.2.tar.xz
- - tar -xf cmocka-1.1.2.tar.xz
- - cd cmocka-1.1.2 && mkdir build && cd build && cmake .. && make -j2 && sudo make install && cd ../..
- - brew update
script:
- mkdir build && cd build && cmake -DENABLE_VALGRIND_TESTS=OFF .. && make -j2 && ctest --output-on-failure && cd -
-
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 85117c3..5bd67a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@
include(GNUInstallDirs)
include(CheckSymbolExists)
include(UseCompat)
+include(ABICheck)
set(LIBYANG_DESCRIPTION "libyang is YANG data modelling language parser and toolkit written (and providing API) in C.")
@@ -33,11 +34,26 @@
# set default build type if not specified by user
if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE debug)
+ set(CMAKE_BUILD_TYPE Debug)
endif()
+# normalize build type string
+string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER)
+if ("${BUILD_TYPE_UPPER}" STREQUAL "RELEASE")
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
+elseif ("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG")
+ set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
+elseif ("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO")
+ set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Build Type" FORCE)
+elseif ("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBUG")
+ set(CMAKE_BUILD_TYPE "RelWithDebug" CACHE STRING "Build Type" FORCE)
+elseif ("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
+ set(CMAKE_BUILD_TYPE "ABICheck" CACHE STRING "Build Type" FORCE)
+else ()
+ message(FATAL_ERROR "Unknown CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\".")
+endif ()
# options
-if((CMAKE_BUILD_TYPE STREQUAL debug) OR (CMAKE_BUILD_TYPE STREQUAL Package))
+if(("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG") OR ("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO"))
option(ENABLE_BUILD_TESTS "Build tests" ON)
option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" ON)
set(INTERNAL_DOCS YES)
@@ -47,7 +63,6 @@
set(INTERNAL_DOCS NO)
endif()
option(ENABLE_COVERAGE "Build code coverage report from tests" OFF)
-
option(ENABLE_FUZZ_TARGETS "Build target programs suitable for fuzzing with AFL" OFF)
#option(ENABLE_CALLGRIND_TESTS "Build performance tests to be run with callgrind" OFF)
@@ -105,10 +120,9 @@
endif()
endif()
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_COVERAGE} -Wall -Wextra -Wno-missing-field-initializers -std=c99")
-set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
-set(CMAKE_C_FLAGS_PACKAGE "-g -O2 -DNDEBUG")
-set(CMAKE_C_FLAGS_DEBUG "-g -Og")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_COVERAGE} -Wall -Wextra -Wno-missing-field-initializers -std=c99")
+set(CMAKE_C_FLAGS_DEBUG "-g3 -O0")
+set(CMAKE_C_FLAGS_ABICHECK "-g -Og")
include_directories(${PROJECT_BINARY_DIR}/src ${PROJECT_SOURCE_DIR}/src)
configure_file(${PROJECT_SOURCE_DIR}/src/config.h.in ${PROJECT_BINARY_DIR}/src/config.h @ONLY)
@@ -279,6 +293,11 @@
configure_file(Doxyfile.in Doxyfile)
endif()
+# generate API/ABI report
+if ("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
+ libyang_abicheck()
+endif()
+
# clean cmake cache
add_custom_target(cclean
COMMAND make clean
@@ -291,9 +310,9 @@
# if the tests are enabled, build libyang_ext_test
if(ENABLE_BUILD_TESTS)
find_package(CMocka 1.0.0)
-# if(CMOCKA_FOUND AND CMAKE_BUILD_TYPE MATCHES debug)
+# if(CMOCKA_FOUND AND CMAKE_BUILD_TYPE MATCHES Debug)
# list(APPEND EXTENSIONS_LIST "libyang_ext_test")
-# endif(CMOCKA_FOUND AND CMAKE_BUILD_TYPE MATCHES debug)
+# endif(CMOCKA_FOUND AND CMAKE_BUILD_TYPE MATCHES Debug)
endif(ENABLE_BUILD_TESTS)
#if(ENABLE_STATIC)
diff --git a/CMakeModules/ABICheck.cmake b/CMakeModules/ABICheck.cmake
new file mode 100644
index 0000000..bd46415
--- /dev/null
+++ b/CMakeModules/ABICheck.cmake
@@ -0,0 +1,69 @@
+cmake_minimum_required(VERSION 2.8.12)
+
+# generate API/ABI report
+macro(LIBYANG_ABICHECK)
+ find_program(ABI_DUMPER abi-dumper)
+ find_package_handle_standard_args(abi-dumper DEFAULT_MSG ABI_DUMPER)
+ if(ABI_DUMPER)
+ set(PUBLIC_HEADERS ${headers})
+ string(PREPEND PUBLIC_HEADERS "${CMAKE_SOURCE_DIR}/")
+ string(REPLACE ";" "\n${CMAKE_SOURCE_DIR}/" PUBLIC_HEADERS "${PUBLIC_HEADERS}")
+ file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/public_headers CONTENT "${PUBLIC_HEADERS}")
+ add_custom_target(abi-dump
+ COMMAND ${ABI_DUMPER} ./libyang${CMAKE_SHARED_LIBRARY_SUFFIX} -o libyang.${LIBYANG_SOVERSION_FULL}.dump
+ -lver ${LIBYANG_SOVERSION_FULL} -public-headers ${CMAKE_BINARY_DIR}/public_headers
+ DEPENDS yang
+ BYPRODUCTS ${CMAKE_BINARY_DIR}/libyang.${LIBYANG_SOVERSION_FULL}.dump
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ COMMENT Dumping ABI information for abi-check.)
+ endif()
+
+ # check correctness of the SO version according to the API/ABI changes
+ find_program(ABI_CHECKER abi-compliance-checker)
+ find_package_handle_standard_args(abi-compliance-checker DEFAULT_MSG ABI_CHECKER)
+ if(ABI_DUMPER AND ABI_CHECKER)
+ set(ABIBASE_HASH "" CACHE STRING "GIT hash for the commit to compare current ABI to. If not set, base SO version commit is found.")
+ if (NOT ABIBASE_HASH)
+ # check that we have some ABI base version already and get its hash in GIT
+ set(ABIBASE_VERSION "${LIBYANG_MAJOR_VERSION}.0.0")
+ execute_process(COMMAND bash "-c" "git log --pretty=oneline --grep=\"SOVERSION .* ${ABIBASE_VERSION}\$\" | cut -d' ' -f1"
+ OUTPUT_VARIABLE ABIBASE_HASH)
+ else()
+ string(SUBSTRING ${ABIBASE_HASH} 0 8 ABIBASE_HASH_SHORT)
+ set(ABIBASE_VERSION "git-${ABIBASE_HASH_SHORT}")
+ endif()
+ if(ABIBASE_HASH)
+ # we have the ABI base version, so generate script for abi-check target
+ string(REPLACE "\n" "" ABIBASE_HASH ${ABIBASE_HASH})
+ file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/abibase.sh CONTENT "#!/bin/sh
+if [ ! -d abibase ]; then mkdir abibase; fi
+cd abibase
+if [ ! -f build/libyang.*.dump ]; then
+ if [ -d .git ] && [ \"${ABIBASE_HASH}\" != \"`git log --pretty=oneline | cut -d' ' -f1`\" ]; then rm -rf .* 2> /dev/null; fi
+ if [ ! -d .git ]; then
+ git init
+ git remote add origin https://github.com/CESNET/libyang
+ git fetch origin --depth 1 ${ABIBASE_HASH}
+ git reset --hard FETCH_HEAD
+ fi
+ if [ ! -d build ]; then mkdir build; fi
+ cd build
+ cmake -DCMAKE_BUILD_TYPE=ABICheck ..
+ make abi-dump
+fi
+")
+ # abi-check target itself using abi-compliance-checker
+ add_custom_target(abi-check
+ COMMAND bash ./abibase.sh
+ COMMAND ${ABI_CHECKER} -l libyang${CMAKE_SHARED_LIBRARY_SUFFIX} -old abibase/build/libyang.*.dump
+ -new ./libyang.${LIBYANG_SOVERSION_FULL}.dump -s
+ DEPENDS yang abi-dump
+ BYPRODUCTS ${CMAKE_BINARY_DIR}/compat_reports/libyang${CMAKE_SHARED_LIBRARY_SUFFIX}/*_to_${LIBYANG_SOVERSION_FULL}/compat_report.html
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ COMMENT Checking ABI compatibility with the ${ABIBASE_VERSION} version.)
+ else()
+ add_custom_target(abi-check
+ COMMENT Nothing to check - missing base SOVERSION commit for ${ABIBASE_VERSION} version.)
+ endif()
+ endif()
+endmacro()