]> git.droids-corp.org - dpdk.git/commitdiff
build: add header includes check
authorBruce Richardson <bruce.richardson@intel.com>
Fri, 29 Jan 2021 16:48:21 +0000 (16:48 +0000)
committerDavid Marchand <david.marchand@redhat.com>
Fri, 29 Jan 2021 19:59:37 +0000 (20:59 +0100)
To verify that all DPDK headers are ok for inclusion directly in a C file,
and are not missing any other pre-requisite headers, we can auto-generate
for each header an empty C file that includes that header. Compiling these
files will throw errors if any header has unmet dependencies.

For some libraries, there may be some header files which are not for direct
inclusion, but rather are to be included via other header files. To allow
later checking of these files for missing includes, we separate out the
indirect include files from the direct ones.

To ensure ongoing compliance, we enable this build test as part of the
default x86 build in "test-meson-builds.sh".

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
20 files changed:
MAINTAINERS
buildtools/chkincs/gen_c_file_for_header.py [new file with mode: 0755]
buildtools/chkincs/main.c [new file with mode: 0644]
buildtools/chkincs/meson.build [new file with mode: 0644]
devtools/test-meson-builds.sh
doc/guides/contributing/coding_style.rst
doc/guides/rel_notes/release_21_02.rst
lib/librte_eal/include/meson.build
lib/librte_eal/x86/include/meson.build
lib/librte_ethdev/meson.build
lib/librte_hash/meson.build
lib/librte_ipsec/meson.build
lib/librte_lpm/meson.build
lib/librte_regexdev/meson.build
lib/librte_ring/meson.build
lib/librte_stack/meson.build
lib/librte_table/meson.build
lib/meson.build
meson.build
meson_options.txt

index 6af59eaff6e0157d66af52908b6dd04ee359551c..ec203143c3266bd4a1a273655d2ab1880f3465be 100644 (file)
@@ -98,6 +98,7 @@ F: Makefile
 F: meson.build
 F: meson_options.txt
 F: config/
+F: buildtools/chkincs/
 F: buildtools/call-sphinx-build.py
 F: buildtools/list-dir-globs.py
 F: buildtools/pkg-config/
diff --git a/buildtools/chkincs/gen_c_file_for_header.py b/buildtools/chkincs/gen_c_file_for_header.py
new file mode 100755 (executable)
index 0000000..ed46948
--- /dev/null
@@ -0,0 +1,12 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2021 Intel Corporation
+
+from sys import argv
+from os.path import abspath
+
+(h_file, c_file) = argv[1:]
+
+contents = '#include "' + abspath(h_file) + '"'
+with open(c_file, 'w') as cf:
+    cf.write(contents)
diff --git a/buildtools/chkincs/main.c b/buildtools/chkincs/main.c
new file mode 100644 (file)
index 0000000..d25bb88
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+int main(void) { return 0; }
diff --git a/buildtools/chkincs/meson.build b/buildtools/chkincs/meson.build
new file mode 100644 (file)
index 0000000..f345e87
--- /dev/null
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2021 Intel Corporation
+
+if not get_option('check_includes')
+       build = false
+       subdir_done()
+endif
+
+if is_windows
+       # for windows, the shebang line in the script won't work.
+       error('option "check_includes" is not supported on windows')
+endif
+
+gen_c_file_for_header = find_program('gen_c_file_for_header.py')
+gen_c_files = generator(gen_c_file_for_header,
+       output: '@BASENAME@.c',
+       arguments: ['@INPUT@', '@OUTPUT@'])
+
+cflags = machine_args
+cflags += '-Wno-unused-function' # needed if we include generic headers
+cflags += '-DALLOW_EXPERIMENTAL_API'
+
+sources = files('main.c')
+sources += gen_c_files.process(dpdk_chkinc_headers)
+
+deps = []
+foreach l:enabled_libs
+       deps += get_variable('static_rte_' + l)
+endforeach
+
+executable('chkincs', sources,
+       c_args: cflags,
+       include_directories: includes,
+       dependencies: deps,
+       link_whole: dpdk_static_libraries + dpdk_drivers,
+       install: false)
index efa91e0e40c16938d69a181e4b043c715cb970e8..a99a177e0c955bcde82a0417c59da75207b60663 100755 (executable)
@@ -227,7 +227,7 @@ default_machine='nehalem'
 if ! check_cc_flags "-march=$default_machine" ; then
        default_machine='corei7'
 fi
