Reapply "[lldb/cmake] Plugin layering enforcement mechanism (#144543)" (#145305)

The only difference from the original PR are the added BRIEF and
FULL_DOCS arguments to define_property, which are required for
cmake<3.23.
This commit is contained in:
Pavel Labath 2025-06-24 11:10:35 +02:00 committed by GitHub
parent a201f8872a
commit 46e1e9f104
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 221 additions and 0 deletions

View File

@ -37,6 +37,7 @@ endif()
include(LLDBConfig)
include(AddLLDB)
include(LLDBLayeringCheck)
set(LLDB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
@ -127,6 +128,8 @@ add_subdirectory(source)
add_subdirectory(tools)
add_subdirectory(docs)
check_lldb_plugin_layering()
if (LLDB_ENABLE_PYTHON)
if(LLDB_BUILD_FRAMEWORK)
set(lldb_python_target_dir "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/Resources/Python/lldb")

View File

@ -0,0 +1,76 @@
foreach (scope DIRECTORY TARGET)
define_property(${scope} PROPERTY LLDB_PLUGIN_KIND INHERITED
BRIEF_DOCS "LLDB plugin kind (Process, SymbolFile, etc.)"
FULL_DOCS "See lldb/docs/resources/contributing.rst"
)
define_property(${scope} PROPERTY LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES INHERITED
BRIEF_DOCS "LLDB plugin kinds which the plugin can depend on"
FULL_DOCS "See lldb/docs/resources/contributing.rst"
)
define_property(${scope} PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES INHERITED
BRIEF_DOCS "LLDB plugin kinds which are depended on for historic reasons."
FULL_DOCS "See lldb/docs/resources/contributing.rst"
)
endforeach()
option(LLDB_GENERATE_PLUGIN_DEP_GRAPH OFF)
function(check_lldb_plugin_layering)
get_property(plugins GLOBAL PROPERTY LLDB_PLUGINS)
foreach (plugin ${plugins})
get_property(plugin_kind TARGET ${plugin} PROPERTY LLDB_PLUGIN_KIND)
get_property(acceptable_deps TARGET ${plugin}
PROPERTY LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES)
get_property(tolerated_deps TARGET ${plugin}
PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES)
# A plugin is always permitted to depend on its own kind for the purposes
# subclassing. Ideally the intra-kind dependencies should not form a loop,
# but we're not checking that here.
list(APPEND acceptable_deps ${plugin_kind})
list(APPEND all_plugin_kinds ${plugin_kind})
get_property(link_libs TARGET ${plugin} PROPERTY LINK_LIBRARIES)
foreach (link_lib ${link_libs})
if(link_lib IN_LIST plugins)
get_property(lib_kind TARGET ${link_lib} PROPERTY LLDB_PLUGIN_KIND)
if (lib_kind)
if (lib_kind IN_LIST acceptable_deps)
set(dep_kind green)
elseif (lib_kind IN_LIST tolerated_deps)
set(dep_kind yellow)
else()
set(dep_kind red)
message(SEND_ERROR "Plugin ${plugin} cannot depend on ${lib_kind} "
"plugin ${link_lib}")
endif()
list(APPEND dep_${dep_kind}_${plugin_kind}_${lib_kind} ${plugin})
endif()
endif()
endforeach()
endforeach()
if (LLDB_GENERATE_PLUGIN_DEP_GRAPH)
set(dep_graph "digraph Plugins {\n")
list(REMOVE_DUPLICATES all_plugin_kinds)
foreach (from ${all_plugin_kinds})
foreach (to ${all_plugin_kinds})
foreach (dep_kind green yellow red)
if (dep_${dep_kind}_${from}_${to})
list(REMOVE_DUPLICATES dep_${dep_kind}_${from}_${to})
string(REGEX REPLACE "lldbPlugin|${from}" "" short_deps
"${dep_${dep_kind}_${from}_${to}}")
string(JOIN "\n" plugins ${short_deps})
string(APPEND dep_graph
" ${from}->${to}[color=\"${dep_kind}\" label=\"${plugins}\"];\n")
endif()
endforeach()
endforeach()
endforeach()
string(APPEND dep_graph "}\n")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lldb-plugin-deps.dot" "${dep_graph}")
endif()
endfunction()

View File

@ -56,6 +56,56 @@ subset of LLDB tests (the API tests) use a different system. Refer to the
`lldb/test <https://github.com/llvm/llvm-project/tree/main/lldb/test>`_ folder
for examples.
LLDB plugins and their dependencies
-----------------------------------
LLDB has a concept of *plugins*, which are used to provide abstraction
boundaries over functionality that is specific to a certain architecture,
operating system, programming language, etc. A plugin implements an abstract
base class (rarely, a set of related base classes), which is a part of LLDB
core. This setup allows the LLDB core to remain generic while making it possible
to support for new architectures, languages, and so on. For this to work, all
code needs to obey certain rules.
The principal rule is that LLDB core (defined as: everything under lldb/source
*minus* lldb/source/Plugins) must not depend on any specific plugin. The only
way it can interact with them is through the abstract interface. Explicit
dependencies such as casting the base class to the plugin type are not permitted
and neither are more subtle dependencies like checking the name plugin or or
other situations where some code in LLDB core is tightly coupled to the
implementation details of a specific plugin.
The rule for interaction between different plugins is more nuanced. We recognize
that some cross-plugin dependencies are unavoidable or even desirable. For
example, a plugin may want to extend a plugin of the same kind to
add/override/refine some functionality (e.g., Android is a "kind of" Linux, but
it handles some things differently). Alternatively, a plugin of one kind may
want to build on the functionality offered by a specific plugin of another kind
(ELFCore Process plugin uses ELF ObjectFile plugin to create a process out of an
ELF core file).
In cases such as these, direct dependencies are acceptable. However, to keep the
dependency graph manageable, we still have some rules to govern these
relationships:
* All dependencies between plugins of the same kind must flow in the same
direction (if plugin `A1` depends on plugin `B1`, then `B2` must not depend on
`A2`)
* Dependency graph of plugin kinds must not contain loops (dependencies like
`A1->B1`, `B2->C2` and `C3->A3` are forbidden because they induce a cycle in
the plugin kind graph even though the plugins themselves are acyclical)
The first of these rules is checked via CMake scripts (using the
`LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES` property). Dependencies in this category
are expected and permitted (subject to other constraints such as that dependency
making sense for the particular pair of plugins). Unfortunately, due to historic
reasons, not all plugin dependencies follow this rule, which is why we have
another category called `LLDB_TOLERATED_PLUGIN_DEPENDENCIES`. New dependencies
are forbidden (even though they are accepted by CMake) and existing ones should
be removed whereever possible.
.. _Error handling:
Error handling and use of assertions in LLDB

View File

@ -1,3 +1,9 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND ABI)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
ProcessUtility
TypeSystem
)
foreach(target AArch64 ARM ARC Hexagon LoongArch Mips MSP430 PowerPC RISCV SystemZ X86)
if (${target} IN_LIST LLVM_TARGETS_TO_BUILD)
add_subdirectory(${target})

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND Architecture)
add_subdirectory(Arm)
add_subdirectory(Mips)
add_subdirectory(PPC64)

