diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt
index 48751ec834e0..e0af678cbfbb 100644
--- a/lldb/CMakeLists.txt
+++ b/lldb/CMakeLists.txt
@@ -138,9 +138,7 @@ if(LLDB_INCLUDE_TESTS)
   endif()
 
   if(TARGET debugserver)
-    if(NOT CMAKE_HOST_APPLE OR LLDB_CODESIGN_IDENTITY)
-      list(APPEND LLDB_TEST_DEPS debugserver)
-    endif()
+    list(APPEND LLDB_TEST_DEPS debugserver)
   endif()
 
   if(TARGET lldb-mi)
diff --git a/lldb/cmake/modules/AddLLDB.cmake b/lldb/cmake/modules/AddLLDB.cmake
index 0e26db55e970..89f59568fe71 100644
--- a/lldb/cmake/modules/AddLLDB.cmake
+++ b/lldb/cmake/modules/AddLLDB.cmake
@@ -100,13 +100,13 @@ endfunction(add_lldb_library)
 function(add_lldb_executable name)
   cmake_parse_arguments(ARG
     "INCLUDE_IN_SUITE;GENERATE_INSTALL"
-    ""
+    "ENTITLEMENTS"
     "LINK_LIBS;LINK_COMPONENTS"
     ${ARGN}
     )
 
   list(APPEND LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS})
