Инструмент include-what-you-use
может использоваться для обнаружения ненужных заголовков. Я использую CMake для моего программного проекта на С++. Как я могу заставить CMake запускать include-what-you-use автоматически в исходных файлах моего программного проекта?
Как использовать инструмент include-what-you-use вместе с CMake для обнаружения неиспользуемых заголовков?
Ответ 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)
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
выдать предупреждение о том, что
включенный вектор заголовка не требуется.
[email protected]:/tmp$ ls ~/hello
CMakeLists.txt main.cc
[email protected]:/tmp$ mkdir /tmp/build
use[email protected]:/tmp$ cd /tmp/build
[email protected]:/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
[email protected]:/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
[email protected]:/tmp/build$ ./hello
Hello World!
[email protected]:/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})
Ответ 2
Если у вас нет доступа к CMake 3.3, include-what-you-use
поставляется с инструментом python под названием iwyu_tool.py, который может делать то, что вы хотите.
Это работает путем разбора базы данных компиляции clang, которая легко создается с помощью CMake.
Запуск инструмента вручную
Предполагая, что у вас уже есть CMake build dir для вашего проекта, сначала вам нужно сообщить CMake, чтобы создать базу данных компиляции:
$ cd build
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
Это создает файл compile_commands.json
, содержащий вызовы компилятора для каждого объектного файла в вашем проекте. Вам не нужно перестраивать проект.
Теперь вы можете запустить include-what-you-use
в своем проекте, запустив инструмент python в каталоге сборки:
$ 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
должен быть на вашем пути для правильной работы любого из вышеперечисленных.
Ответ 3
Вы также можете включить его глобально вне cmake script, установив переменную cmake:
cmake -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu" <builddir>
Затем он вызывается на каждую цель CXX.
Ответ 4
Я расширил исходный код от Alastair Harrison, чтобы создать многоразовое решение. Я придумал следующее, которое должно работать с всеми версиями 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 <wolte[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
и iwyu_tool.py
должны находиться в том же каталоге, что и clang
, clang++
и т.д.