xref: /llvm-project/lldb/cmake/modules/AddLLDB.cmake (revision a982cabea3cfbf456a01ed85499fa7dfc7ec18c7)
1include(GNUInstallDirs)
2
3function(lldb_tablegen)
4  # Syntax:
5  # lldb_tablegen output-file [tablegen-arg ...] SOURCE source-file
6  # [[TARGET cmake-target-name] [DEPENDS extra-dependency ...]]
7  #
8  # Generates a custom command for invoking tblgen as
9  #
10  # tblgen source-file -o=output-file tablegen-arg ...
11  #
12  # and, if cmake-target-name is provided, creates a custom target for
13  # executing the custom command depending on output-file. It is
14  # possible to list more files to depend after DEPENDS.
15
16  cmake_parse_arguments(LTG "" "SOURCE;TARGET" "" ${ARGN})
17
18  if(NOT LTG_SOURCE)
19    message(FATAL_ERROR "SOURCE source-file required by lldb_tablegen")
20  endif()
21
22  set(LLVM_TARGET_DEFINITIONS ${LTG_SOURCE})
23
24  if (LLVM_USE_SANITIZER MATCHES ".*Address.*")
25    list(APPEND LTG_UNPARSED_ARGUMENTS -DLLDB_SANITIZED)
26  endif()
27
28  tablegen(LLDB ${LTG_UNPARSED_ARGUMENTS})
29
30  if(LTG_TARGET)
31    add_public_tablegen_target(${LTG_TARGET})
32    set_property(GLOBAL APPEND PROPERTY LLDB_TABLEGEN_TARGETS ${LTG_TARGET})
33  endif()
34endfunction(lldb_tablegen)
35
36function(add_lldb_library name)
37  include_directories(BEFORE
38    ${CMAKE_CURRENT_BINARY_DIR}
39)
40
41  # only supported parameters to this macro are the optional
42  # MODULE;SHARED;STATIC library type and source files
43  cmake_parse_arguments(PARAM
44    "MODULE;SHARED;STATIC;OBJECT;PLUGIN;FRAMEWORK;NO_INTERNAL_DEPENDENCIES;NO_PLUGIN_DEPENDENCIES"
45    "INSTALL_PREFIX;ENTITLEMENTS"
46    "EXTRA_CXXFLAGS;DEPENDS;LINK_LIBS;LINK_COMPONENTS;CLANG_LIBS"
47    ${ARGN})
48  llvm_process_sources(srcs ${PARAM_UNPARSED_ARGUMENTS})
49  list(APPEND LLVM_LINK_COMPONENTS ${PARAM_LINK_COMPONENTS})
50
51  if(PARAM_NO_INTERNAL_DEPENDENCIES)
52    foreach(link_lib ${PARAM_LINK_LIBS})
53      if (link_lib MATCHES "^lldb")
54        message(FATAL_ERROR
55          "Library ${name} cannot depend on any other lldb libs "
56          "(Found ${link_lib} in LINK_LIBS)")
57      endif()
58    endforeach()
59  endif()
60
61  if(PARAM_NO_PLUGIN_DEPENDENCIES)
62    foreach(link_lib ${PARAM_LINK_LIBS})
63      if (link_lib MATCHES "^lldbPlugin")
64        message(FATAL_ERROR
65          "Library ${name} cannot depend on a plugin (Found ${link_lib} in "
66          "LINK_LIBS)")
67      endif()
68    endforeach()
69  endif()
70
71  if(PARAM_PLUGIN)
72    set_property(GLOBAL APPEND PROPERTY LLDB_PLUGINS ${name})
73  endif()
74
75  if (MSVC_IDE OR XCODE)
76    string(REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR})
77    list(GET split_path -1 dir)
78    file(GLOB_RECURSE headers
79      ../../include/lldb${dir}/*.h)
80    set(srcs ${srcs} ${headers})
81  endif()
82  if (PARAM_MODULE)
83    set(libkind MODULE)
84  elseif (PARAM_SHARED)
85    set(libkind SHARED)
86  elseif (PARAM_OBJECT)
87    set(libkind OBJECT)
88  else ()
89    # PARAM_STATIC or library type unspecified. BUILD_SHARED_LIBS
90    # does not control the kind of libraries created for LLDB,
91    # only whether or not they link to shared/static LLVM/Clang
92    # libraries.
93    set(libkind STATIC)
94  endif()
95
96  #PIC not needed on Win
97  # FIXME: Setting CMAKE_CXX_FLAGS here is a no-op, use target_compile_options
98  # or omit this logic instead.
99  if (NOT WIN32)
100    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
101  endif()
102
103  if (PARAM_OBJECT)
104    add_library(${name} ${libkind} ${srcs})
105  else()
106    if(PARAM_ENTITLEMENTS)
107      set(pass_ENTITLEMENTS ENTITLEMENTS ${PARAM_ENTITLEMENTS})
108    endif()
109
110    if(LLDB_NO_INSTALL_DEFAULT_RPATH)
111      set(pass_NO_INSTALL_RPATH NO_INSTALL_RPATH)
112    endif()
113
114    llvm_add_library(${name} ${libkind} ${srcs}
115      LINK_LIBS ${PARAM_LINK_LIBS}
116      DEPENDS ${PARAM_DEPENDS}
117      ${pass_ENTITLEMENTS}
118      ${pass_NO_INSTALL_RPATH}
119    )
120
121    if(CLANG_LINK_CLANG_DYLIB)
122      target_link_libraries(${name} PRIVATE clang-cpp)
123    else()
124      target_link_libraries(${name} PRIVATE ${PARAM_CLANG_LIBS})
125    endif()
126  endif()
127
128  # A target cannot be changed to a FRAMEWORK after calling install() because
129  # this may result in the wrong install DESTINATION. The FRAMEWORK property
130  # must be set earlier.
131  if(PARAM_FRAMEWORK)
132    set_target_properties(${name} PROPERTIES FRAMEWORK ON)
133  endif()
134
135  if(PARAM_SHARED)
136    set(install_dest lib${LLVM_LIBDIR_SUFFIX})
137    if(PARAM_INSTALL_PREFIX)
138      set(install_dest ${PARAM_INSTALL_PREFIX})
139    endif()
140    # RUNTIME is relevant for DLL platforms, FRAMEWORK for macOS
141    install(TARGETS ${name} COMPONENT ${name}
142      RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
143      LIBRARY DESTINATION ${install_dest}
144      ARCHIVE DESTINATION ${install_dest}
145      FRAMEWORK DESTINATION ${install_dest})
146    if (NOT CMAKE_CONFIGURATION_TYPES)
147      add_llvm_install_targets(install-${name}
148                              DEPENDS ${name}
149                              COMPONENT ${name})
150    endif()
151  endif()
152
153  # Hack: only some LLDB libraries depend on the clang autogenerated headers,
154  # but it is simple enough to make all of LLDB depend on some of those
155  # headers without negatively impacting much of anything.
156  if(NOT LLDB_BUILT_STANDALONE)
157    add_dependencies(${name} clang-tablegen-targets)
158  endif()
159
160  # Add in any extra C++ compilation flags for this library.
161  target_compile_options(${name} PRIVATE ${PARAM_EXTRA_CXXFLAGS})
162
163  if(PARAM_PLUGIN)
164    get_property(parent_dir DIRECTORY PROPERTY PARENT_DIRECTORY)
165    if(EXISTS ${parent_dir})
166      get_filename_component(category ${parent_dir} NAME)
167      set_target_properties(${name} PROPERTIES FOLDER "LLDB/Plugins/${category}")
168    endif()
169  else()
170    set_target_properties(${name} PROPERTIES FOLDER "LLDB/Libraries")
171  endif()
172
173  # If we want to export all lldb symbols (i.e LLDB_EXPORT_ALL_SYMBOLS=ON), we
174  # need to use default visibility for all LLDB libraries even if a global
175  # `CMAKE_CXX_VISIBILITY_PRESET=hidden`is present.
176  if (LLDB_EXPORT_ALL_SYMBOLS)
177    set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET default)
178  endif()
179endfunction(add_lldb_library)
180
181function(add_lldb_executable name)
182  cmake_parse_arguments(ARG
183    "GENERATE_INSTALL"
184    "INSTALL_PREFIX;ENTITLEMENTS"
185    "LINK_LIBS;CLANG_LIBS;LINK_COMPONENTS;BUILD_RPATH;INSTALL_RPATH"
186    ${ARGN}
187    )
188
189  if(ARG_ENTITLEMENTS)
190    set(pass_ENTITLEMENTS ENTITLEMENTS ${ARG_ENTITLEMENTS})
191  endif()
192
193  if(LLDB_NO_INSTALL_DEFAULT_RPATH)
194    set(pass_NO_INSTALL_RPATH NO_INSTALL_RPATH)
195  endif()
196
197  list(APPEND LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS})
198  add_llvm_executable(${name}
199    ${pass_ENTITLEMENTS}
200    ${pass_NO_INSTALL_RPATH}
201    ${ARG_UNPARSED_ARGUMENTS}
202  )
203
204  target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
205  if(CLANG_LINK_CLANG_DYLIB)
206    target_link_libraries(${name} PRIVATE clang-cpp)
207  else()
208    target_link_libraries(${name} PRIVATE ${ARG_CLANG_LIBS})
209  endif()
210
211  if (ARG_BUILD_RPATH)
212    set_target_properties(${name} PROPERTIES BUILD_RPATH "${ARG_BUILD_RPATH}")
213  endif()
214
215  if (ARG_INSTALL_RPATH)
216    set_target_properties(${name} PROPERTIES
217      BUILD_WITH_INSTALL_RPATH OFF
218      INSTALL_RPATH "${ARG_INSTALL_RPATH}")
219  endif()
220
221  if(ARG_GENERATE_INSTALL)
222    set(install_dest bin)
223    if(ARG_INSTALL_PREFIX)
224      set(install_dest ${ARG_INSTALL_PREFIX})
225    endif()
226    install(TARGETS ${name} COMPONENT ${name}
227            RUNTIME DESTINATION ${install_dest}
228            LIBRARY DESTINATION ${install_dest}
229            BUNDLE DESTINATION ${install_dest}
230            FRAMEWORK DESTINATION ${install_dest})
231    if (NOT CMAKE_CONFIGURATION_TYPES)
232      add_llvm_install_targets(install-${name}
233                               DEPENDS ${name}
234                               COMPONENT ${name})
235    endif()
236    if(APPLE AND ARG_INSTALL_PREFIX)
237      lldb_add_post_install_steps_darwin(${name} ${ARG_INSTALL_PREFIX})
238    endif()
239  endif()
240endfunction()
241
242
243macro(add_lldb_tool_subdirectory name)
244  add_llvm_subdirectory(LLDB TOOL ${name})
245endmacro()
246
247function(add_lldb_tool name)
248  cmake_parse_arguments(ARG "ADD_TO_FRAMEWORK" "" "" ${ARGN})
249  if(LLDB_BUILD_FRAMEWORK AND ARG_ADD_TO_FRAMEWORK)
250    set(subdir LLDB.framework/Versions/${LLDB_FRAMEWORK_VERSION}/Resources)
251    add_lldb_executable(${name}
252      GENERATE_INSTALL
253      INSTALL_PREFIX ${LLDB_FRAMEWORK_INSTALL_DIR}/${subdir}
254      ${ARG_UNPARSED_ARGUMENTS}
255    )
256    lldb_add_to_buildtree_lldb_framework(${name} ${subdir})
257    return()
258  endif()
259
260  add_lldb_executable(${name} GENERATE_INSTALL ${ARG_UNPARSED_ARGUMENTS})
261  set_target_properties(${name} PROPERTIES XCODE_GENERATE_SCHEME ON)
262endfunction()
263
264# The test suite relies on finding LLDB.framework binary resources in the
265# build-tree. Remove them before installing to avoid collisions with their
266# own install targets.
267function(lldb_add_to_buildtree_lldb_framework name subdir)
268  # Destination for the copy in the build-tree. While the framework target may
269  # not exist yet, it will exist when the generator expression gets expanded.
270  set(copy_dest "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/${subdir}/$<TARGET_FILE_NAME:${name}>")
271
272  # Copy into the given subdirectory for testing.
273  add_custom_command(TARGET ${name} POST_BUILD
274    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${name}> ${copy_dest}
275    COMMENT "Copy ${name} to ${copy_dest}"
276  )
277
278  # Create a custom target to remove the copy again from LLDB.framework in the
279  # build tree.
280  add_custom_target(${name}-cleanup
281    COMMAND ${CMAKE_COMMAND} -E remove ${copy_dest}
282    COMMENT "Removing ${name} from LLDB.framework")
283  add_dependencies(lldb-framework-cleanup
284    ${name}-cleanup)
285endfunction()
286
287# Add extra install steps for dSYM creation and stripping for the given target.
288function(lldb_add_post_install_steps_darwin name install_prefix)
289  if(NOT APPLE)
290    message(WARNING "Darwin-specific functionality; not currently available on non-Apple platforms.")
291    return()
292  endif()
293
294  get_target_property(output_name ${name} OUTPUT_NAME)
295  if(NOT output_name)
296    set(output_name ${name})
297  endif()
298
299  get_target_property(is_framework ${name} FRAMEWORK)
300  if(is_framework)
301    get_target_property(buildtree_dir ${name} LIBRARY_OUTPUT_DIRECTORY)
302    if(buildtree_dir)
303      set(bundle_subdir ${output_name}.framework/Versions/${LLDB_FRAMEWORK_VERSION}/)
304    else()
305      message(SEND_ERROR "Framework target ${name} missing property for output directory. Cannot generate post-install steps.")
306      return()
307    endif()
308  else()
309    get_target_property(target_type ${name} TYPE)
310    if(target_type STREQUAL "EXECUTABLE")
311      set(buildtree_dir ${LLVM_RUNTIME_OUTPUT_INTDIR})
312    else()
313      # Only ever install shared libraries.
314      set(output_name "lib${output_name}.dylib")
315      set(buildtree_dir ${LLVM_LIBRARY_OUTPUT_INTDIR})
316    endif()
317  endif()
318
319  # Generate dSYM
320  if(NOT LLDB_SKIP_DSYM)
321    set(dsym_name ${output_name}.dSYM)
322    if(is_framework)
323      set(dsym_name ${output_name}.framework.dSYM)
324    endif()
325    if(LLDB_DEBUGINFO_INSTALL_PREFIX)
326      # This makes the path absolute, so we must respect DESTDIR.
327      set(dsym_name "\$ENV\{DESTDIR\}${LLDB_DEBUGINFO_INSTALL_PREFIX}/${dsym_name}")
328    endif()
329
330    set(buildtree_name ${buildtree_dir}/${bundle_subdir}${output_name})
331    install(CODE "message(STATUS \"Externalize debuginfo: ${dsym_name}\")" COMPONENT ${name})
332    install(CODE "execute_process(COMMAND xcrun dsymutil -o=${dsym_name} ${buildtree_name})"
333            COMPONENT ${name})
334  endif()
335
336  if(NOT LLDB_SKIP_STRIP)
337    # Strip distribution binary with -ST (removing debug symbol table entries and
338    # Swift symbols). Avoid CMAKE_INSTALL_DO_STRIP and llvm_externalize_debuginfo()
339    # as they can't be configured sufficiently.
340    set(installtree_name "\$ENV\{DESTDIR\}${install_prefix}/${bundle_subdir}${output_name}")
341    install(CODE "message(STATUS \"Stripping: ${installtree_name}\")" COMPONENT ${name})
342    install(CODE "execute_process(COMMAND xcrun strip -ST ${installtree_name})"
343            COMPONENT ${name})
344  endif()
345endfunction()
346
347# CMake's set_target_properties() doesn't allow to pass lists for RPATH
348# properties directly (error: "called with incorrect number of arguments").
349# Instead of defining two list variables each time, use this helper function.
350function(lldb_setup_rpaths name)
351  cmake_parse_arguments(LIST "" "" "BUILD_RPATH;INSTALL_RPATH" ${ARGN})
352  set_target_properties(${name} PROPERTIES
353    BUILD_WITH_INSTALL_RPATH OFF
354    BUILD_RPATH "${LIST_BUILD_RPATH}"
355    INSTALL_RPATH "${LIST_INSTALL_RPATH}"
356  )
357endfunction()
358
359function(lldb_find_system_debugserver path)
360  execute_process(COMMAND xcode-select -p
361                  RESULT_VARIABLE exit_code
362                  OUTPUT_VARIABLE xcode_dev_dir
363                  ERROR_VARIABLE error_msg
364                  OUTPUT_STRIP_TRAILING_WHITESPACE)
365  if(exit_code)
366    message(WARNING "`xcode-select -p` failed:\n${error_msg}")
367  else()
368    set(subpath "LLDB.framework/Resources/debugserver")
369    set(path_shared "${xcode_dev_dir}/../SharedFrameworks/${subpath}")
370    set(path_private "${xcode_dev_dir}/Library/PrivateFrameworks/${subpath}")
371
372    if(EXISTS ${path_shared})
373      set(${path} ${path_shared} PARENT_SCOPE)
374    elseif(EXISTS ${path_private})
375      set(${path} ${path_private} PARENT_SCOPE)
376    else()
377      message(WARNING "System debugserver requested, but not found. "
378                      "Candidates don't exist: ${path_shared}\n${path_private}")
379    endif()
380  endif()
381endfunction()
382
383function(lldb_find_python_module module)
384  set(MODULE_FOUND PY_${module}_FOUND)
385  if (${MODULE_FOUND})
386    return()
387  endif()
388
389  execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import ${module}"
390    RESULT_VARIABLE status
391    ERROR_QUIET)
392
393  if (status)
394    set(${MODULE_FOUND} OFF PARENT_SCOPE)
395    message(STATUS "Could NOT find Python module '${module}'")
396  else()
397    set(${MODULE_FOUND} ON PARENT_SCOPE)
398    message(STATUS "Found Python module '${module}'")
399  endif()
400endfunction()
401
402# Removes all module flags from the current CMAKE_CXX_FLAGS. Used for
403# the Objective-C++ code in lldb which we don't want to build with modules.
404# Reasons for this are that modules with Objective-C++ would require that
405# all LLVM/Clang modules are Objective-C++ compatible (which they are likely
406# not) and we would have rebuild a second set of modules just for the few
407# Objective-C++ files in lldb (which slows down the build process).
408macro(remove_module_flags)
409  string(REGEX REPLACE "-fmodules-cache-path=[^ ]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
410  string(REGEX REPLACE "-fmodules-local-submodule-visibility" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
411  string(REGEX REPLACE "-fmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
412  string(REGEX REPLACE "-gmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
413  string(REGEX REPLACE "-fcxx-modules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
414endmacro()
415