From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932721AbcHVSfU (ORCPT ); Mon, 22 Aug 2016 14:35:20 -0400 Received: from mail.kapsi.fi ([217.30.184.167]:39269 "EHLO mail.kapsi.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751602AbcHVSfN (ORCPT ); Mon, 22 Aug 2016 14:35:13 -0400 From: Mikko Rapeli To: linux-kernel@vger.kernel.org Cc: Mikko Rapeli Subject: [PATCH v05 03/72] headers_compile_test.sh: add GNU libc compatibility test Date: Mon, 22 Aug 2016 20:32:20 +0200 Message-Id: <1471890809-4383-4-git-send-email-mikko.rapeli@iki.fi> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1471890809-4383-1-git-send-email-mikko.rapeli@iki.fi> References: <1471890809-4383-1-git-send-email-mikko.rapeli@iki.fi> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 2a02:8070:d18f:5c00:bc6b:5a80:6b8d:855c X-SA-Exim-Mail-From: mikko.rapeli@iki.fi X-SA-Exim-Scanned: No (on mail.kapsi.fi); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The test is to compile all kernel uapi headers against the non-conflicting set of all GNU libc headers. The test covers variants where kernel header is included before libc header and libc header before kernel header. Tested in Debian unstable with libc6 version 2.22-4. Example execution: $ make headers_install && \ cd usr/include && \ ../../scripts/headers_compile_test.sh -lk Testing that /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l /libc_headers.h compiles cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i 686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes t_include.rwDf0l/i686-linux-gnu -o /dev/null ./drm/i810_drm.h PASSED: ./drm/i810_drm.h cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i 686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes t_include.rwDf0l/i686-linux-gnu -o /dev/null ./drm/i810_drm.h_libc_before_kernel .h PASSED libc before kernel test: ./drm/i810_drm.h ... cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i 686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes t_include.rwDf0l/i686-linux-gnu -o /dev/null ./linux/coda.h PASSED: ./linux/coda.h cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i 686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes t_include.rwDf0l/i686-linux-gnu -o /dev/null ./linux/coda.h_libc_before_kernel.h In file included from ./linux/coda.h_libc_before_kernel.h:2:0: ./linux/coda.h:108:16: error: conflicting types for ‘dev_t’ typedef u_long dev_t; ^~~~~ In file included from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_inclu de.rwDf0l/aio.h:26:0, from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_inclu de.rwDf0l/libc_headers.h:1, from ./linux/coda.h_libc_before_kernel.h:1: /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/sys/types.h: 60:17: note: previous declaration of ‘dev_t’ was here typedef __dev_t dev_t; ^~~~~ In file included from ./linux/coda.h_libc_before_kernel.h:2:0: ./linux/coda.h:109:16: error: conflicting types for ‘caddr_t’ typedef void * caddr_t; ^~~~~~~ In file included from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/aio.h:26:0, from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/libc_headers.h:1, from ./linux/coda.h_libc_before_kernel.h:1: /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/sys/types.h:116:19: note: previous declaration of ‘caddr_t’ was here typedef __caddr_t caddr_t; ^~~~~~~ FAILED libc before kernel test: ./linux/coda.h ... Kernel header compile test statistics: 0 files failed the kernel header compile test. 784 files passed the kernel header compile test. libc and kernel header compatibility test statistics: 39 files failed libc before kernel include test. 745 files passed libc before kernel include test. Signed-off-by: Mikko Rapeli --- scripts/headers_compile_test.sh | 329 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 319 insertions(+), 10 deletions(-) diff --git a/scripts/headers_compile_test.sh b/scripts/headers_compile_test.sh index e13f533..94021b6 100755 --- a/scripts/headers_compile_test.sh +++ b/scripts/headers_compile_test.sh @@ -15,14 +15,19 @@ Execute in root directory of exported kernel headers in Linux kernel source tree. Sets up gcc and libc headers without existing kernel headers to a temporary environment and tries to compile all exported header files from current directory against them. Return value is zero if all tests pass, -non-zero if something goes wrong during execution, or the amount of files -which failed the compile test. +non-zero if something goes wrong during execution or if any file failed +the compile tests. Supported arguments: - -h|--help print help - -k|--keep don't cleanup temporary header files and directories - -v|--verbose print more verbose output + -h|--help print help + -k|--keep don't cleanup temporary header files and directories + -lk|--libc-kernel test for conflicts between kernel and libc headers + when libc headers are included before kernel headers + -kl|--kernel-libc test for conflicts between kernel and libc headers + when kernel headers are included before libc headers + -l|--libc test both -lk and -kl + -v|--verbose print more verbose output Example in Linux kernel source tree: @@ -38,6 +43,9 @@ set -euo pipefail KEEP=0 HELP=0 +LIBC_TEST=0 +LIBC_KERNEL_TEST=0 +KERNEL_LIBC_TEST=0 # command line arguments for p in "$@"; do @@ -45,6 +53,19 @@ for p in "$@"; do -k|--keep) KEEP=1 ;; + -l|--libc) + LIBC_TEST=1 + LIBC_KERNEL_TEST=1 + KERNEL_LIBC_TEST=1 + ;; + -lk|--libc-kernel) + LIBC_TEST=1 + LIBC_KERNEL_TEST=1 + ;; + -kl|--kernel-libc) + LIBC_TEST=1 + KERNEL_LIBC_TEST=1 + ;; -h|--help) HELP=1 ;; @@ -138,6 +159,164 @@ for d in $LIBC; do fi done +# A single header with all non-conflicting libc headers to test kernel +# headers against libc headers for conflicts. +if [ "$LIBC_TEST" != 0 ]; then + # List taken from Debian unstable libc6 version 2.21-9. + # Some glibc headers conflict with each other so they + # are filtered out. Not perfect but better than nothing. + # + # $ for f in $( egrep "\.h$" /var/lib/dpkg/info/libc6-dev\:i386.list | sed -e 's|/usr/include/||'| sort | grep -v arpa | grep -v linux-gnu | grep -v rpcsvc | grep -v regexp.h | grep -v rpc | grep -v scsi | grep -v talkd ); do echo "#include <$f>"; done > libc_headers.h + + cat > "$COMPILE_TEST_INC/libc_headers.h" << EOF_LIBC_HEADERS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_G_config.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +EOF_LIBC_HEADERS + +fi # LIBC_TEST + # Simulate libc headers without kernel headers by removing # all known kernel header dirs from the copied libc ones. # This seems to magically work. @@ -170,11 +349,32 @@ if [ "$GCC_INC"foobar == "foobar" ]; then fi set -u -# For each header file, try to compile it using the headers we prepared. +# sanity check: test that plain libc headers compile +if [ "$LIBC_TEST" != 0 ]; then + echo "Testing that $COMPILE_TEST_INC/libc_headers.h compiles" + $CC -Wall -c -nostdinc $GCC_INC -I . \ + -I "$COMPILE_TEST_INC" \ + -I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \ + -o /dev/null \ + "$COMPILE_TEST_INC/libc_headers.h" +fi + +# Summary counters: _FAILED=0 _PASSED=0 +_LIBC_FAILED=0 +_LIBC_PASSED=0 +_LIBC_BEFORE_KERNEL_FAILED=0 +_LIBC_BEFORE_KERNEL_PASSED=0 +_KERNEL_BEFORE_LIBC_FAILED=0 +_KERNEL_BEFORE_LIBC_PASSED=0 + +# For each header file, try to compile it using the headers we prepared. for f in $( find . -name "*\.h" | xargs ); do _FAIL=0 + _FAIL_LIBC=0 + _FAIL_LIBC_BEFORE_KERNEL=0 + _FAIL_KERNEL_BEFORE_LIBC=0 # compile test, CC not quoted to support ccache echo $CC -Wall -c -nostdinc $GCC_INC -I . -I "$COMPILE_TEST_INC" -I "$COMPILE_TEST_INC/$ARCH_TRIPLET" -o /dev/null "$f" @@ -189,10 +389,119 @@ for f in $( find . -name "*\.h" | xargs ); do echo "PASSED: $f" _PASSED="$(( _PASSED + 1))" fi + + # libc header conflict tests + if [ "$LIBC_TEST" != 0 ]; then + _LIBC_BEFORE_KERNEL="$f"_libc_before_kernel.h + _KERNEL_BEFORE_LIBC="$f"_kernel_before_libc.h + + # libc header included before kernel header + if [ "$LIBC_KERNEL_TEST" != 0 ]; then + cat > "$_LIBC_BEFORE_KERNEL" << EOF_LIBC_BEFORE_KERNEL +#include +#include <$( echo "$f" | cut -c3- )> +EOF_LIBC_BEFORE_KERNEL + echo \ + $CC -Wall -c -nostdinc $GCC_INC \ + -I . -I "$COMPILE_TEST_INC" \ + -I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \ + -o /dev/null "$_LIBC_BEFORE_KERNEL" + $CC -Wall -c -nostdinc $GCC_INC \ + -I . -I "$COMPILE_TEST_INC" \ + -I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \ + -o /dev/null "$_LIBC_BEFORE_KERNEL" \ + || _FAIL_LIBC_BEFORE_KERNEL=1 + + # report errors + if [ "$_FAIL_LIBC_BEFORE_KERNEL" -gt 0 ]; then + echo "FAILED libc before kernel test: $f" + _LIBC_BEFORE_KERNEL_FAILED="$(( _LIBC_BEFORE_KERNEL_FAILED + 1 ))" + else + echo "PASSED libc before kernel test: $f" + _LIBC_BEFORE_KERNEL_PASSED="$(( _LIBC_BEFORE_KERNEL_PASSED + 1))" + fi + fi + + # kernel header included before libc + if [ "$KERNEL_LIBC_TEST" != 0 ]; then + cat > "$_KERNEL_BEFORE_LIBC" << EOF_KERNEL_BEFORE_LIBC +#include <$( echo "$f" | cut -c3- )> +#include +EOF_KERNEL_BEFORE_LIBC + echo \ + $CC -Wall -c -nostdinc $GCC_INC \ + -I . -I "$COMPILE_TEST_INC" \ + -I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \ + -o /dev/null "$_KERNEL_BEFORE_LIBC" + $CC -Wall -c -nostdinc $GCC_INC \ + -I . -I "$COMPILE_TEST_INC" \ + -I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \ + -o /dev/null "$_KERNEL_BEFORE_LIBC" \ + || _FAIL_KERNEL_BEFORE_LIBC=1 + + # report errors + if [ "$_FAIL_KERNEL_BEFORE_LIBC" -gt 0 ]; then + echo "FAILED kernel before libc test: $f" + _KERNEL_BEFORE_LIBC_FAILED="$(( _KERNEL_BEFORE_LIBC_FAILED + 1 ))" + else + echo "PASSED kernel before libc test: $f" + _KERNEL_BEFORE_LIBC_PASSED="$(( _KERNEL_BEFORE_LIBC_PASSED + 1))" + fi + fi + + # libc summary + if [ "$_FAIL_LIBC_BEFORE_KERNEL" -gt 0 -o "$_FAIL_KERNEL_BEFORE_LIBC" -gt 0 ]; then + _LIBC_FAILED="$(( _LIBC_FAILED + 1))" + else + _LIBC_PASSED="$(( _LIBC_PASSED + 1))" + fi + + if [ "$KEEP" = "0" ]; then + rm -f "$_LIBC_BEFORE_KERNEL" "$_KERNEL_BEFORE_LIBC" + fi + fi # LIBC_TEST done -echo Statistics: -echo "$_FAILED files failed the compile test." -echo "$_PASSED files passed the compile test." +cat << EOF_STATS + +Kernel header compile test statistics: + +$_FAILED files failed the kernel header compile test. +$_PASSED files passed the kernel header compile test. + +EOF_STATS + +if [ "$LIBC_TEST" != 0 ]; then + cat << EOF_LIBC_STATS +libc and kernel header compatibility test statistics: +EOF_LIBC_STATS + +if [ "$LIBC_KERNEL_TEST" != 0 ] && [ "$KERNEL_LIBC_TEST" != 0 ]; then + cat << EOF_LIBC_COMBINED +$_LIBC_FAILED files failed the libc compatibility test. +$_LIBC_PASSED files passed the libc compatibility test. +EOF_LIBC_COMBINED +fi + +if [ "$LIBC_KERNEL_TEST" != 0 ]; then + cat << EOF_LIBC_KERNEL +$_LIBC_BEFORE_KERNEL_FAILED files failed libc before kernel include test. +$_LIBC_BEFORE_KERNEL_PASSED files passed libc before kernel include test. +EOF_LIBC_KERNEL +fi + +if [ "$KERNEL_LIBC_TEST" != 0 ]; then + cat << EOF_KERNEL_LIBC +$_KERNEL_BEFORE_LIBC_FAILED files failed kernel before libc include test. +$_KERNEL_BEFORE_LIBC_PASSED files passed kernel before libc include test. +EOF_KERNEL_LIBC +fi -exit "$_FAILED" +fi # LIBC_TEST + +# return value, summary of all failures. +if [ "$(( $_FAILED + $_LIBC_BEFORE_KERNEL_FAILED + $_KERNEL_BEFORE_LIBC_FAILED ))" != 0 ]; then + exit 1 +else + exit 0 +fi -- 2.8.1