c++cmakeheader-filesiwyuinclude-what-you-use

How can I use the tool 'Include What You Use' together with CMake to detect unused headers?


The tool Include What You Use can be used to detect unneeded headers. I am using CMake for my C++ software project. How can I instruct CMake to run Include What You Use automatically on the source files of my software project?


Solution

  • CMake 3.3 introduced the new target property CXX_INCLUDE_WHAT_YOU_USE that can be set to the path of the program include-what-you-use. For instance this CMakeLists.txt

    cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
    add_executable(hello main.cc)
    
    find_program(iwyu_path NAMES include-what-you-use iwyu REQUIRED)
    
    # If using CGAL<3.18, you remove REQUIRED and use
    # if(NOT iwyu_path)
    #   message(FATAL_ERROR "Could not find the program include-what-you-use")
    # endif()
    
    set_property(TARGET hello PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${iwyu_path})
    

    is able to build the file main.cc

    #include <iostream>
    #include <vector>
    
    int main() {
      std::cout << "Hello World!" << std::endl;
      return 0;
    }
    

    and at the same time have include-what-you-use give out a warning that the included header vector is not needed.

    user@ubuntu:/tmp$ ls ~/hello
    CMakeLists.txt  main.cc
    user@ubuntu:/tmp$ mkdir /tmp/build
    user@ubuntu:/tmp$ cd /tmp/build
    user@ubuntu:/tmp/build$ ~/cmake-3.3.0-rc2-Linux-x86_64/bin/cmake ~/hello
    -- The C compiler identification is GNU 4.9.2
    -- The CXX compiler identification is GNU 4.9.2
    -- Check for working C compiler: /usr/bin/cc
    -- Check for working C compiler: /usr/bin/cc -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- Check for working CXX compiler: /usr/bin/c++
    -- Check for working CXX compiler: /usr/bin/c++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /tmp/build
    user@ubuntu:/tmp/build$ make
    Scanning dependencies of target hello
    [ 50%] Building CXX object CMakeFiles/hello.dir/main.cc.o
    Warning: include-what-you-use reported diagnostics:
    
    /home/user/hello/main.cc should add these lines:
    
    /home/user/hello/main.cc should remove these lines:
    - #include <vector>  // lines 2-2
    
    The full include-list for /home/user/hello/main.cc:
    #include <iostream>  // for operator<<, basic_ostream, cout, endl, ostream
    ---
    
    [100%] Linking CXX executable hello
    [100%] Built target hello
    user@ubuntu:/tmp/build$ ./hello
    Hello World!
    user@ubuntu:/tmp/build$
    

    If you want to pass custom options to include-what-you-use, like for instance --mapping_file you can do it via

    set(iwyu_path_and_options
        ${iwyu_path}
        -Xiwyu
        --mapping_file=${my_mapping})
    
    set_property(TARGET hello
        PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${iwyu_path_and_options})