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