【问题标题】:How to use the tool include-what-you-use together with CMake to detect unused headers?如何使用 include-what-you-use 工具与 CMake 一起检测未使用的标头?
【发布时间】:2015-09-06 05:23:37
【问题描述】:

工具include-what-you-use 可用于检测不需要的标头。我在我的 C++ 软件项目中使用CMake。如何指示 CMake 在我的软件项目的源文件中自动运行 include-what-you-use?

【问题讨论】:

  • 我需要在我的 CMake 项目中使用 include-what-you-use。当我发现这种方法时,我认为将其记录为其他人的 stackoverflow 问题是一个好主意。根据documentation 鼓励自我回答
  • 当您提出问题时,甚至还有一个“回答您自己的问题”复选框。

标签: c++ cmake header-files


【解决方案1】:

CMake 3.3引入了新的目标属性CXX_INCLUDE_WHAT_YOU_USE,可以设置为程序include-what-you-use的路径。例如这个 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})

能够构建文件main.cc

#include <iostream>
#include <vector>

int main() {
  std::cout << "Hello World!" << std::endl;
  return 0;
}

同时有include-what-you-use发出警告 不需要包含的标题 vector

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$

如果您想将自定义选项传递给include-what-you-use,例如--mapping_file,您可以通过

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})

【讨论】:

  • 在我的机器上,iwyu 从不发出任何关于额外包含的警告:/
【解决方案2】:

如果您无法访问 CMake 3.3,include-what-you-use 附带一个名为 iwyu_tool.py 的 Python 工具,它可以做您想做的事情。

它通过解析 JSON 编译数据库来工作,该数据库很容易用 CMake 生成(见下文)。

手动运行工具

假设您的项目已经有一个 CMake 构建目录,您首先需要告诉 CMake 生成编译数据库:

$ cd build
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .

这会生成一个文件compile_commands.json,其中包含项目中每个目标文件的编译器调用。您无需重新构建项目。

您现在可以通过在构建目录上运行 python 工具在您的项目上运行 include-what-you-use

$ python /path/to/iwyu_tool.py -p .

为您的 cmake 项目添加自定义目标

下面的sn-p可以用来给cmake项目添加iwyu目标。

# Generate clang compilation database
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

find_package(PythonInterp)
find_program(iwyu_tool_path NAMES iwyu_tool.py)
if (iwyu_tool_path AND PYTHONINTERP_FOUND)
  add_custom_target(iwyu
    ALL      # Remove ALL if you don't iwyu to be run by default.
    COMMAND "${PYTHON_EXECUTABLE}" "${iwyu_tool_path}" -p "${CMAKE_BINARY_DIR}"
    COMMENT "Running include-what-you-use tool"
    VERBATIM
  )
endif()

注意事项

include-what-you-use 二进制文件需要在您的路径中,以上任何一项才能正常工作。

默认情况下,iwyu_tool.py 是单线程的,这对于大型项目可能会很慢。您可以使用--jobs 参数来增加将并行处理的源文件的数量。

【讨论】:

  • 我在最新的源代码中找不到 iwyu_tool.py。什么是等价的?
  • @bysreg 你说的是从http://include-what-you-use.org/downloads/ 下载的include-what-you-use-0.7.src.tar.gz 吗? iwyu_tool.py 似乎仍然存在,尽管它深深地嵌套在目录结构中。或者,只需从 github page 下载脚本。
  • 啊,你是对的。我使用的是 clang 3.4 分支,它没有 iwyu_tool.py。该文件仅存在于 clang 3.6 以上。感谢您的帮助!
  • 请注意,像这样运行该工具不会像使用 make -j 那样利用任何并行性。
  • 它被称为iwyu_tool 而不是iwyu-tool。您可能想要更正您的答案,或者其他人可能会遇到与我在搜索后者时遇到的类似情况,但在任何地方都找不到该工具。
【解决方案3】:

您也可以通过设置 cmake 变量在 cmake 脚本之外全局启用它:

cmake -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu" <builddir> 

然后它将在每个 CXX 目标上调用它。