-  add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS})
+  add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS} ENTITLEMENTS ${ARG_ENTITLEMENTS})
 
   target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
   set_target_properties(${name} PROPERTIES
diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index 98710f13b7bd..fc3913943e73 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -50,6 +50,8 @@ if (LLDB_DISABLE_CURSES)
   add_definitions( -DLLDB_DISABLE_CURSES )
 endif()
 
+option(LLDB_USE_ENTITLEMENTS "When code signing, use entitlements if available" ON)
+
 # On Windows, we can't use the normal FindPythonLibs module that comes with CMake,
 # for a number of reasons.
 # 1) Prior to MSVC 2015, it is only possible to embed Python if python itself was
diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt
index bf7b21e5d870..2efd99acc449 100644
--- a/lldb/test/CMakeLists.txt
+++ b/lldb/test/CMakeLists.txt
@@ -74,8 +74,8 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Windows" )
   endif()
 endif()
 
-if(LLDB_CODESIGN_IDENTITY)
-  list(APPEND LLDB_TEST_COMMON_ARGS --codesign-identity "${LLDB_CODESIGN_IDENTITY}")
+if(LLDB_CODESIGN_IDENTITY_USED)
+  list(APPEND LLDB_TEST_COMMON_ARGS --codesign-identity "${LLDB_CODESIGN_IDENTITY_USED}")
 endif()
 
 if(LLDB_BUILD_FRAMEWORK)
@@ -93,11 +93,11 @@ if (NOT "${LLDB_LIT_TOOLS_DIR}" STREQUAL "")
   endif()
 endif()
 
-if(CMAKE_HOST_APPLE)
+if(CMAKE_HOST_APPLE AND DEBUGSERVER_PATH)
   list(APPEND LLDB_TEST_COMMON_ARGS --server ${DEBUGSERVER_PATH})
 endif()
 
-if(SKIP_DEBUGSERVER)
+if(SKIP_TEST_DEBUGSERVER)
   list(APPEND LLDB_TEST_COMMON_ARGS --out-of-tree-debugserver)
 endif()
 
diff --git a/lldb/tools/debugserver/CMakeLists.txt b/lldb/tools/debugserver/CMakeLists.txt
index 58231582909e..53f89fd5bdad 100644
--- a/lldb/tools/debugserver/CMakeLists.txt
+++ b/lldb/tools/debugserver/CMakeLists.txt
@@ -15,6 +15,8 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
   set(LLDB_SOURCE_DIR "${CMAKE_SOURCE_DIR}/../../")
   include_directories(${LLDB_SOURCE_DIR}/include)
 
+  option(LLDB_USE_ENTITLEMENTS "When code signing, use entitlements if available" ON)
+
   # lldb-suite is a dummy target that encompasses all the necessary tools and
   # libraries for building a fully-functioning liblldb.
   add_custom_target(lldb-suite)
diff --git a/lldb/tools/debugserver/source/CMakeLists.txt b/lldb/tools/debugserver/source/CMakeLists.txt
index 16369e46e547..d82178bd39ba 100644
--- a/lldb/tools/debugserver/source/CMakeLists.txt
+++ b/lldb/tools/debugserver/source/CMakeLists.txt
@@ -94,32 +94,121 @@ set(lldbDebugserverCommonSources
 
 add_library(lldbDebugserverCommon ${lldbDebugserverCommonSources})
 
+# LLDB-specific identity, currently used for code signing debugserver.
+set(LLDB_CODESIGN_IDENTITY "" CACHE STRING
+    "Override code sign identity for debugserver and for use in tests; falls back to LLVM_CODESIGNING_IDENTITY if set or lldb_codesign otherwise (Darwin only)")
 
-set(LLDB_CODESIGN_IDENTITY "lldb_codesign"
-  CACHE STRING "Identity used for code signing. Set to empty string to skip the signing step.")
-
-if(NOT LLDB_CODESIGN_IDENTITY STREQUAL "")
-  set(DEBUGSERVER_PATH ${LLVM_RUNTIME_OUTPUT_INTDIR}/debugserver${CMAKE_EXECUTABLE_SUFFIX} CACHE PATH "Path to debugserver.")
-  set(SKIP_DEBUGSERVER OFF CACHE BOOL "Skip building the in-tree debug server")
+# Determine which identity to use and store it in the separate cache entry.
+# We will query it later for LLDB_TEST_COMMON_ARGS.
+if(LLDB_CODESIGN_IDENTITY)
+  set(LLDB_CODESIGN_IDENTITY_USED ${LLDB_CODESIGN_IDENTITY} CACHE INTERNAL "" FORCE)
+elseif(LLVM_CODESIGNING_IDENTITY)
+  set(LLDB_CODESIGN_IDENTITY_USED ${LLVM_CODESIGNING_IDENTITY} CACHE INTERNAL "" FORCE)
 else()
+  set(LLDB_CODESIGN_IDENTITY_USED lldb_codesign CACHE INTERNAL "" FORCE)
+endif()
+
+# Override locally, so the identity is used for targets created in this scope.
+set(LLVM_CODESIGNING_IDENTITY ${LLDB_CODESIGN_IDENTITY_USED})
+
+option(LLDB_NO_DEBUGSERVER "Disable the debugserver target" OFF)
+option(LLDB_USE_SYSTEM_DEBUGSERVER "Use the system's debugserver instead of building it from source (Darwin only)." OFF)
+
+# Incompatible options
+if(LLDB_NO_DEBUGSERVER AND LLDB_USE_SYSTEM_DEBUGSERVER)
+  message(FATAL_ERROR "Inconsistent options: LLDB_NO_DEBUGSERVER and LLDB_USE_SYSTEM_DEBUGSERVER")
+endif()
+
+# Try to locate the system debugserver.
+# Subsequent feasibility checks depend on it.
+if(APPLE AND CMAKE_HOST_APPLE)
   execute_process(
     COMMAND xcode-select -p
-    OUTPUT_VARIABLE XCODE_DEV_DIR)
-  string(STRIP ${XCODE_DEV_DIR} XCODE_DEV_DIR)
-  if(EXISTS "${XCODE_DEV_DIR}/../SharedFrameworks/LLDB.framework/")
-    set(DEBUGSERVER_PATH
-      "${XCODE_DEV_DIR}/../SharedFrameworks/LLDB.framework/Resources/debugserver" CACHE PATH "Path to debugserver.")
-  elseif(EXISTS "${XCODE_DEV_DIR}/Library/PrivateFrameworks/LLDB.framework/")
-    set(DEBUGSERVER_PATH
-      "${XCODE_DEV_DIR}/Library/PrivateFrameworks/LLDB.framework/Resources/debugserver" CACHE PATH "Path to debugserver.")
+    OUTPUT_VARIABLE xcode_dev_dir)
+  string(STRIP ${xcode_dev_dir} xcode_dev_dir)
+
+  set(debugserver_rel_path "LLDB.framework/Resources/debugserver")
+  set(debugserver_shared "${xcode_dev_dir}/../SharedFrameworks/${debugserver_rel_path}")
+  set(debugserver_private "${xcode_dev_dir}/Library/PrivateFrameworks/${debugserver_rel_path}")
+
+  if(EXISTS ${debugserver_shared})
+    set(system_debugserver ${debugserver_shared})
+  elseif(EXISTS ${debugserver_private})
+    set(system_debugserver ${debugserver_private})
+  endif()
+endif()
+
+# Handle unavailability
+if(LLDB_USE_SYSTEM_DEBUGSERVER)
+  if(system_debugserver)
+    set(use_system_debugserver ON)
+  elseif(APPLE AND CMAKE_HOST_APPLE)
+    # Binary not found on system. Keep cached variable, to try again on reconfigure.
+    message(SEND_ERROR
+      "LLDB_USE_SYSTEM_DEBUGSERVER option set, but no debugserver found in:\
+        ${debugserver_shared}\
+        ${debugserver_private}")
   else()
-    message(SEND_ERROR "Cannot find debugserver on system.")
+    # Non-Apple target platform or non-Darwin host. Reset invalid cached variable.
+    message(WARNING "Reverting invalid option LLDB_USE_SYSTEM_DEBUGSERVER (Darwin only)")
+    set(LLDB_USE_SYSTEM_DEBUGSERVER OFF CACHE BOOL "" FORCE)
   endif()
-  set(SKIP_DEBUGSERVER ON CACHE BOOL "Skip building the in-tree debug server")
+elseif(NOT LLDB_NO_DEBUGSERVER)
+  # Default case: on Darwin we need the right code signing ID.
+  # See lldb/docs/code-signing.txt for details.
+  if(CMAKE_HOST_APPLE AND NOT LLVM_CODESIGNING_IDENTITY STREQUAL "lldb_codesign")
+    set(problem "Cannot code sign debugserver with LLVM_CODESIGNING_IDENTITY '${LLVM_CODESIGNING_IDENTITY}'.")
+    set(advice "Pass -DLLDB_CODESIGN_IDENTITY=lldb_codesign to override the LLVM value for debugserver.")
+    if(system_debugserver)
+      set(effect "Will fall back to system's debugserver.")
+      set(use_system_debugserver ON)
+    else()
+      set(effect "debugserver will not be available.")
+    endif()
+    message(WARNING "${problem} ${effect} ${advice}")
+  else()
+    set(build_and_sign_debugserver ON)
+  endif()
+endif()
+
+# TODO: We don't use the $<TARGET_FILE:debugserver> generator expression here,
+# because the value of DEBUGSERVER_PATH is used to build LLDB_DOTEST_ARGS,
+# which is used for configuring lldb-dotest.in, which does not have a generator
+# step at the moment.
+set(default_debugserver_path "${LLVM_RUNTIME_OUTPUT_INTDIR}/debugserver${CMAKE_EXECUTABLE_SUFFIX}")
+
+# Remember where debugserver binary goes and whether or not we have to test it.
+set(DEBUGSERVER_PATH "" CACHE FILEPATH "Path to debugserver")
+set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "Building the in-tree debugserver was skipped")
+
+# Reset values in all cases in order to correctly support reconfigurations.
+if(use_system_debugserver)
+  add_custom_target(debugserver
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different
+            ${system_debugserver} ${LLVM_RUNTIME_OUTPUT_INTDIR}
+    COMMENT "Copying the system debugserver to LLDB's binaries directory.")
+
+  # Don't test debugserver itself.
+  # Tests that require debugserver will use the copy.
+  set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE)
+  set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE)
+
+  message(STATUS "Copy system debugserver from: ${system_debugserver}")
+elseif(build_and_sign_debugserver)
+  # Build, sign and test debugserver (below)
+  set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE)
+  set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "" FORCE)
+
+  message(STATUS "lldb debugserver: ${DEBUGSERVER_PATH}")
+else()
+  # No tests for debugserver, no tests that require it.
+  set(DEBUGSERVER_PATH "" CACHE FILEPATH "" FORCE)
+  set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE)
+
+  message(STATUS "lldb debugserver will not be available.")
 endif()
