| include(GNUInstallDirs) | |
| function(lldb_tablegen) | |
| # Syntax: | |
| # lldb_tablegen output-file [tablegen-arg ...] SOURCE source-file | |
| # [[TARGET cmake-target-name] [DEPENDS extra-dependency ...]] | |
| # | |
| # Generates a custom command for invoking tblgen as | |
| # | |
| # tblgen source-file -o=output-file tablegen-arg ... | |
| # | |
| # and, if cmake-target-name is provided, creates a custom target for | |
| # executing the custom command depending on output-file. It is | |
| # possible to list more files to depend after DEPENDS. | |
| cmake_parse_arguments(LTG "" "SOURCE;TARGET" "" ${ARGN}) | |
| if(NOT LTG_SOURCE) | |
| message(FATAL_ERROR "SOURCE source-file required by lldb_tablegen") | |
| endif() | |
| set(LLVM_TARGET_DEFINITIONS ${LTG_SOURCE}) | |
| if (LLVM_USE_SANITIZER MATCHES ".*Address.*") | |
| list(APPEND LTG_UNPARSED_ARGUMENTS -DLLDB_SANITIZED) | |
| endif() | |
| string(TOUPPER "${CMAKE_BUILD_TYPE}" LTG_BUILD_TYPE) | |
| if (NOT LLVM_ENABLE_ASSERTIONS AND NOT LTG_BUILD_TYPE STREQUAL "DEBUG") | |
| list(APPEND LTG_UNPARSED_ARGUMENTS -DNDEBUG) | |
| endif() | |
| tablegen(LLDB ${LTG_UNPARSED_ARGUMENTS}) | |
| if(LTG_TARGET) | |
| add_public_tablegen_target(${LTG_TARGET}) | |
| set_property(GLOBAL APPEND PROPERTY LLDB_TABLEGEN_TARGETS ${LTG_TARGET}) | |
| endif() | |
| if("-dump-json" IN_LIST ARGN) | |
| set_property(GLOBAL APPEND PROPERTY LLDB_DOCS_JSON_OUTPUTS "${TABLEGEN_OUTPUT}") | |
| endif() | |
| endfunction(lldb_tablegen) | |
| # Returns TRUE in `out_var` if any of `libs` is `liblldb` or already carries | |
| # the LLDB_LINKS_LIBLLDB property. | |
| function(_lldb_links_liblldb_check out_var libs) | |
| set(${out_var} FALSE PARENT_SCOPE) | |
| foreach(lib ${libs}) | |
| if("${lib}" STREQUAL "liblldb") | |
| set(${out_var} TRUE PARENT_SCOPE) | |
| return() | |
| endif() | |
| if(TARGET "${lib}") | |
| get_target_property(_p "${lib}" LLDB_LINKS_LIBLLDB) | |
| if(_p) | |
| set(${out_var} TRUE PARENT_SCOPE) | |
| return() | |
| endif() | |
| endif() | |
| endforeach() | |
| endfunction() | |
| function(_lldb_propagate_links_liblldb name libs) | |
| _lldb_links_liblldb_check(_links_liblldb "${libs}") | |
| set_target_properties(${name} PROPERTIES LLDB_LINKS_LIBLLDB ${_links_liblldb}) | |
| endfunction() | |
| # Records a target's undefined LLDB symbols for re-export by liblldb. | |
| # The output path is appended to the LLDB_DYNAMIC_SCRIPTINTERPRETER_SYMBOL_FILES | |
| # global property. | |
| function(lldb_record_dynamic_script_interpreter_exports target) | |
| set(symbol_file | |
| "${CMAKE_CURRENT_BINARY_DIR}/${target}.undefined.symbols") | |
| # llvm-nm is registered as a CMake target after the LLDB subdirectory is | |
| # processed, so a forward target reference is required. LLVM_NM, when set, | |
| # points to a prebuilt host tool for cross-compiled builds. | |
| if(LLVM_NM) | |
| set(nm_exe "${LLVM_NM}") | |
| set(nm_dep) | |
| else() | |
| set(nm_exe "$<TARGET_FILE:llvm-nm>") | |
| set(nm_dep llvm-nm) | |
| endif() | |
| set(extra_args) | |
| if(APPLE) | |
| list(APPEND extra_args --mach-o) | |
| endif() | |
| add_custom_command( | |
| OUTPUT ${symbol_file} | |
| COMMAND "${Python3_EXECUTABLE}" | |
| ${LLDB_SOURCE_DIR}/scripts/extract-dynamic-script-interpreter-exports.py | |
| --nm ${nm_exe} | |
| ${extra_args} | |
| -o ${symbol_file} | |
| $<TARGET_OBJECTS:${target}> | |
| DEPENDS | |
| ${LLDB_SOURCE_DIR}/scripts/extract-dynamic-script-interpreter-exports.py | |
| $<TARGET_OBJECTS:${target}> | |
| ${nm_dep} | |
| COMMAND_EXPAND_LISTS | |
| VERBATIM | |
| COMMENT "Extracting LLDB symbols required by ${target}" | |
| ) | |
| add_custom_target(${target}-exports DEPENDS ${symbol_file}) | |
| set_target_properties(${target}-exports PROPERTIES FOLDER "LLDB/API") | |
| set_property(GLOBAL APPEND PROPERTY | |
| LLDB_DYNAMIC_SCRIPTINTERPRETER_SYMBOL_FILES ${symbol_file}) | |
| endfunction() | |
| # Applies an exports file to a target's link without inserting the | |
| # order-only edge that add_llvm_symbol_exports normally adds. That edge | |
| # propagates through CMake's compile-order graph and forms a cycle when | |
| # the exports list is itself derived from a target that links the same | |
| # library. LINK_DEPENDS still triggers a relink when the file's content | |
| # changes (Ninja and Makefile generators only). | |
| function(lldb_apply_exports_file target export_file) | |
| add_llvm_symbol_exports(${target} ${export_file} | |
| NO_TARGET_DEPENDENCY | |
| OUTPUT_FILE_VAR native_export_file) | |
| set_property(TARGET ${target} APPEND PROPERTY LINK_DEPENDS | |
| ${native_export_file}) | |
| endfunction() | |
| # Configure-time scan: every #include "lldb/<Module>/..." in <SOURCES> and in | |
| # PUBLIC_HEADER_DIR (recursive) must reference OWN_MODULE or a name in | |
| # ALLOWED_MODULES, otherwise FATAL_ERROR. Catches accidental cross-module | |
| # includes that succeed at link time (e.g. on macOS) without a corresponding | |
| # CMake LINK_LIBS dependency. | |
| function(lldb_check_header_layering target) | |
| cmake_parse_arguments(HC "" "PUBLIC_HEADER_DIR;OWN_MODULE" | |
| "SOURCES;ALLOWED_MODULES" ${ARGN}) | |
| set(_files) | |
| foreach(src ${HC_SOURCES}) | |
| if(NOT IS_ABSOLUTE "${src}") | |
| set(src "${CMAKE_CURRENT_SOURCE_DIR}/${src}") | |
| endif() | |
| # PARAM_UNPARSED_ARGUMENTS in add_lldb_library carries source files | |
| # alongside llvm_add_library keywords like ADDITIONAL_HEADER_DIRS or | |
| # LINK_COMPONENTS. Skip anything that isn't an existing file. | |
| if(EXISTS "${src}" AND NOT IS_DIRECTORY "${src}") | |
| list(APPEND _files "${src}") | |
| endif() | |
| endforeach() | |
| if(HC_PUBLIC_HEADER_DIR AND EXISTS "${HC_PUBLIC_HEADER_DIR}") | |
| file(GLOB_RECURSE _public_hdrs | |
| "${HC_PUBLIC_HEADER_DIR}/*.h" "${HC_PUBLIC_HEADER_DIR}/*.hpp") | |
| list(APPEND _files ${_public_hdrs}) | |
| endif() | |
| set(_allowed ${HC_ALLOWED_MODULES} ${HC_OWN_MODULE}) | |
| foreach(file ${_files}) | |
| file(STRINGS "${file}" _includes | |
| REGEX "^[ \t]*#[ \t]*include[ \t]+\"lldb/[A-Za-z_][A-Za-z0-9_]*/") | |
| foreach(line ${_includes}) | |
| # Allow Windows system-header wrapper. | |
| if(line MATCHES "\"lldb/Host/windows/windows\\.h\"") | |
| continue() | |
| endif() | |
| string(REGEX MATCH | |
| "^[ \t]*#[ \t]*include[ \t]+\"lldb/([A-Za-z_][A-Za-z0-9_]*)/" | |
| _m "${line}") | |
| if(NOT CMAKE_MATCH_1 IN_LIST _allowed) | |
| message(FATAL_ERROR | |
| "LLDB layering: target '${target}' includes a header from " | |
| "module 'lldb/${CMAKE_MATCH_1}/' which is not in its allowlist.\n" | |
| " File: ${file}\n" | |
| " Include: ${line}\n" | |
| " Own module: ${HC_OWN_MODULE}\n" | |
| " Allowed modules: ${HC_ALLOWED_MODULES}\n" | |
| "Either remove the include or add 'lldb${CMAKE_MATCH_1}' to " | |
| "ALLOWED_INTERNAL_DEPENDENCIES.") | |
| endif() | |
| endforeach() | |
| endforeach() | |
| endfunction() | |
| function(add_lldb_library name) | |
| include_directories(BEFORE | |
| ${CMAKE_CURRENT_BINARY_DIR} | |
| ) | |
| cmake_parse_arguments(PARAM | |
| "MODULE;SHARED;STATIC;OBJECT;PLUGIN;FRAMEWORK;NO_INTERNAL_DEPENDENCIES;NO_PLUGIN_DEPENDENCIES" | |
| "INSTALL_PREFIX" | |
| "LINK_LIBS;CLANG_LIBS;ALLOWED_INTERNAL_DEPENDENCIES" | |
| ${ARGN}) | |
| foreach(link_lib ${PARAM_LINK_LIBS}) | |
| # May not be a target yet. | |
| if (NOT TARGET ${link_lib}) | |
| continue() | |
| endif() | |
| if (link_lib MATCHES "^clang") | |
| message(FATAL_ERROR "Library ${name} links against clang library ${link_lib} via LINK_LIBS but must be added via CLANG_LIBS") | |
| endif() | |
| get_target_property(_is_llvm_component ${link_lib} LLVM_COMPONENT) | |
| if (link_lib MATCHES "^LLVM" AND ${_is_llvm_component}) | |
| message(FATAL_ERROR "Library ${name} links against LLVM library ${link_lib} via LINK_LIBS but must be added via LINK_COMPONENTS") | |
| endif() | |
| endforeach() | |
| set(_check_internal_deps FALSE) | |
| if(PARAM_NO_INTERNAL_DEPENDENCIES) | |
| set(_allowed_internal_deps "") | |
| set(_check_internal_deps TRUE) | |
| elseif(DEFINED PARAM_ALLOWED_INTERNAL_DEPENDENCIES) | |
| set(_allowed_internal_deps "${PARAM_ALLOWED_INTERNAL_DEPENDENCIES}") | |
| set(_check_internal_deps TRUE) | |
| endif() | |
| if(_check_internal_deps) | |
| foreach(link_lib ${PARAM_LINK_LIBS}) | |
| if(link_lib MATCHES "^lldb" AND NOT link_lib IN_LIST _allowed_internal_deps) | |
| message(FATAL_ERROR | |
| "LLDB layering: target '${name}' has a forbidden internal dependency on '${link_lib}'.\n" | |
| " Allowed internal deps: ${_allowed_internal_deps}\n" | |
| "Add '${link_lib}' to ALLOWED_INTERNAL_DEPENDENCIES on the " | |
| "add_lldb_library(${name} ...) call, or remove it from LINK_LIBS.") | |
| endif() | |
| endforeach() | |
| # Also scan sources and public headers for forbidden cross-module | |
| # #include directives. Catches accidental layering breaks that succeed | |
| # at link time on macOS due to static linking, even without a | |
| # corresponding LINK_LIBS entry. | |
| # Map a target name to its module directory under | |
| # ${LLDB_INCLUDE_DIR}/lldb/. Top-level libraries map directly | |
| # (lldbCore -> Core); sub-libraries fold into their parent module by | |
| # longest-prefix match (lldbHostMacOSXObjCXX -> Host). | |
| macro(_lldb_module_for target_name out_var) | |
| string(REGEX REPLACE "^lldb" "" _stripped "${target_name}") | |
| if(IS_DIRECTORY "${LLDB_INCLUDE_DIR}/lldb/${_stripped}") | |
| set(${out_var} "${_stripped}") | |
| else() | |
| set(${out_var} "${_stripped}") | |
| foreach(candidate Utility Host Core Symbol Target Breakpoint | |
| Expression Interpreter API DataFormatters Commands | |
| Initialization ValueObject Version) | |
| string(LENGTH "${candidate}" _clen) | |
| string(SUBSTRING "${_stripped}" 0 ${_clen} _prefix) | |
| if(_prefix STREQUAL candidate) | |
| set(${out_var} "${candidate}") | |
| break() | |
| endif() | |
| endforeach() | |
| endif() | |
| endmacro() | |
| _lldb_module_for("${name}" _own_module) | |
| set(_allowed_modules) | |
| foreach(dep ${_allowed_internal_deps}) | |
| _lldb_module_for("${dep}" _m) | |
| list(APPEND _allowed_modules "${_m}") | |
| endforeach() | |
| list(REMOVE_DUPLICATES _allowed_modules) | |
| # PUBLIC_HEADER_DIR uses the unfolded name so sub-libraries | |
| # (e.g. lldbHostMacOSXObjCXX) don't redundantly scan their parent | |
| # module's headers — those are scanned by the parent's own check. | |
| string(REGEX REPLACE "^lldb" "" _own_dir "${name}") | |
| lldb_check_header_layering(${name} | |
| SOURCES ${PARAM_UNPARSED_ARGUMENTS} | |
| PUBLIC_HEADER_DIR "${LLDB_INCLUDE_DIR}/lldb/${_own_dir}" | |
| OWN_MODULE ${_own_module} | |
| ALLOWED_MODULES ${_allowed_modules}) | |
| endif() | |
| if(PARAM_NO_PLUGIN_DEPENDENCIES) | |
| foreach(link_lib ${PARAM_LINK_LIBS}) | |
| if (link_lib MATCHES "^lldbPlugin") | |
| message(FATAL_ERROR | |
| "Library ${name} cannot depend on a plugin (Found ${link_lib} in " | |
| "LINK_LIBS)") | |
| endif() | |
| endforeach() | |
| endif() | |
| if(PARAM_PLUGIN) | |
| set_property(GLOBAL APPEND PROPERTY LLDB_PLUGINS ${name}) | |
| endif() | |
| if (PARAM_MODULE) | |
| set(libkind MODULE) | |
| elseif (PARAM_SHARED) | |
| set(libkind SHARED) | |
| elseif (PARAM_OBJECT) | |
| # Pass STATIC alongside OBJECT so that under BUILD_SHARED_LIBS=ON the | |
| # secondary library variant llvm_add_library produces is a STATIC archive | |
| # rather than a SHARED library. OBJECT consumers in LLDB carry no LINK_LIBS | |
| # of their own (consumers add them), so a SHARED variant would fail to link. | |
| set(libkind "OBJECT;STATIC") | |
| else () | |
| # PARAM_STATIC or library type unspecified. BUILD_SHARED_LIBS | |
| # does not control the kind of libraries created for LLDB, | |
| # only whether or not they link to shared/static LLVM/Clang | |
| # libraries. | |
| set(libkind STATIC) | |
| endif() | |
| if(LLDB_NO_INSTALL_DEFAULT_RPATH) | |
| set(pass_NO_INSTALL_RPATH NO_INSTALL_RPATH) | |
| endif() | |
| llvm_add_library(${name} ${libkind} | |
| ${PARAM_UNPARSED_ARGUMENTS} | |
| LINK_LIBS ${PARAM_LINK_LIBS} | |
| ${pass_NO_INSTALL_RPATH} | |
| ) | |
| # Mark whether this library transitively pulls in liblldb. | |
| _lldb_propagate_links_liblldb(${name} "${PARAM_LINK_LIBS}") | |
| if(CLANG_LINK_CLANG_DYLIB) | |
| target_link_libraries(${name} PRIVATE clang-cpp) | |
| else() | |
| target_link_libraries(${name} PRIVATE ${PARAM_CLANG_LIBS}) | |
| endif() | |
| # A target cannot be changed to a FRAMEWORK after calling install() because | |
| # this may result in the wrong install DESTINATION. The FRAMEWORK property | |
| # must be set earlier. | |
| if(PARAM_FRAMEWORK) | |
| set_target_properties(${name} PROPERTIES FRAMEWORK ON) | |
| endif() | |
| if(PARAM_SHARED OR | |
| (LLDB_BUILD_STATIC_LIBLLDB AND libkind STREQUAL "STATIC")) | |
| set(install_dest lib${LLVM_LIBDIR_SUFFIX}) | |
| if(PARAM_INSTALL_PREFIX) | |
| set(install_dest ${PARAM_INSTALL_PREFIX}) | |
| endif() | |
| # RUNTIME is relevant for DLL platforms, FRAMEWORK for macOS | |
| install(TARGETS ${name} COMPONENT ${name} | |
| RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" | |
| LIBRARY DESTINATION ${install_dest} | |
| ARCHIVE DESTINATION ${install_dest} | |
| FRAMEWORK DESTINATION ${install_dest}) | |
| if (NOT CMAKE_CONFIGURATION_TYPES) | |
| add_llvm_install_targets(install-${name} | |
| DEPENDS ${name} | |
| COMPONENT ${name}) | |
| endif() | |
| endif() | |
| # Hack: only some LLDB libraries depend on the clang autogenerated headers, | |
| # but it is simple enough to make all of LLDB depend on some of those | |
| # headers without negatively impacting much of anything. | |
| if(NOT LLDB_BUILT_STANDALONE) | |
| add_dependencies(${name} clang-tablegen-targets) | |
| endif() | |
| if(PARAM_PLUGIN) | |
| get_property(parent_dir DIRECTORY PROPERTY PARENT_DIRECTORY) | |
| if(EXISTS ${parent_dir}) | |
| get_filename_component(category ${parent_dir} NAME) | |
| set_target_properties(${name} PROPERTIES FOLDER "LLDB/Plugins/${category}") | |
| endif() | |
| else() | |
| set_target_properties(${name} PROPERTIES FOLDER "LLDB/Libraries") | |
| endif() | |
| # When liblldb re-exports private symbols (due to LLDB_EXPORT_ALL_SYMBOLS | |
| # and/or LLDB_ENABLE_DYNAMIC_SCRIPTINTERPRETERS) those symbols must keep | |
| # default visibility in the contributing libraries, even if a global | |
| # `CMAKE_CXX_VISIBILITY_PRESET=hidden` is present. A linker version script | |
| # cannot re-export a symbol that was hidden at compile time. | |
| if (LLDB_EXPORT_ALL_SYMBOLS OR LLDB_ENABLE_DYNAMIC_SCRIPTINTERPRETERS) | |
| set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET default) | |
| endif() | |
| endfunction(add_lldb_library) | |
| function(add_lldb_executable name) | |
| cmake_parse_arguments(ARG | |
| "GENERATE_INSTALL" | |
| "INSTALL_PREFIX" | |
| "LINK_LIBS;CLANG_LIBS;LINK_COMPONENTS;BUILD_RPATH;INSTALL_RPATH" | |
| ${ARGN} | |
| ) | |
| if(LLDB_NO_INSTALL_DEFAULT_RPATH) | |
| set(pass_NO_INSTALL_RPATH NO_INSTALL_RPATH) | |
| endif() | |
| list(APPEND LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS}) | |
| add_llvm_executable(${name} | |
| ${pass_NO_INSTALL_RPATH} | |
| ${ARG_UNPARSED_ARGUMENTS} | |
| ) | |
| target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS}) | |
| if(WIN32) | |
| list(FIND ARG_LINK_LIBS liblldb LIBLLDB_INDEX) | |
| if(NOT LIBLLDB_INDEX EQUAL -1) | |
| if (MSVC) | |
| target_link_options(${name} PRIVATE | |
| "LINKER:/DELAYLOAD:$<TARGET_FILE_NAME:liblldb>") | |
| target_link_libraries(${name} PRIVATE delayimp) | |
| elseif (MINGW AND LINKER_IS_LLD) | |
| # LLD can delay load just by passing a --delayload flag, as long as the import | |
| # library is a short type import library (which LLD and MS link.exe produce). | |
| # With ld.bfd, with long import libraries (as produced by GNU binutils), one | |
| # has to generate a separate delayload import library with dlltool. | |
| target_link_options(${name} PRIVATE "-Wl,--delayload=$<TARGET_FILE_NAME:liblldb>") | |
| elseif (DEFINED LLDB_PYTHON_DLL_RELATIVE_PATH) | |
| # If liblldb can't be delayloaded, then LLDB_PYTHON_DLL_RELATIVE_PATH will not | |
| # have any effect. | |
| message(WARNING "liblldb is not delay loaded, LLDB_PYTHON_DLL_RELATIVE_PATH has no effect") | |
| endif() | |
| endif() | |
| endif() | |
| if(CLANG_LINK_CLANG_DYLIB) | |
| target_link_libraries(${name} PRIVATE clang-cpp) | |
| else() | |
| target_link_libraries(${name} PRIVATE ${ARG_CLANG_LIBS}) | |
| endif() | |
| if (ARG_BUILD_RPATH) | |
| set_target_properties(${name} PROPERTIES BUILD_RPATH "${ARG_BUILD_RPATH}") | |
| endif() | |
| if (ARG_INSTALL_RPATH) | |
| set_target_properties(${name} PROPERTIES | |
| BUILD_WITH_INSTALL_RPATH OFF | |
| INSTALL_RPATH "${ARG_INSTALL_RPATH}") | |
| endif() | |
| if(ARG_GENERATE_INSTALL) | |
| set(install_dest bin) | |
| if(ARG_INSTALL_PREFIX) | |
| set(install_dest ${ARG_INSTALL_PREFIX}) | |
| endif() | |
| install(TARGETS ${name} COMPONENT ${name} | |
| RUNTIME DESTINATION ${install_dest} | |
| LIBRARY DESTINATION ${install_dest} | |
| BUNDLE DESTINATION ${install_dest} | |
| FRAMEWORK DESTINATION ${install_dest}) | |
| if (NOT CMAKE_CONFIGURATION_TYPES) | |
| add_llvm_install_targets(install-${name} | |
| DEPENDS ${name} | |
| COMPONENT ${name}) | |
| # An installed tool that links liblldb won't run without liblldb | |
| # installed alongside it. Record it on a global list so other | |
| # runtime components (e.g. the Python/Lua script packages) can | |
| # attach themselves to the same install targets. | |
| _lldb_links_liblldb_check(_links_liblldb "${ARG_LINK_LIBS}") | |
| if(_links_liblldb) | |
| set_property(GLOBAL APPEND PROPERTY LLDB_TOOLS_LINKING_LIBLLDB ${name}) | |
| if(TARGET install-liblldb) | |
| add_dependencies(install-${name} install-liblldb) | |
| if(TARGET install-${name}-stripped AND TARGET install-liblldb-stripped) | |
| add_dependencies(install-${name}-stripped install-liblldb-stripped) | |
| endif() | |
| endif() | |
| endif() | |
| endif() | |
| if(APPLE AND ARG_INSTALL_PREFIX) | |
| lldb_add_post_install_steps_darwin(${name} ${ARG_INSTALL_PREFIX}) | |
| endif() | |
| endif() | |
| endfunction() | |
| macro(add_lldb_tool_subdirectory name) | |
| add_llvm_subdirectory(LLDB TOOL ${name}) | |
| endmacro() | |
| function(add_lldb_tool name) | |
| cmake_parse_arguments(ARG "ADD_TO_FRAMEWORK" "" "" ${ARGN}) | |
| if(LLDB_BUILD_FRAMEWORK AND ARG_ADD_TO_FRAMEWORK) | |
| set(subdir LLDB.framework/Versions/${LLDB_FRAMEWORK_VERSION}/Resources) | |
| add_lldb_executable(${name} | |
| GENERATE_INSTALL | |
| INSTALL_PREFIX ${LLDB_FRAMEWORK_INSTALL_DIR}/${subdir} | |
| ${ARG_UNPARSED_ARGUMENTS} | |
| ) | |
| lldb_add_to_buildtree_lldb_framework(${name} ${subdir}) | |
| return() | |
| endif() | |
| add_lldb_executable(${name} GENERATE_INSTALL ${ARG_UNPARSED_ARGUMENTS}) | |
| set_target_properties(${name} PROPERTIES XCODE_GENERATE_SCHEME ON) | |
| endfunction() | |
| # liblldb statically absorbs lldbHost, lldbUtility, and every plugin. A tool | |
| # that links the shared liblldb while also linking those archives statically | |
| # carries a second copy of their object code. On ELF, if the tool re-exports | |
| # the archive symbols through its own .dynsym, the dynamic linker can bind the | |
| # shared liblldb's internal references to the tool's copy instead of its own, | |
| # breaking shared state such as the HostInfo singletons. --exclude-libs,ALL | |
| # keeps the archive symbols out of the tool's .dynsym. Only ELF is affected: | |
| # Mach-O uses two-level namespaces and PE/COFF does not export symbols by | |
| # default. | |
| function(lldb_prevent_liblldb_symbol_interposition name) | |
| if(UNIX AND NOT APPLE) | |
| target_link_options(${name} PRIVATE "LINKER:--exclude-libs,ALL") | |
| endif() | |
| endfunction() | |
| # The test suite relies on finding LLDB.framework binary resources in the | |
| # build-tree. Remove them before installing to avoid collisions with their | |
| # own install targets. | |
| function(lldb_add_to_buildtree_lldb_framework name subdir) | |
| # The rpaths needed to find the LLVM dylib in the buildtree differ from installation rpaths. | |
| if (LLVM_LINK_LLVM_DYLIB) | |
| set_target_properties(${name} PROPERTIES | |
| BUILD_WITH_INSTALL_RPATH OFF | |
| ) | |
| endif() | |
| # Destination for the copy in the build-tree. While the framework target may | |
| # not exist yet, it will exist when the generator expression gets expanded. | |
| set(copy_dest "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/${subdir}/$<TARGET_FILE_NAME:${name}>") | |
| # Copy into the given subdirectory for testing. | |
| add_custom_command(TARGET ${name} POST_BUILD | |
| COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${name}> ${copy_dest} | |
| COMMENT "Copy ${name} to ${copy_dest}" | |
| ) | |
| # Create a custom target to remove the copy again from LLDB.framework in the | |
| # build tree. | |
| add_custom_target(${name}-cleanup | |
| COMMAND ${CMAKE_COMMAND} -E remove ${copy_dest} | |
| COMMENT "Removing ${name} from LLDB.framework") | |
| add_dependencies(lldb-framework-cleanup | |
| ${name}-cleanup) | |
| endfunction() | |
| # PluginManager discovers dynamic script interpreter plugins at runtime by | |
| # scanning the directory that holds liblldb, so a plugin is loaded only when it | |
| # sits beside it. A framework build moves liblldb into the bundle, so the plugin | |
| # must move with it and carry an rpath that reaches liblldb from its new | |
| # location. | |
| function(lldb_add_scriptinterpreter_plugin_to_buildtree_framework name) | |
| if(NOT LLDB_BUILD_FRAMEWORK) | |
| return() | |
| endif() | |
| # The rpaths needed to find the LLVM dylib in the buildtree differ from installation rpaths. | |
| if (LLVM_LINK_LLVM_DYLIB) | |
| set_target_properties(${name} PROPERTIES | |
| BUILD_WITH_INSTALL_RPATH OFF | |
| ) | |
| endif() | |
| # Copy under the unversioned name: PluginManager derives a plugin's | |
| # initializer symbol from it. A versioned copy would load but never | |
| # initialize. | |
| set(plugin_in_framework | |
| "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/Versions/${LLDB_FRAMEWORK_VERSION}/$<TARGET_LINKER_FILE_NAME:${name}>") | |
| add_custom_command(TARGET ${name} POST_BUILD VERBATIM | |
| COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${name}>" "${plugin_in_framework}" | |
| COMMENT "Copy ${name} into LLDB.framework") | |
| add_custom_target(${name}-framework-cleanup | |
| COMMAND ${CMAKE_COMMAND} -E remove "${plugin_in_framework}" | |
| COMMENT "Removing ${name} from LLDB.framework") | |
| add_dependencies(lldb-framework-cleanup ${name}-framework-cleanup) | |
| endfunction() | |
| function(lldb_add_scriptinterpreter_dynamic_library name) | |
| if (LLDB_BUILD_FRAMEWORK) | |
| set(framework_install_prefix "${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Versions/${LLDB_FRAMEWORK_VERSION}/") | |
| set(framework_arg INSTALL_PREFIX "${framework_install_prefix}") | |
| endif() | |
| # ScriptInterpreter shared libraries are loaded at runtime by PluginManager. | |
| # Private lldb symbols are resolved via liblldb's re-exports, so we | |
| # explicitly cannot link against any lldb_private libraries. | |
| # FIXME: Add a mechanism to enforce this. We already have | |
| # `ALLOWED_INTERNAL_DEPENDENCIES`, but it is not fine-grained enough to | |
| # distinguish between link dependencies and header dependencies. | |
| add_lldb_library(${name} SHARED | |
| ${framework_arg} | |
| ${ARGN} | |
| ) | |
| if (LLDB_BUILD_FRAMEWORK) | |
| lldb_add_post_install_steps_darwin(${name} ${framework_install_prefix}) | |
| endif() | |
| if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") | |
| lldb_record_dynamic_script_interpreter_exports(${name}) | |
| endif() | |
| set_property(TARGET ${name} APPEND PROPERTY | |
| INSTALL_RPATH "@loader_path/../../..") | |
| lldb_add_scriptinterpreter_plugin_to_buildtree_framework(${name}) | |
| endfunction(lldb_add_scriptinterpreter_dynamic_library) | |
| # Add extra install steps for dSYM creation and stripping for the given target. | |
| function(lldb_add_post_install_steps_darwin name install_prefix) | |
| if(NOT APPLE) | |
| message(WARNING "Darwin-specific functionality; not currently available on non-Apple platforms.") | |
| return() | |
| endif() | |
| get_target_property(output_name ${name} OUTPUT_NAME) | |
| if(NOT output_name) | |
| set(output_name ${name}) | |
| endif() | |
| get_target_property(is_framework ${name} FRAMEWORK) | |
| if(is_framework) | |
| get_target_property(buildtree_dir ${name} LIBRARY_OUTPUT_DIRECTORY) | |
| if(buildtree_dir) | |
| set(bundle_subdir ${output_name}.framework/Versions/${LLDB_FRAMEWORK_VERSION}/) | |
| else() | |
| message(SEND_ERROR "Framework target ${name} missing property for output directory. Cannot generate post-install steps.") | |
| return() | |
| endif() | |
| else() | |
| get_target_property(target_type ${name} TYPE) | |
| if(target_type STREQUAL "EXECUTABLE") | |
| set(buildtree_dir ${LLVM_RUNTIME_OUTPUT_INTDIR}) | |
| else() | |
| # Only ever install shared libraries. | |
| set(output_name "lib${output_name}.dylib") | |
| set(buildtree_dir ${LLVM_LIBRARY_OUTPUT_INTDIR}) | |
| endif() | |
| endif() | |
| # Generate dSYM | |
| if(NOT LLDB_SKIP_DSYM) | |
| set(dsym_name ${output_name}.dSYM) | |
| if(is_framework) | |
| set(dsym_name ${output_name}.framework.dSYM) | |
| endif() | |
| if(LLDB_DEBUGINFO_INSTALL_PREFIX) | |
| # This makes the path absolute, so we must respect DESTDIR. | |
| set(dsym_name "\$ENV\{DESTDIR\}${LLDB_DEBUGINFO_INSTALL_PREFIX}/${dsym_name}") | |
| endif() | |
| set(buildtree_name ${buildtree_dir}/${bundle_subdir}${output_name}) | |
| install(CODE "message(STATUS \"Externalize debuginfo: ${dsym_name}\")" COMPONENT ${name}) | |
| install(CODE "execute_process(COMMAND xcrun dsymutil -o=${dsym_name} ${buildtree_name})" | |
| COMPONENT ${name}) | |
| endif() | |
| if(NOT LLDB_SKIP_STRIP) | |
| # Strip distribution binary with -ST (removing debug symbol table entries and | |
| # Swift symbols). Avoid CMAKE_INSTALL_DO_STRIP and llvm_externalize_debuginfo() | |
| # as they can't be configured sufficiently. | |
| set(installtree_name "\$ENV\{DESTDIR\}${install_prefix}/${bundle_subdir}${output_name}") | |
| install(CODE "message(STATUS \"Stripping: ${installtree_name}\")" COMPONENT ${name}) | |
| install(CODE "execute_process(COMMAND xcrun strip -ST ${installtree_name})" | |
| COMPONENT ${name}) | |
| endif() | |
| endfunction() | |
| # CMake's set_target_properties() doesn't allow to pass lists for RPATH | |
| # properties directly (error: "called with incorrect number of arguments"). | |
| # Instead of defining two list variables each time, use this helper function. | |
| function(lldb_setup_rpaths name) | |
| cmake_parse_arguments(LIST "" "" "BUILD_RPATH;INSTALL_RPATH" ${ARGN}) | |
| set_target_properties(${name} PROPERTIES | |
| BUILD_WITH_INSTALL_RPATH OFF | |
| BUILD_RPATH "${LIST_BUILD_RPATH}" | |
| INSTALL_RPATH "${LIST_INSTALL_RPATH}" | |
| ) | |
| endfunction() | |
| function(lldb_find_system_debugserver path) | |
| execute_process(COMMAND xcode-select -p | |
| RESULT_VARIABLE exit_code | |
| OUTPUT_VARIABLE xcode_dev_dir | |
| ERROR_VARIABLE error_msg | |
| OUTPUT_STRIP_TRAILING_WHITESPACE) | |
| if(exit_code) | |
| message(WARNING "`xcode-select -p` failed:\n${error_msg}") | |
| else() | |
| set(subpath "LLDB.framework/Resources/debugserver") | |
| set(path_shared "${xcode_dev_dir}/../SharedFrameworks/${subpath}") | |
| set(path_private "${xcode_dev_dir}/Library/PrivateFrameworks/${subpath}") | |
| if(EXISTS ${path_shared}) | |
| set(${path} ${path_shared} PARENT_SCOPE) | |
| elseif(EXISTS ${path_private}) | |
| set(${path} ${path_private} PARENT_SCOPE) | |
| else() | |
| message(WARNING "System debugserver requested, but not found. " | |
| "Candidates don't exist: ${path_shared}\n${path_private}") | |
| endif() | |
| endif() | |
| endfunction() | |
| function(lldb_find_python_module module) | |
| set(MODULE_FOUND PY_${module}_FOUND) | |
| if (${MODULE_FOUND}) | |
| return() | |
| endif() | |
| execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import ${module}" | |
| RESULT_VARIABLE status | |
| ERROR_QUIET) | |
| if (status) | |
| set(${MODULE_FOUND} OFF PARENT_SCOPE) | |
| message(STATUS "Could NOT find Python module '${module}'") | |
| else() | |
| set(${MODULE_FOUND} ON PARENT_SCOPE) | |
| message(STATUS "Found Python module '${module}'") | |
| endif() | |
| endfunction() | |
| # Removes all module flags from the current CMAKE_CXX_FLAGS. Used for | |
| # the Objective-C++ code in lldb which we don't want to build with modules. | |
| # Reasons for this are that modules with Objective-C++ would require that | |
| # all LLVM/Clang modules are Objective-C++ compatible (which they are likely | |
| # not) and we would have rebuild a second set of modules just for the few | |
| # Objective-C++ files in lldb (which slows down the build process). | |
| macro(remove_module_flags) | |
| string(REGEX REPLACE "-fmodules-cache-path=[^ ]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") | |
| string(REGEX REPLACE "-fmodules-local-submodule-visibility" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") | |
| string(REGEX REPLACE "-fmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") | |
| string(REGEX REPLACE "-gmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") | |
| string(REGEX REPLACE "-fcxx-modules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") | |
| endmacro() |