Users of kernel header files would be happier if they did not contain kernel specific parts and would contain #include statements for all other header files that they depend on, and in general would compile. For each header file exported to userspace, the script creates a simple .c file which just includes the header file. Then it tries to compile it and reports results. Kernel headers depend on GCC headers so their path is included in the compiler command line. Some gcc and kernel headers depend on libc headers so make them available by copying from the running system. The /usr/include location can not be used directly since it may contain an older version of the kernel headers. Execute the script like this on x86 GNU/Linux machine with GCC headers in /usr/lib/gcc/i586-linux-gnu/4.9/include and libc headers in /usr/include: $ make headers_install $ cd usr/include $ ../../scripts/headers_compile_test.sh Example statistics from 3.15.9 kernel: 131 files failed the compile test. 597 files passed the compile test. Example error count from 3.15.9: $ ../../scripts/headers_compile_test.sh 2>&1 | \ grep error: | sed -e 's/.*error://g' | sort | uniq -c | sort -rn 256 unknown type name ‘uint32_t’ 115 unknown type name ‘uint64_t’ 103 unknown type name ‘size_t’ 43 unknown type name ‘__kernel_ulong_t’ 36 unknown type name ‘uint8_t’ 22 field ‘addr’ has incomplete type 18 field ‘tstamp’ has incomplete type 16 unknown type name ‘__kernel_time_t’ 16 field ‘in’ has incomplete type 16 field ‘in6’ has incomplete type 14 unknown type name ‘__be16’ 13 ‘IFNAMSIZ’ undeclared here (not in a function) 9 unknown type name ‘uint16_t’ 9 field ‘ifru_netmask’ has incomplete type 9 field ‘ifru_hwaddr’ has incomplete type 9 field ‘ifru_dstaddr’ has incomplete type 9 field ‘ifru_broadaddr’ has incomplete type 9 field ‘ifru_addr’ has incomplete type 8 unknown type name ‘__kernel_pid_t’ 7 unknown type name ‘u_short’ 7 unknown type name ‘pid_t’ 6 invalid application of ‘sizeof’ to incomplete type ‘struct timespec’ 6 field ‘audio_tstamp’ has incomplete type 5 unknown type name ‘__kernel_long_t’ 5 requested alignment is not an integer constant 5 limits.h: No such file or directory 5 array type has incomplete element type 4 unknown type name ‘__kernel_uid32_t’ 4 unknown type name ‘__kernel_gid32_t’ 4 unknown type name ‘int32_t’ 4 field ‘src’ has incomplete type 4 ‘ETH_ALEN’ undeclared here (not in a function) 3 unknown type name ‘int64_t’ 3 unknown type name ‘caddr_t’ 3 ‘IPSET_ERR_TYPE_SPECIFIC’ undeclared here (not in a function) 3 field ‘trigger_tstamp’ has incomplete type 3 field ‘src_addr’ has incomplete type 3 field ‘smsk’ has incomplete type 3 field ‘sin_addr’ has incomplete type 3 field ‘laddr’ has incomplete type 3 field ‘id’ has incomplete type 3 field ‘bssid’ has incomplete type 3 expected specifier-qualifier-list before ‘uint64_t’ 2 unknown type name ‘u_long’ 2 unknown type name ‘stack_t’ 2 unknown type name ‘sigset_t’ 2 unknown type name ‘sa_family_t’ 2 unknown type name ‘__kernel_mode_t’ 2 unknown type name ‘__kernel_key_t’ 2 unknown type name ‘elf_gregset_t’ 2 unknown type name ‘bool’ 2 ‘uint64_t’ undeclared here (not in a function) 2 ‘true’ undeclared (first use in this function) 2 ‘NAME_MAX’ undeclared here (not in a function) 2 ‘__kernel_mode_t’ undeclared here (not in a function) 2 field ‘uc_mcontext’ has incomplete type 2 field ‘tmsk’ has incomplete type 2 field ‘tgt’ has incomplete type 2 field ‘shm_perm’ has incomplete type 2 field ‘sem_perm’ has incomplete type 2 field ‘raddr’ has incomplete type 2 field ‘msg_perm’ has incomplete type 2 field ‘grp’ has incomplete type 2 field ‘dst_addr’ has incomplete type 2 field ‘arp_pa’ has incomplete type 2 field ‘arp_netmask’ has incomplete type 2 field ‘arp_ha’ has incomplete type 2 ‘false’ undeclared (first use in this function) 1 xen/interface/xen.h: No such file or directory 1 via_drmclient.h: No such file or directory 1 unknown type name ‘wait_queue_head_t’ 1 unknown type name ‘u_int8_t’ 1 unknown type name ‘snd_seq_client_type_t’ 1 unknown type name ‘int16_t’ 1 unknown type name ‘ino_t’ 1 unknown type name ‘elf_greg_t’ 1 unknown type name ‘elf_fpxregset_t’ 1 unknown type name ‘elf_fpregset_t’ 1 unknown type name ‘__be32’ 1 ‘SIOCDEVPRIVATE’ undeclared here (not in a function) 1 ‘NULL’ undeclared (first use in this function) 1 netinet/in.h: No such file or directory 1 ‘MSG_FIN’ undeclared here (not in a function) 1 ‘MAX_IPOPTLEN’ undeclared here (not in a function) 1 ‘MAX_ADDR_LEN’ undeclared here (not in a function) 1 invalid application of ‘sizeof’ to incomplete type ‘struct sockaddr’ 1 ‘IFHWADDRLEN’ undeclared here (not in a function) 1 field ‘vmask’ has incomplete type 1 field ‘vifc_rmt_addr’ has incomplete type 1 field ‘vifc_lcl_addr’ has incomplete type 1 field ‘vaddr’ has incomplete type 1 field ‘uc_chain’ has incomplete type 1 field ‘tgt_ip’ has incomplete type 1 field ‘tcp’ has incomplete type 1 field ‘sw_reserved’ has incomplete type 1 field ‘stamp’ has incomplete type 1 field ‘sspp_addr’ has incomplete type 1 field ‘ssp_addr’ has incomplete type 1 field ‘src_mask’ has incomplete type 1 field ‘src_ip’ has incomplete type 1 field ‘spt_address’ has incomplete type 1 field ‘spp_address’ has incomplete type 1 field ‘spinfo_address’ has incomplete type 1 field ‘spc_aaddr’ has incomplete type 1 field ‘sas_obs_rto_ipaddr’ has incomplete type 1 field ‘saddr’ has incomplete type 1 field ‘rtmsg_src’ has incomplete type 1 field ‘rtmsg_gateway’ has incomplete type 1 field ‘rtmsg_dst’ has incomplete type 1 field ‘rt_genmask’ has incomplete type 1 field ‘rt_gateway’ has incomplete type 1 field ‘rt_dst’ has incomplete type 1 field ‘real’ has incomplete type 1 field ‘prefix’ has incomplete type 1 field ‘obj_list’ has incomplete type 1 field ‘mfcc_origin’ has incomplete type 1 field ‘mfcc_mcastgrp’ has incomplete type 1 field ‘mf6cc_origin’ has incomplete type 1 field ‘mf6cc_mcastgrp’ has incomplete type 1 field ‘mask’ has incomplete type 1 field ‘ival2’ has incomplete type 1 field ‘ival1’ has incomplete type 1 field ‘iph’ has incomplete type 1 field ‘ip’ has incomplete type 1 field ‘ip6’ has incomplete type 1 field ‘im_src’ has incomplete type 1 field ‘im_dst’ has incomplete type 1 field ‘im6_src’ has incomplete type 1 field ‘im6_dst’ has incomplete type 1 field ‘gw’ has incomplete type 1 field ‘expected’ has incomplete type 1 field ‘dst_mask’ has incomplete type 1 field ‘dmsk’ has incomplete type 1 field ‘dest_addr’ has incomplete type 1 field ‘daddr’ has incomplete type 1 field ‘ap_addr’ has incomplete type 1 field ‘a6’ has incomplete type 1 field ‘a4’ has incomplete type 1 expected specifier-qualifier-list before ‘DECLARE_BITMAP’ 1 expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘snd_seq_client_type_t’ 1 #error "patchkey.h included directly" 1 drm.h: No such file or directory 1 ‘DLM_RESNAME_MAXLEN’ undeclared here (not in a function) 1 arpa/inet.h: No such file or directory Signed-off-by: Mikko Rapeli <mikko.rapeli@xxxxxx> --- scripts/headers_compile_test.sh | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100755 scripts/headers_compile_test.sh diff --git a/scripts/headers_compile_test.sh b/scripts/headers_compile_test.sh new file mode 100755 index 0000000..59f7032 --- /dev/null +++ b/scripts/headers_compile_test.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# bash due to arithmetics +set -e +set -u +#set -x + +echo Simple compile test for header files meant for userspace. + +# sanity test +if [ ! -d ./linux ]; then + echo Sanity check error: ./linux directory not found + echo Should be called in usr/include after \'make headers_install\'. + echo Returns number of failed files, 0 if none. + exit 1 +fi + +# Support CC variable for compiler and ccache +set +u +if [ "$CC"foobar == "foobar" ]; then + CC=cc +fi +set -u + +# Kernel headers refer to some gcc and libc headers so make them available. +set +u +if [ "$LIBC_ARCH"foobar == "foobar" ]; then + LIBC_ARCH=i386-linux-gnu +fi + +if [ "$LIBC"foobar == "foobar" ]; then + LIBC=/usr/include +fi +set -u + +LIBC_INC=../libc_include +rm -rf "$LIBC_INC" +mkdir -p "$LIBC_INC" + +# just copy them all without subdirectories +cp "$LIBC"/*.h "$LIBC_INC"/ +cp -a "$LIBC/$LIBC_ARCH" "$LIBC_INC/$LIBC_ARCH" + +# GCC headers +set +u +if [ "$GCC_INC"foobar == "foobar" ]; then + GCC_INC=/usr/lib/gcc/i586-linux-gnu/4.9/include +fi +set -u + +# For each header file, create a .c which just includes the header file +# and try to compile it using only current directory for searching other +# included header files. +_FAILED=0 +_PASSED=0 +for f in $( find . -name "*\.h" | xargs ); do + _FAIL=0 + CFILE=$( echo "$( dirname $f )/$( basename $f .h ).c" ) + + # create .c file + echo "#include <$( echo $f | sed -e 's|^.\/||' )>" \ + > "$(dirname $f)/$(basename $f .h).c" + + # compile test, CC not quoted to support ccache + echo $CC -Wall -c -nostdinc -I . -I "$LIBC_INC" -I "$LIBC_INC/$LIBC_ARCH" -I "$GCC_INC" "$CFILE" + $CC -Wall -c -nostdinc -I . -I "$LIBC_INC" -I "$LIBC_INC/$LIBC_ARCH" -I "$GCC_INC" "$CFILE" \ + || _FAIL=1 + + # report errors + if [ "$_FAIL" -gt 0 ]; then + echo "FAILED: $f" + _FAILED=$(( $_FAILED + 1 )) + else + echo "PASSED: $f" + _PASSED=$(( $_PASSED + 1)) + fi +done + +rm -rf "$LIBC_INC" + +echo Statistics: +echo $_FAILED files failed the compile test. +echo $_PASSED files passed the compile test. + +exit $_FAILED -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html