View File

@ -1 +1,3 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND Disassembler)
add_subdirectory(LLVMC)

View File

@ -1,3 +1,10 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND DynamicLoader)
set_property(DIRECTORY PROPERTY LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES ObjectFile)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
Process # part of a loop (Process<->DynamicLoader).
TypeSystem
)
add_subdirectory(Darwin-Kernel)
add_subdirectory(FreeBSD-Kernel)
add_subdirectory(MacOSX-DYLD)

View File

@ -1 +1,3 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND ExpressionParser)
add_subdirectory(Clang)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND Instruction)
add_subdirectory(ARM)
add_subdirectory(ARM64)
add_subdirectory(LoongArch)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND InstrumentationRuntime)
add_subdirectory(ASan)
add_subdirectory(ASanLibsanitizers)
add_subdirectory(MainThreadChecker)

View File

@ -1 +1,4 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND JITLoader)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES ObjectFile)
add_subdirectory(GDB)

View File

@ -1,3 +1,9 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND Language)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
LanguageRuntime
TypeSystem
)
add_subdirectory(ClangCommon)
add_subdirectory(CPlusPlus)
add_subdirectory(ObjC)

View File

@ -1,2 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND LanguageRuntime)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES TypeSystem)
add_subdirectory(CPlusPlus)
add_subdirectory(ObjC)

