web-dev-qa-db-ja.com

このツールをCMakeと一緒に使用して、未使用のヘッダーを検出する方法は?

ツール - include-what-you-use は、不要なヘッダーを検出するために使用できます。 C++ソフトウェアプロジェクトに CMake を使用しています。ソフトウェアプロジェクトのソースファイルに対して、使用するものを自動的に実行するようにCMakeに指示するにはどうすればよいですか?

44
Erik Sjölund

CMake 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)
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})
51
Erik Sjölund

CMake 3.3にアクセスできない場合は、include-what-you-useにpythonというツールがあります iwyu_tool.py と呼ばれます。

CMakeで簡単に作成できるclangコンパイルデータベースを解析することで機能します。

ツールを手動で実行する

プロジェクトの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プロジェクトにカスタムターゲットを追加する

次のスニペットを使用して、iwyuターゲットをcmakeプロジェクトに追加できます。

# 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バイナリがパスに含まれている必要があります。

23

Cmake変数を設定して、cmakeスクリプトの外部でグローバルに有効にすることもできます。

cmake -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu" <builddir> 

その後、各CXXターゲットで呼び出します。

6
user7159222

再利用可能なソリューションを作成するために、Alastair Harrisonのソースコードを拡張しました。 allCMakeバージョンで動作するはずの以下を思いつきました:

ファイル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 <[email protected]>

#===============================================================================
# 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を呼び出して、include-what-you-useを実行しますallターゲットが呼び出されます:

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プロパティ<LANG>_INCLUDE_WHAT_YOU_USEを使用したアプローチはCMakeバージョン3.3.1。したがって、ソリューションを更新しました。

2015-09-30の編集:include-what-you-useインストールが壊れていたため、出力が間違っていました。 include-what-you-useおよびiwyu_tool.pyファイルは、clangclang++などと同じディレクトリに存在する必要があります。

2
Florian Wolters