-message(STATUS "Path to the lldb debugserver: ${DEBUGSERVER_PATH}")
 
-if (APPLE)
+if(APPLE)
   if(IOS)
     find_library(BACKBOARD_LIBRARY BackBoardServices
       PATHS ${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks)
@@ -132,7 +221,7 @@ if (APPLE)
     find_library(LOCKDOWN_LIBRARY lockdown)
 
     if(NOT BACKBOARD_LIBRARY)
-      set(SKIP_DEBUGSERVER ON CACHE BOOL "Skip building the in-tree debug server" FORCE)
+      set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE)
     endif()
   else()
     find_library(COCOA_LIBRARY Cocoa)
@@ -143,7 +232,16 @@ if(HAVE_LIBCOMPRESSION)
   set(LIBCOMPRESSION compression)
 endif()
 
-if(NOT SKIP_DEBUGSERVER)
+if(LLDB_USE_ENTITLEMENTS)
+  if(IOS)
+    set(entitlements ${CMAKE_CURRENT_SOURCE_DIR}/debugserver-entitlements.plist)
+  else()
+    # Same entitlements file as used for lldb-server
+    set(entitlements ${LLDB_SOURCE_DIR}/resources/debugserver-macosx-entitlements.plist)
+  endif()
+endif()
+
+if(build_and_sign_debugserver)
   target_link_libraries(lldbDebugserverCommon
                         INTERFACE ${COCOA_LIBRARY}
                         ${CORE_FOUNDATION_LIBRARY}
@@ -166,6 +264,9 @@ if(NOT SKIP_DEBUGSERVER)
 
     LINK_LIBS
       lldbDebugserverCommon
+
+    ENTITLEMENTS
+      ${entitlements}
     )
   if(IOS)
     set_property(TARGET lldbDebugserverCommon APPEND PROPERTY COMPILE_DEFINITIONS
@@ -203,54 +304,8 @@ if(IOS)
 
     LINK_LIBS
       lldbDebugserverCommon_NonUI
-    )
-endif()
-
-set(entitlements_xml ${CMAKE_CURRENT_SOURCE_DIR}/debugserver-macosx-entitlements.plist)
-if(IOS)
-  set(entitlements_xml ${CMAKE_CURRENT_SOURCE_DIR}/debugserver-entitlements.plist)
-else()
-  set(entitlements_xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../resources/debugserver-macosx-entitlements.plist)
-endif()
-
-set(LLDB_USE_ENTITLEMENTS_Default On)
-option(LLDB_USE_ENTITLEMENTS "Use entitlements when codesigning (Defaults Off when using lldb_codesign identity, otherwise On)" ${LLDB_USE_ENTITLEMENTS_Default})
 