-build build-x86-default cc skipABI \
+build build-x86-default cc skipABI -Dcheck_includes=true \
        -Dlibdir=lib -Dmachine=$default_machine $use_shared
 
 # 32-bit with default compiler
index bb3f3efcbc556c231999d24adb3bf9e96fa36d9d..734d1901b22bb1e7fa6c16ec7374c3a6807e3035 100644 (file)
@@ -891,6 +891,18 @@ headers
        installed to $PREFIX/include when ``ninja install`` is run. As with
        source files, these should be specified using the meson ``files()``
        function.
+       When ``check_includes`` build option is set to ``true``, each header file
+       has additional checks performed on it, for example to ensure that it is
+       not missing any include statements for dependent headers.
+       For header files which are public, but only included indirectly in
+       applications, these checks can be skipped by using the ``indirect_headers``
+       variable rather than ``headers``.
+
+indirect_headers
+       **Default Value = []**.
+       As with ``headers`` option above, except that the files are not checked
+       for all needed include files as part of a DPDK build when
+       ``check_includes`` is set to ``true``.
 
 includes:
        **Default Value = []**.
index d26e581563aac3c40f6b11fe88620b43eccf8210..29046a6f7dab9c2e335cc542ff5dc3f107f9873c 100644 (file)
@@ -138,6 +138,14 @@ New Features
 
   See the :doc:`../compressdevs/mlx5` for more details.
 
+* **Added support for build-time checking of header includes.**
+
+  A new build option ``check_includes`` has been added, which, when enabled,
+  will perform build-time checking on DPDK public header files, to ensure none
+  are missing dependent header includes. This feature, disabled by default, is
+  intended for use by developers contributing to the DPDK SDK itself, and is
+  integrated into the build scripts and automated CI for patch contributions.
+
 
 Removed Items
 -------------
