Add rules for include-what-you-use
Never wonder if you have all the right headers again!
Signed-off-by: Stephan Pleines <pleines.stephan@gmail.com>
Change-Id: I0cfc3f720f343a285d0ad59e90ec357f92547806
diff --git a/.bazelrc b/.bazelrc
index be75aa1..09c943f 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -157,6 +157,30 @@
build:remote --remote_instance_name=fuse
build:remote --verbose_failures
+# How to use IWYU - Include What You Use
+# Start by deleting any *.iwyu.txt files that you might have from a previous run:
+# find -L bazel-bin/ -name "*.iwyu.txt" | xargs rm
+# Build desired target(s)
+# bazel build --config=iwyu //my:target
+# run script to fix includes
+# find -L bazel-bin/ -name "*.iwyu.txt" | \
+# xargs -I % sh -c 'external/iwyu_prebuilt_pkg/bin/fix_includes.py --nosafe_headers < $1' sh %
+# run clang-format to get includes in the right order
+# bazel run //tools/lint:clang_format
+# build targets, or ideally everything, to make sure that it still builds.
+#
+# If you are unhappy with the result, you have the following options:
+# Use pragmas or mappings.
+# https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md
+# https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUMappings.md
+# Our mapping files are in tools/iwyu.
+build:iwyu --aspects @com_github_storypku_bazel_iwyu//bazel/iwyu:iwyu.bzl%iwyu_aspect
+build:iwyu --@com_github_storypku_bazel_iwyu//:iwyu_mappings=//tools/iwyu:mappings
+build:iwyu --output_groups=report
+build:iwyu --@com_github_storypku_bazel_iwyu//:iwyu_opts=--no_fwd_decls,--cxx17ns,--verbose=3
+build:iwyu --strategy=iwyu=sandboxed,standalone
+
+
# Load a local file that users can use to customize bazel invocations. This
# should stay the last line in this file so users can override things when they
# want.
diff --git a/WORKSPACE b/WORKSPACE
index 371829f..aac52f4 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1718,3 +1718,16 @@
strip_prefix = "expected-1.1.0",
url = "https://github.com/TartanLlama/expected/archive/refs/tags/v1.1.0.tar.gz",
)
+
+http_archive(
+ name = "com_github_storypku_bazel_iwyu",
+ integrity = "sha256-R/rVwWn3SveoC8lAcicw6MOfdTqLLkubpaljT4qHjJg=",
+ strip_prefix = "bazel_iwyu-bb102395e553215abd66603bcdeb6e93c66ca6d7",
+ urls = [
+ "https://github.com/storypku/bazel_iwyu/archive/bb102395e553215abd66603bcdeb6e93c66ca6d7.zip",
+ ],
+)
+
+load("@com_github_storypku_bazel_iwyu//bazel:dependencies.bzl", "bazel_iwyu_dependencies")
+
+bazel_iwyu_dependencies()
diff --git a/tools/iwyu/BUILD.bazel b/tools/iwyu/BUILD.bazel
new file mode 100644
index 0000000..957cf94
--- /dev/null
+++ b/tools/iwyu/BUILD.bazel
@@ -0,0 +1,6 @@
+filegroup(
+ name = "mappings",
+ srcs = glob([
+ "*.imp",
+ ]),
+)
diff --git a/tools/iwyu/by_hand.imp b/tools/iwyu/by_hand.imp
new file mode 100644
index 0000000..54f271b
--- /dev/null
+++ b/tools/iwyu/by_hand.imp
@@ -0,0 +1,45 @@
+[
+ # libc++ headers
+ { "include": ["<bits/chrono.h>", "private", "<chrono>", "public"] },
+ { "include": ["<bits/types/struct_sched_param.h>", "private", "<sched.h>", "public"] },
+ { "include": ["<bits/mman-map-flags-generic.h>", "private", "<sys/mman.h>", "public"] },
+ { "include": ["<bits/std_abs.h>", "private", "<cstdlib>", "public"] },
+ { "include": ["<bits/string_fortified.h>", "private", "<string.h>", "public"] },
+ { "include": ["<bits/strings_fortified.h>", "private", "<string.h>", "public"] },
+
+ # parts of Python.h
+ { "include": ["<boolobject.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<bytesobject.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<listobject.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<longobject.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<methodobject.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<modsupport.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<moduleobject.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<object.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<pyerrors.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<pymacro.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<pyport.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<tupleobject.h>", "private", "<Python.h>", "public"] },
+ { "include": ["<unicodeobject.h>", "private", "<Python.h>", "public"] },
+
+ # seasocks
+ { "include": ["<seasocks/Logger.h>", "private", "\"seasocks/Logger.h\"", "public"] },
+
+ # libjpeg
+ { "include": ["\"third_party/libjpeg/jmorecfg.h\"", "private", "\"third_party/libjpeg/jpeglib.h\"", "public"] },
+
+ # glog
+ { "include": ["\"glog/log_severity.h\"", "private", "\"glog/logging.h\"", "public"] },
+
+ # gtest
+ { "include": ["<gtest/gtest.h>", "private", "\"gtest/gtest.h\"", "public"] },
+
+ # grpc
+ { "include": ["<grpcpp/client_context.h>", "private", "\"grpcpp/client_context.h\"", "public"] },
+ { "include": ["<grpcpp/support/status.h>", "private", "\"grpcpp/support/status.h\"", "public"] },
+ { "include": ["<grpcpp/server_context.h>", "private", "\"grpcpp/server_context.h\"", "public"] },
+ { "include": ["<grpcpp/impl/service_type.h>", "private", "\"grpcpp/impl/service_type.h\"", "public"] },
+ { "include": ["<grpcpp/security/credentials.h>", "private", "\"grpcpp/security/credentials.h\"", "public"] },
+ { "include": ["<grpcpp/server.h>", "private", "\"grpcpp/server.h\"", "public"] },
+]
+
diff --git a/tools/iwyu/gtest.imp b/tools/iwyu/gtest.imp
new file mode 100644
index 0000000..60ee552
--- /dev/null
+++ b/tools/iwyu/gtest.imp
@@ -0,0 +1,14 @@
+[
+ { include: [ "@<gtest/internal/.*>", private, "\"gtest/gtest.h\"", public ] },
+ { include: [ "<gtest/gtest_prod.h>", private, "\"gtest/gtest_prod.h\"", public ] },
+ { include: [ "@<gtest/gtest-.*>", private, "\"gtest/gtest.h\"", public ] },
+ { include: [ "@\"gtest/internal/.*\"", private, "\"gtest/gtest.h\"", public ] },
+ { include: [ "@\"gtest/gtest-.*\"", private, "\"gtest/gtest.h\"", public ] },
+ { include: [ "@<gmock/internal/.*>", private, "\"gmock/gmock.h\"", public ] },
+ { include: [ "@<gmock/gmock-.*>", private, "\"gmock/gmock.h\"", public ] },
+ { include: [ "<gmock/gmock.h>", private, "\"gmock/gmock.h\"", public ] },
+ { include: [ "@\"gmock/internal/.*\"", private, "\"gmock/gmock.h\"", public ] },
+ { include: [ "@\"gmock/gmock-.*\"", private, "\"gmock/gmock.h\"", public ] },
+ { include: [ "<gtest/gtest_pred_impl.h>", private, "\"gtest/gtest.h\"", public ] },
+ { include: [ "\"gtest/gtest_pred_impl.h\"", private, "\"gtest/gtest.h\"", public ] },
+]
diff --git a/tools/iwyu/libcxx.imp b/tools/iwyu/libcxx.imp
new file mode 100644
index 0000000..609f4af
--- /dev/null
+++ b/tools/iwyu/libcxx.imp
@@ -0,0 +1,80 @@
+# libc++ headers
+[
+ { "include": ["<__mutex_base>", "private", "<mutex>", "public"] },
+ { "include": ["<__tree>", "private", "<set>", "public"] },
+ { "include": ["<__tree>", "private", "<map>", "public"] },
+
+ # For the following entries:
+ # cd llvm-project/libcxx/include ; find -type d -name "__*" | sort | sed -e 's#./__\(.*\)# { "include": ["@<__\1/.*>", "private", "<\1>", "public"] },#'
+ #
+ # tweak locale_dir entry, and comment out debug_utils, fwd, pstl, support
+ { "include": ["@<__algorithm/.*>", "private", "<algorithm>", "public"] },
+ { "include": ["@<__atomic/.*>", "private", "<atomic>", "public"] },
+ { "include": ["@<__bit/.*>", "private", "<bit>", "public"] },
+ { "include": ["@<__charconv/.*>", "private", "<charconv>", "public"] },
+ { "include": ["@<__chrono/.*>", "private", "<chrono>", "public"] },
+ { "include": ["@<__compare/.*>", "private", "<compare>", "public"] },
+ { "include": ["@<__concepts/.*>", "private", "<concepts>", "public"] },
+ { "include": ["@<__condition_variable/.*>", "private", "<condition_variable>", "public"] },
+ { "include": ["@<__coroutine/.*>", "private", "<coroutine>", "public"] },
+ #{ "include": ["@<__debug_utils/.*>", "private", "<debug_utils>", "public"] },
+ { "include": ["@<__exception/.*>", "private", "<exception>", "public"] },
+ { "include": ["@<__expected/.*>", "private", "<expected>", "public"] },
+ { "include": ["@<__filesystem/.*>", "private", "<filesystem>", "public"] },
+ { "include": ["@<__format/.*>", "private", "<format>", "public"] },
+ { "include": ["@<__functional/.*>", "private", "<functional>", "public"] },
+ #{ "include": ["@<__fwd/.*>", "private", "<fwd>", "public"] },
+ { "include": ["@<__ios/.*>", "private", "<ios>", "public"] },
+ { "include": ["@<__iterator/.*>", "private", "<iterator>", "public"] },
+ { "include": ["@<__locale_dir/.*>", "private", "<locale>", "public"] },
+ { "include": ["@<__mdspan/.*>", "private", "<mdspan>", "public"] },
+ { "include": ["@<__memory/.*>", "private", "<memory>", "public"] },
+ { "include": ["@<__memory_resource/.*>", "private", "<memory_resource>", "public"] },
+ { "include": ["@<__mutex/.*>", "private", "<mutex>", "public"] },
+ { "include": ["@<__numeric/.*>", "private", "<numeric>", "public"] },
+ #{ "include": ["@<__pstl/.*>", "private", "<pstl>", "public"] },
+ { "include": ["@<__random/.*>", "private", "<random>", "public"] },
+ { "include": ["@<__ranges/.*>", "private", "<ranges>", "public"] },
+ { "include": ["@<__stop_token/.*>", "private", "<stop_token>", "public"] },
+ { "include": ["@<__string/.*>", "private", "<string>", "public"] },
+ #{ "include": ["@<__support/.*>", "private", "<support>", "public"] },
+ { "include": ["@<__system_error/.*>", "private", "<system_error>", "public"] },
+ { "include": ["@<__thread/.*>", "private", "<thread>", "public"] },
+ { "include": ["@<__tuple/.*>", "private", "<tuple>", "public"] },
+ { "include": ["@<__type_traits/.*>", "private", "<type_traits>", "public"] },
+ { "include": ["@<__utility/.*>", "private", "<utility>", "public"] },
+ { "include": ["@<__variant/.*>", "private", "<variant>", "public"] },
+
+ # For the following entries:
+ # cd llvm-project/libcxx/include ; find __fwd -type f -name "*.h" | sort | sed -e 's#__fwd/\(.*\).h# { "include": ["<__fwd/\1.h>", "private", "<\1>", "public"] },#'
+ #
+ # tweak hash, pair, subrange entries, and comment out bit_reference, get
+ { "include": ["<__fwd/array.h>", "private", "<array>", "public"] },
+ #{ "include": ["<__fwd/bit_reference.h>", "private", "<bit_reference>", "public"] },
+ { "include": ["<__fwd/fstream.h>", "private", "<fstream>", "public"] },
+ #{ "include": ["<__fwd/get.h>", "private", "<get>", "public"] },
+ { "include": ["<__fwd/hash.h>", "private", "<functional>", "public"] },
+ { "include": ["<__fwd/ios.h>", "private", "<ios>", "public"] },
+ { "include": ["<__fwd/istream.h>", "private", "<istream>", "public"] },
+ { "include": ["<__fwd/mdspan.h>", "private", "<mdspan>", "public"] },
+ { "include": ["<__fwd/memory_resource.h>", "private", "<memory_resource>", "public"] },
+ { "include": ["<__fwd/ostream.h>", "private", "<ostream>", "public"] },
+ { "include": ["<__fwd/pair.h>", "private", "<utility>", "public"] },
+ { "include": ["<__fwd/span.h>", "private", "<span>", "public"] },
+ { "include": ["<__fwd/sstream.h>", "private", "<sstream>", "public"] },
+ { "include": ["<__fwd/streambuf.h>", "private", "<streambuf>", "public"] },
+ { "include": ["<__fwd/string.h>", "private", "<string>", "public"] },
+ { "include": ["<__fwd/string_view.h>", "private", "<string_view>", "public"] },
+ { "include": ["<__fwd/subrange.h>", "private", "<ranges>", "public"] },
+ { "include": ["<__fwd/tuple.h>", "private", "<tuple>", "public"] },
+
+ { "symbol": [ "std::nullptr_t", "private", "<cstddef>", "public"] },
+
+ # For older MacOS libc++ (13.0.0), on macOS Ventura (13.2.1)
+ { "include": ["<__functional_base>", "private", "<functional>", "public"] },
+
+ # For older libc++ (16.x)
+ { "include": ["@<__tuple_dir/.*>", "private", "<tuple>", "public"] },
+
+ { "symbol": [ "std::string", "private", "<string>", "public"] },
+]