-if (SKIP_DEBUGSERVER)
-  if (CMAKE_HOST_APPLE)
-    # If we haven't built a signed debugserver, copy the one from the system.
-    add_custom_target(debugserver
-      COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DEBUGSERVER_PATH} ${CMAKE_BINARY_DIR}/bin
-      VERBATIM
-      COMMENT "Copying the system debugserver to LLDB's binaries directory.")
-  endif()
-else()
-  if(LLDB_USE_ENTITLEMENTS)
-    set(entitlements_flags --entitlements ${entitlements_xml})
-  endif()
-  execute_process(
-    COMMAND xcrun -f codesign_allocate
-    OUTPUT_STRIP_TRAILING_WHITESPACE
-    OUTPUT_VARIABLE CODESIGN_ALLOCATE
-    )
-  add_custom_command(TARGET debugserver
-    POST_BUILD
-    COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE}
-            codesign --force --sign ${LLDB_CODESIGN_IDENTITY}
-            ${entitlements_flags}
-            $<TARGET_FILE:debugserver>
-  )
-  if(IOS)
-    add_custom_command(TARGET debugserver-nonui
-      POST_BUILD
-      COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE}
-              codesign --force --sign ${LLDB_CODESIGN_IDENTITY}
-              ${entitlements_flags}
-              $<TARGET_FILE:debugserver>
+    ENTITLEMENTS
+      ${entitlements}
     )
-  endif()
 endif()
-
-
-
-
diff --git a/lldb/unittests/tools/CMakeLists.txt b/lldb/unittests/tools/CMakeLists.txt
index bce076ee91ec..d180ebe8987d 100644
--- a/lldb/unittests/tools/CMakeLists.txt
+++ b/lldb/unittests/tools/CMakeLists.txt
@@ -1,5 +1,5 @@
 if(CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|Linux|NetBSD")
-  if ((CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_DEBUGSERVER) OR (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_LLDB_SERVER_BUILD))
+  if ((CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_TEST_DEBUGSERVER) OR (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_LLDB_SERVER_BUILD))
     # These tests are meant to test lldb-server/debugserver in isolation, and
     # don't provide any value if run against a server copied from somewhere.
   else()
diff --git a/lldb/unittests/tools/lldb-server/CMakeLists.txt b/lldb/unittests/tools/lldb-server/CMakeLists.txt
index dcbd9bed529f..60616c93153f 100644
--- a/lldb/unittests/tools/lldb-server/CMakeLists.txt
+++ b/lldb/unittests/tools/lldb-server/CMakeLists.txt
@@ -12,7 +12,7 @@ endfunction()
 add_lldb_test_executable(thread_inferior inferior/thread_inferior.cpp)
 add_lldb_test_executable(environment_check inferior/environment_check.cpp)
 
-if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+if(DEBUGSERVER_PATH)
   add_definitions(-DLLDB_SERVER="${DEBUGSERVER_PATH}" -DLLDB_SERVER_IS_DEBUGSERVER=1)
 else()
   add_definitions(-DLLDB_SERVER="$<TARGET_FILE:lldb-server>" -DLLDB_SERVER_IS_DEBUGSERVER=0)