【讨论】:

    【解决方案4】:

    我扩展了 Alastair Harrison 的源代码,以创建可重用的解决方案。我想出了以下应该适用于 all CMake 版本:

    文件iwyu.cmake

    #.rst:
    # include-what-you-use (iwyu)
    # ----------------------------
    #
    # Allows to run the static code analyzer `include-what-you-use (iwyu)
    # <http://include-what-you-use.org>`_ as a custom target with the build system
    # `CMake <http://cmake.org>`_.
    #
    # .. topic:: Dependencies
    #
    #  This module requires the following *CMake* modules:
    #
    #  * ``FindPythonInterp``
    #
    # .. topic:: Contributors
    #
    #  * Florian Wolters <wolters.fl@gmail.com>
    
    #===============================================================================
    # Copyright 2015 Florian Wolters
    #
    # Distributed under the Boost Software License, Version 1.0. (See accompanying
    # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    #===============================================================================
    
    # ------------------------------------------------------------------------------
    # Include guard for this file.
    # ------------------------------------------------------------------------------
    
    if(iwyu_included)
      return()
    endif()
    
    set(iwyu_included TRUE)
    
    option(BUILD_IWYU
           "Run the include-what-you-use static analyzer on the source code of the project."
           OFF)
    
    function(iwyu_enable)
      set(iwyu_EXECUTABLE_NAME include-what-you-use)
      find_program(iwyu_EXECUTABLE ${iwyu_EXECUTABLE_NAME})
    
      if(iwyu_EXECUTABLE)
        # This is not exactly the same behavior as with CMake v3.3, since here all
        # compiled targets are analyzed.
        set(iwyu_tool_EXECUTABLE_NAME iwyu_tool.py)
    
        find_package(PythonInterp)
        find_program(iwyu_tool_EXECUTABLE ${iwyu_tool_EXECUTABLE_NAME})
    
        if(PYTHONINTERP_FOUND AND iwyu_tool_EXECUTABLE)
          set(CMAKE_EXPORT_COMPILE_COMMANDS ON PARENT_SCOPE)
    
          add_custom_target(iwyu
                            ALL
                            COMMAND "${PYTHON_EXECUTABLE}" "${iwyu_tool_EXECUTABLE}" -p "${CMAKE_BINARY_DIR}"
                            COMMENT "Running the ${iwyu_tool_EXECUTABLE_NAME} compilation database driver"
                            VERBATIM)
        else()
          message(STATUS
                  "Unable to find the Python interpreter and/or the ${iwyu_tool_EXECUTABLE_NAME} script")
        endif()
      else()
        message(STATUS "Unable to find the ${iwyu_EXECUTABLE_NAME} executable")
      endif()
    endfunction()
    

    文件CMakeLists.txt

    cmake_minimum_required(VERSION 3.0)
    
    include(iwyu.cmake)
    
    project(hello_world)
    add_executable(${PROJECT_NAME} main.cc)
    
    if(BUILD_IWYU)
      iwyu_enable()
    endif()
    

    如下调用 CMake 以在调用 all 目标时运行 include-what-you-use

    cmake -DBUILD_IWYU=ON <path-to-source>
    cmake --build . --target all
    

    输出应该如下:

    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/wolters/workspace/include-what-you-use_example/build
    [ 66%] Built target hello_world
    [100%] Running the iwyu_tool.py compilation database driver
    
    /home/wolters/workspace/include-what-you-use_example/develop/main.cc should add these lines:
    
    /home/wolters/workspace/include-what-you-use_example/develop/main.cc should remove these lines:
    - #include <vector>  // lines 1-1
    
    The full include-list for /home/wolters/workspace/include-what-you-use_example/develop/main.cc:
    #include <iostream>  // for operator<<, basic_ostream, cout, endl, ostream
    ---
    [100%] Built target iwyu
    

    编辑 2015-08-19: CMake 属性 &lt;LANG&gt;_INCLUDE_WHAT_YOU_USE 的方法不适用于 CMake 3.3 版。 1.因此我更新了解决方案。

    编辑 2015-09-30: 输出错误,因为我的 include-what-you-use 安装已损坏。 include-what-you-useiwyu_tool.py 文件必须与 clangclang++ 等位于同一目录中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-12
      • 1970-01-01
      • 2021-06-29
      • 2019-01-12
      • 1970-01-01
      • 2020-08-18
      • 2015-12-02
      相关资源
      最近更新 更多