[RFC PATCH v2 01/27] Compile test script for exported header files

From: Mikko Rapeli
Date: Mon Sep 01 2014 - 02:33:45 EST


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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/