Dear Burt,

This is of interest, but I have concerns about boiling the ocean at this point 
in the release cycle. Please hold any patches on this topic until well after 
the 17.10 RC1 throttle branch pull.

Although we haven’t caused ourselves massive pain with similar work - coding 
standards cleanup, build-related directory refactoring - I’m not convinced that 
restructuring existing header files is worth the pain it may cause.

Direct inclusion creates ordering requirements which are at least as annoying 
as unnecessary build dependencies.

Thanks… Dave

From: vpp-dev-boun...@lists.fd.io [mailto:vpp-dev-boun...@lists.fd.io] On 
Behalf Of Burt Silverman
Sent: Friday, September 22, 2017 9:39 PM
To: vpp-dev <vpp-dev@lists.fd.io>
Subject: [vpp-dev] Practical use of the include-what-you-use tool for 
individual developers

This is a follow up on my recent post about the include-what-you-use tool. I 
discovered a way that you can use this tool to include a more appropriate set 
of header files in the files that you develop than would otherwise be the case.

The stated philosophy behind the tool is that you should directly include all 
header files that are used by a file. If struct a is declared in a.h and struct 
b is declared in b.h, your .c file that references both struct a and struct b 
should directly include a.h and b.h. But this will lead to including many more 
files than we have typically done in vpp. My personal preference, although not 
sanctioned by the pros, is to allow indirect header file inclusion. It turns 
out that there is a simple way to do this using include-what-you-use, and it 
does not require rewriting the tool's code.

include-what-you-use will suggest which header files should be added and which 
header files should be removed from the file that you are analyzing.

Understand that the corresponding .h file to a .c file will be treated 
specially. It will be analyzed along with the .c file.

For an example, I will use vnet/tcp/builtin_client.c. First I show files that 
are suggested to be removed from builtin_client.h.

vnet/tcp/builtin_client.h should remove these lines:
- #include <svm/svm_fifo_segment.h>  // lines 28-28
- #include <vnet/ip/ip.h>  // lines 22-22
- #include <vnet/session/application_interface.h>  // lines 30-30
- #include <vnet/session/session.h>  // lines 29-29
- #include <vppinfra/error.h>  // lines 26-26
- #include <vppinfra/hash.h>  // lines 25-25

Running include-what-you-use involves running the clang C compiler, so if a 
necessary header file is missing and a type cannot be resolved, you will see 
regular compiler error messages.

After removing the header file includes above from builtin_client.h, and 
re-running include-what-you-use, we find the error:

In file included from vnet/tcp/builtin_client.c:20:
./vnet/tcp/builtin_client.h:40:3: error: unknown type name 'svm_fifo_t'
  svm_fifo_t *server_rx_fifo;
  ^

We manually search for the svm_fifo_t declaration and we see that rather than 
including svm_fifo_segment.h in builtin_client.h, we should have included 
svm_fifo.h.

Fixing that and re-running IWYU, we find

vnet/tcp/builtin_client.c:55:3: error: use of undeclared identifier 
'session_fifo_event_t' session_fifo_event_t evt;
  ^

so therefore, session.h should have been included in builtin_client.c rather 
than builtin_client.h.

We also find

vnet/tcp/builtin_client.c:258:8: error: use of undeclared identifier 
'vnet_disconnect_args_t'
              vnet_disconnect_args_t _a, *a = &_a;
              ^
so application_interface.h should have been included in builtin_client.c rather 
than builtin_client.h.

Re-running IWYU tells us that no lines need to be removed from 
builtin_client.h, however,

vnet/tcp/builtin_client.c should remove these lines:
- #include <vlibapi/api.h>  // lines 24-24
- #include <vlibmemory/api.h>  // lines 25-25
- #include <vlibsocket/api.h>  // lines 26-26
- #include <vnet/plugin/plugin.h>  // lines 19-19
- #include <vnet/vnet.h>  // lines 18-18
- #include <vpp/app/version.h>  // lines 27-27