index 0dea342e1debe9d0b1b1d0bc0865c33c4113f34b..3969cf4ac70347f1c6275440df660f9919ac83f1 100644 (file)
@@ -16,7 +16,6 @@ headers += files(
        'rte_dev.h',
        'rte_devargs.h',
        'rte_eal.h',
-       'rte_eal_interrupts.h',
        'rte_eal_memconfig.h',
        'rte_eal_trace.h',
        'rte_errno.h',
@@ -49,6 +48,7 @@ headers += files(
        'rte_version.h',
        'rte_vfio.h',
 )
+indirect_headers += files('rte_eal_interrupts.h')
 
 # special case install the generic headers, since they go in a subdir
 generic_headers = files(
index 549cc21a42ede49bb6d7c951efcef5d0a58a232a..1a6ad0b17342573e91d3f2d644c0015060a24b39 100644 (file)
@@ -2,11 +2,7 @@
 # Copyright(c) 2017 Intel Corporation
 
 arch_headers = files(
-       'rte_atomic_32.h',
-       'rte_atomic_64.h',
        'rte_atomic.h',
-       'rte_byteorder_32.h',
-       'rte_byteorder_64.h',
        'rte_byteorder.h',
        'rte_cpuflags.h',
        'rte_cycles.h',
@@ -22,4 +18,12 @@ arch_headers = files(
        'rte_ticketlock.h',
        'rte_vect.h',
 )
-install_headers(arch_headers, subdir: get_option('include_subdir_arch'))
+arch_indirect_headers = files(
+       'rte_atomic_32.h',
+       'rte_atomic_64.h',
+       'rte_byteorder_32.h',
+       'rte_byteorder_64.h',
+)
+install_headers(arch_headers + arch_indirect_headers,
+               subdir: get_option('include_subdir_arch'))
+dpdk_chkinc_headers += arch_headers
index 829abd456b755e58aa5623507506416018ac7a70..c37b2e3772c6ed46e229a673c5b97992d5389369 100644 (file)
@@ -11,10 +11,8 @@ sources = files('ethdev_private.c',
        'rte_tm.c')
 
 headers = files('rte_ethdev.h',
-       'rte_ethdev_core.h',
        'rte_ethdev_trace.h',
        'rte_ethdev_trace_fp.h',
-       'rte_eth_ctrl.h',
        'rte_dev_info.h',
        'rte_flow.h',
        'rte_flow_driver.h',
@@ -22,5 +20,8 @@ headers = files('rte_ethdev.h',
        'rte_mtr_driver.h',
        'rte_tm.h',
        'rte_tm_driver.h')
+indirect_headers += files(
+       'rte_ethdev_core.h',
+       'rte_eth_ctrl.h')
 
 deps += ['net', 'kvargs', 'meter', 'telemetry']
index 0977a63fd279e791ce0e45da6882c8f0a7b348f7..242859f5ad1258f24a982a55b082a443e815ffcf 100644 (file)
@@ -1,12 +1,12 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-headers = files('rte_crc_arm64.h',
-       'rte_fbk_hash.h',
+headers = files('rte_fbk_hash.h',
        'rte_hash_crc.h',
        'rte_hash.h',
        'rte_jhash.h',
        'rte_thash.h')
+indirect_headers += files('rte_crc_arm64.h')
 
 sources = files('rte_cuckoo_hash.c', 'rte_fbk_hash.c')
 deps += ['ring']
index fc69970ec5d4181a6ce6df1597ed20ae95a23776..1497f573bb16ac2b5b7e34099f2a77c540ee6ba3 100644 (file)
@@ -3,6 +3,7 @@
 
 sources = files('esp_inb.c', 'esp_outb.c', 'sa.c', 'ses.c', 'ipsec_sad.c')
 
-headers = files('rte_ipsec.h', 'rte_ipsec_group.h', 'rte_ipsec_sa.h', 'rte_ipsec_sad.h')
+headers = files('rte_ipsec.h', 'rte_ipsec_sa.h', 'rte_ipsec_sad.h')
+indirect_headers += files('rte_ipsec_group.h')
 
 deps += ['mbuf', 'net', 'cryptodev', 'security', 'hash']
index f93c866409dad009c3582e7e1d5f78ea54bf4689..90cbf8646a4a9ceafc2caaea30760f02d1a41aba 100644 (file)
@@ -5,6 +5,6 @@ sources = files('rte_lpm.c', 'rte_lpm6.c')
 headers = files('rte_lpm.h', 'rte_lpm6.h')
 # since header files have different names, we can install all vector headers
 # without worrying about which architecture we actually need
-headers += files('rte_lpm_altivec.h', 'rte_lpm_neon.h', 'rte_lpm_sse.h', 'rte_lpm_sve.h')
+indirect_headers += files('rte_lpm_altivec.h', 'rte_lpm_neon.h', 'rte_lpm_sse.h', 'rte_lpm_sve.h')
 deps += ['hash']
 deps += ['rcu']
index c417b9caf02902c1ae93172cd9f48c3542de0e89..1b3b6db22a48baae779995651c9cbc49a8a84ac1 100644 (file)
@@ -3,6 +3,6 @@
 
 sources = files('rte_regexdev.c')
 headers = files('rte_regexdev.h',
-       'rte_regexdev_core.h',
        'rte_regexdev_driver.h')
+indirect_headers += files('rte_regexdev_core.h')
 deps += ['mbuf']
index f007893b5f2a1adf9bc2cfb3ccef00b3ed4a8551..ea050d564a933a2f2e9dc59c9143d23e3040affd 100644 (file)
@@ -2,7 +2,9 @@
 # Copyright(c) 2017 Intel Corporation
 
 sources = files('rte_ring.c')
-headers = files('rte_ring.h',
+headers = files('rte_ring.h')
+# most sub-headers are not for direct inclusion
+indirect_headers += files (
                'rte_ring_core.h',
                'rte_ring_elem.h',
                'rte_ring_elem_pvt.h',
index 8f82a40ec2c1135531bfd7eb3854f4e6484e050a..9ff33722b2ce45cfd45cef9a0e1e73d55c6fe4b1 100644 (file)
@@ -2,7 +2,9 @@
 # Copyright(c) 2019 Intel Corporation
 
 sources = files('rte_stack.c', 'rte_stack_std.c', 'rte_stack_lf.c')
-headers = files('rte_stack.h',
+headers = files('rte_stack.h')
+# subheaders, not for direct inclusion by apps
+indirect_headers += files(
                'rte_stack_std.h',
                'rte_stack_lf.h',
                'rte_stack_lf_generic.h',
index d69678386e47c4be83504540fddbc2a6f657bbb2..aa1e1d0385b279efb38d81676d3c4a57346e6c0f 100644 (file)
@@ -20,7 +20,6 @@ headers = files('rte_table.h',
                'rte_table_hash.h',
                'rte_table_hash_cuckoo.h',
                'rte_table_hash_func.h',
-               'rte_table_hash_func_arm64.h',
                'rte_lru.h',
                'rte_table_array.h',
                'rte_table_stub.h',
@@ -28,6 +27,6 @@ headers = files('rte_table.h',
                'rte_swx_table_em.h',)
 deps += ['mbuf', 'port', 'lpm', 'hash', 'acl']
 
-if arch_subdir == 'x86'
-       headers += files('rte_lru_x86.h')
-endif
+indirect_headers += files('rte_lru_x86.h',
+               'rte_lru_arm64.h',
+               'rte_table_hash_func_arm64.h')
index 44f0a6214240fbef95d0a925798c3d5a34bad662..7712aa4977010572a9c72bef02ce930590f25975 100644 (file)
@@ -66,6 +66,7 @@ foreach l:libraries
        use_function_versioning = false
        sources = []
        headers = []
+       indirect_headers = [] # public headers not directly included by apps
        includes = []
        cflags = default_cflags
        objs = [] # other object files to link against, used e.g. for
@@ -103,6 +104,8 @@ foreach l:libraries
                enabled_libs += name
                dpdk_conf.set('RTE_LIB_' + name.to_upper(), 1)
                install_headers(headers)
+               install_headers(indirect_headers)
+               dpdk_chkinc_headers += headers
 
                libname = 'rte_' + name
                includes += include_directories(dir_name)
index 2b9c37eb42ace3ff30d47c307f5e6b5d190f940a..fcc4d4c900aba0125954e6d3b385df5e186de44c 100644 (file)
@@ -16,6 +16,7 @@ cc = meson.get_compiler('c')
 dpdk_conf = configuration_data()
 dpdk_libraries = []
 dpdk_static_libraries = []
+dpdk_chkinc_headers = []
 dpdk_driver_classes = []
 dpdk_drivers = []
 dpdk_extra_ldflags = []
@@ -67,6 +68,11 @@ if get_option('enable_kmods')
        subdir('kernel')
 endif
 
+# check header includes if requested
+if get_option('check_includes')
+       subdir('buildtools/chkincs')
+endif
+
 # write the build config
 build_cfg = 'rte_build_config.h'
 configure_file(output: build_cfg,
index 4604328224986eead5c0e63891b48c8ecf073b64..5c382487da7d7e266112b5ccc433ec01d1c1d2ff 100644 (file)
@@ -1,5 +1,7 @@
 # Please keep these options sorted alphabetically.
 
+option('check_includes', type: 'boolean', value: false,
+       description: 'build "chkincs" to verify each header file can compile alone')
 option('disable_drivers', type: 'string', value: '',
        description: 'Comma-separated list of drivers to explicitly disable.')
 option('drivers_install_subdir', type: 'string', value: 'dpdk/pmds-<VERSION>',