View File

@ -1 +1,3 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND MemoryHistory)
add_subdirectory(asan)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND ObjectContainer)
add_subdirectory(BSD-Archive)
add_subdirectory(Universal-Mach-O)
add_subdirectory(Mach-O-Fileset)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND ObjectFile)
add_subdirectory(Breakpad)
add_subdirectory(COFF)
add_subdirectory(ELF)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND OperatingSystem)
if (LLDB_ENABLE_PYTHON)
add_subdirectory(Python)
endif()

View File

@ -1,3 +1,10 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND Platform)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
DynamicLoader
ObjectContainer
Process
)
add_subdirectory(AIX)
add_subdirectory(Android)
add_subdirectory(FreeBSD)

View File

@ -1,3 +1,8 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND Process)
set_property(DIRECTORY PROPERTY LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES ObjectFile)
# This dependency is part of a loop (Process<->DynamicLoader).
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES DynamicLoader)
if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
add_subdirectory(Linux)
add_subdirectory(POSIX)

View File

@ -1,3 +1,6 @@
# TODO: Clean up this directory and its dependencies
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND ProcessUtility)
add_lldb_library(lldbPluginProcessUtility
AuxVector.cpp
FreeBSDSignals.cpp

View File

@ -1 +1,4 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND REPL)
set_property(DIRECTORY PROPERTY LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES TypeSystem)
add_subdirectory(Clang)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND RegisterTypeBuilder)
add_lldb_library(lldbPluginRegisterTypeBuilderClang PLUGIN
RegisterTypeBuilderClang.cpp

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND ScriptInterpreter)
add_subdirectory(None)
if (LLDB_ENABLE_PYTHON)
add_subdirectory(Python)

View File

@ -1,2 +1,4 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND StructuredData)
add_subdirectory(DarwinLog)

View File

@ -1,3 +1,10 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND SymbolFile)
set_property(DIRECTORY PROPERTY LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES ObjectFile)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
Language
TypeSystem # part of a loop (TypeSystem<->SymbolFile).
)
add_subdirectory(Breakpad)
add_subdirectory(CTF)
add_subdirectory(DWARF)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND SymbolLocator)
# Order matters here: the first symbol locator prevents further searching.
# For DWARF binaries that are both stripped and split, the Default plugin
# will return the stripped binary when asked for the ObjectFile, which then

View File

@ -1,3 +1,6 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND SymbolVendor)
set_property(DIRECTORY PROPERTY LLDB_ACCEPTABLE_PLUGIN_DEPENDENCIES ObjectFile)
add_subdirectory(ELF)
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")

View File

@ -1 +1,4 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND SystemRuntime)
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES TypeSystem)
add_subdirectory(MacOSX)

View File

@ -1,3 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND Trace)
option(LLDB_BUILD_INTEL_PT "Enable Building of Intel(R) Processor Trace Tool" OFF)
add_subdirectory(common)

View File

@ -1,2 +1,4 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND TraceExporter)
add_subdirectory(common)
add_subdirectory(ctf)

View File

@ -1 +1,5 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND TypeSystem)
# This dependency is part of a loop (TypeSystem<->SymbolFile).
set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES SymbolFile)
add_subdirectory(Clang)

View File

@ -1,2 +1,4 @@
set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND UnwindAssembly)
add_subdirectory(InstEmulation)
add_subdirectory(x86)