Removing these includes, re-running IWYU indicates that no more includes need 
to be removed from either builtin_client.h or builtin_client.c, and the 
compilation is successful. We are done, and
we have

builtin_client.h includes:
#include <vnet/vnet.h>
#include <vnet/ethernet/ethernet.h>
#include <vlibmemory/unix_shared_memory_queue.h>
#include <svm/svm_fifo.h>

builtin_client.c includes:
#include <vnet/tcp/builtin_client.h>
#include <vnet/session/session.h>
#include <vnet/session/application_interface.h>

Now, if on the other hand, a developer prefers to include all the headers 
directly, like many experts like to see, the result would be:

The full include-list for vnet/tcp/builtin_client.c:
#include <vnet/tcp/builtin_client.h>
#include <string.h>                               // for memset, NULL
#include <vnet/session/application_interface.h>   // for vnet_app_attach_args_t
#include <vnet/session/session.h>                 // for stream_session_handle
#include "svm/svm_fifo.h"                         // for svm_fifo_t, svm_fif...
#include "vlib/cli.h"                             // for vlib_cli_output
#include "vlib/global_funcs.h"                    // for vlib_get_thread_main
#include "vlib/init.h"                            // for VLIB_INIT_FUNCTION
#include "vlib/node_funcs.h"                      // for vlib_process_get_ev...
#include "vlib/threads.h"                         // for vlib_get_thread_index
#include "vlibapi/api_common.h"                   // for api_main_t, api_main
#include "vlibmemory/api_common.h"                // for vl_api_memclnt_crea...
#include "vlibmemory/unix_shared_memory_queue.h"  // for unix_shared_memory_...
#include "vnet/session/application.h"             // for session_cb_vft_t
#include "vnet/session/stream_session.h"          // for stream_session_t
#include "vppinfra/clib.h"                        // for PREDICT_FALSE, ARRA...
#include "vppinfra/clib_error.h"                  // for clib_error_t
#include "vppinfra/elog.h"                        // for ELOG_DATA, ELOG_TYP...
#include "vppinfra/error.h"                       // for clib_warning, clib_...
#include "vppinfra/error_bootstrap.h"             // for ASSERT
#include "vppinfra/format.h"                      // for unformat, unformat_...
#include "vppinfra/memcpy_avx.h"                  // for clib_memcpy
#include "vppinfra/pool.h"                        // for pool_header_t, pool...
#include "vppinfra/smp.h"                         // for __sync_fetch_and_add_4
#include "vppinfra/vec.h"                         // for vec_validate, vec_add1
#include "vppinfra/vec_bootstrap.h"               // for vec_header_t, vec_len
---
and
The full include-list for vnet/tcp/builtin_client.h:
#include <pthread.h>                              // for pthread_t
#include <svm/svm_fifo.h>                         // for svm_fifo_t
#include <vlibmemory/unix_shared_memory_queue.h>  // for unix_shared_memory_...
#include <vnet/ethernet/ethernet.h>               // for ethernet_main_t
#include <vnet/vnet.h>                            // for vnet_main_t
#include <vppinfra/clib.h>                        // for u32, u64, u8, f64
#include "vlib/main.h"                            // for vlib_main_t
#include "vlib/node.h"                            // for vlib_node_registrat...
#include "vppinfra/lock.h"                        // for clib_spinlock_t
---

Again, the beauty is that a developer can focus on just his or her files, and 
come up with a short list or a long list of #includes.

I will discuss some additional fine points in a future post. In the meantime, 
note that it is somewhat tricky to get the tool to give you consistent usage of 
'"' versus '<' and '>'. Possible but a bit tricky or annoying. Roughly it 
involves having the header files installed under /usr/include, and not using 
-I. Anyway, here it was only an issue with the long list of #includes.

Regards,
Burt

_______________________________________________
vpp-dev mailing list
vpp-dev@lists.fd.io
https://lists.fd.io/mailman/listinfo/vpp-dev

Reply via email to