Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32#3# Copyright (c) 2018-present The Bitcoin Core developers4# Distributed under the MIT software license, see the accompanying5# file COPYING or http://www.opensource.org/licenses/mit-license.php.6#7# Check for duplicate includes.8# Guard against accidental introduction of new Boost dependencies.9# Check includes: Check for duplicate includes. Enforce bracket syntax includes.11import os12import re13import sys15from subprocess import check_output, CalledProcessError17from lint_ignore_dirs import SHARED_EXCLUDED_SUBTREES20EXCLUDED_DIRS = ["contrib/devtools/bitcoin-tidy/",21] + SHARED_EXCLUDED_SUBTREES23EXPECTED_BOOST_INCLUDES = [24"boost/multi_index/detail/hash_index_iterator.hpp",25"boost/multi_index/hashed_index.hpp",26"boost/multi_index/identity.hpp",27"boost/multi_index/indexed_by.hpp",28"boost/multi_index/ordered_index.hpp",29"boost/multi_index/sequenced_index.hpp",30"boost/multi_index/tag.hpp",31"boost/multi_index_container.hpp",32"boost/operators.hpp",33"boost/test/included/unit_test.hpp",34"boost/test/unit_test.hpp",35"boost/tuple/tuple.hpp",36]39def get_toplevel():40return check_output(["git", "rev-parse", "--show-toplevel"], text=True).rstrip("\n")43def list_files_by_suffix(suffixes):44exclude_args = [":(exclude)" + dir for dir in EXCLUDED_DIRS]46files_list = check_output(["git", "ls-files", "src"] + exclude_args, text=True).splitlines()48return [file for file in files_list if file.endswith(suffixes)]51def find_duplicate_includes(include_list):52tempset = set()53duplicates = set()55for inclusion in include_list:56if inclusion in tempset:57duplicates.add(inclusion)58else:59tempset.add(inclusion)61return duplicates64def find_included_cpps():65included_cpps = list()67try:68included_cpps = check_output(["git", "grep", "-E", r"^#include [<\"][^>\"]+\.cpp[>\"]", "--", "*.cpp", "*.h"], text=True).splitlines()69except CalledProcessError as e:70if e.returncode > 1:71raise e73# Exception: `#include <moc_*.cpp>` statements in src/qt source files are permitted.74# See:75# - https://doc.qt.io/qt-6/moc.html76# - https://cmake.org/cmake/help/latest/prop_tgt/AUTOMOC.html77return [i for i in included_cpps if not re.match(r"src/qt/[^:]+\.cpp:#include <moc_[^<>:]+\.cpp>$", i)]80def find_extra_boosts():81included_boosts = list()82filtered_included_boost_set = set()83exclusion_set = set()85try:86included_boosts = check_output(["git", "grep", "-E", r"^#include <boost/", "--", "*.cpp", "*.h"], text=True).splitlines()87except CalledProcessError as e:88if e.returncode > 1:89raise e91for boost in included_boosts:92filtered_included_boost_set.add(re.findall(r'(?<=\<).+?(?=\>)', boost)[0])94for expected_boost in EXPECTED_BOOST_INCLUDES:95for boost in filtered_included_boost_set:96if expected_boost in boost:97exclusion_set.add(boost)99extra_boosts = set(filtered_included_boost_set.difference(exclusion_set))101return extra_boosts104def find_quote_syntax_inclusions():105exclude_args = [":(exclude)" + dir for dir in EXCLUDED_DIRS]106quote_syntax_inclusions = list()108try:109quote_syntax_inclusions = check_output(["git", "grep", r"^#include \"", "--", "*.cpp", "*.h"] + exclude_args, text=True).splitlines()110except CalledProcessError as e:111if e.returncode > 1:112raise e114return quote_syntax_inclusions117def main():118exit_code = 0120os.chdir(get_toplevel())122# Check for duplicate includes123for filename in list_files_by_suffix((".cpp", ".h")):124with open(filename, "r") as file:125include_list = [line.rstrip("\n") for line in file if re.match(r"^#include", line)]127duplicates = find_duplicate_includes(include_list)129if duplicates:130print(f"Duplicate include(s) in {filename}:")131for duplicate in duplicates:132print(duplicate)133print("")134exit_code = 1136# Check if code includes .cpp-files137included_cpps = find_included_cpps()139if included_cpps:140print("The following files #include .cpp files:")141for included_cpp in included_cpps:142print(included_cpp)143print("")144exit_code = 1146# Guard against accidental introduction of new Boost dependencies147extra_boosts = find_extra_boosts()149if extra_boosts:150for boost in extra_boosts:151print(f"A new Boost dependency in the form of \"{boost}\" appears to have been introduced:")152print(check_output(["git", "grep", boost, "--", "*.cpp", "*.h"], text=True))153exit_code = 1155# Check if Boost dependencies are no longer used156for expected_boost in EXPECTED_BOOST_INCLUDES:157try:158check_output(["git", "grep", "-q", r"^#include <%s>" % expected_boost, "--", "*.cpp", "*.h"], text=True)159except CalledProcessError as e:160if e.returncode > 1:161raise e162else:163print(f"Good job! The Boost dependency \"{expected_boost}\" is no longer used. "164"Please remove it from EXPECTED_BOOST_INCLUDES in test/lint/lint-includes.py "165"to make sure this dependency is not accidentally reintroduced.\n")166exit_code = 1168# Enforce bracket syntax includes169quote_syntax_inclusions = find_quote_syntax_inclusions()170# *Rationale*: Bracket syntax is less ambiguous because the preprocessor171# searches a fixed list of include directories without taking location of the172# source file into account. This allows quoted includes to stand out more when173# the location of the source file actually is relevant.175if quote_syntax_inclusions:176print("Please use bracket syntax includes (\"#include <foo.h>\") instead of quote syntax includes:")177for quote_syntax_inclusion in quote_syntax_inclusions:178print(quote_syntax_inclusion)179exit_code = 1181sys.exit(exit_code)184if __name__ == "__main__":185main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.