code:
# This is a generated file and its contents are an internal implementation detail.
# The update step will be re-executed if anything in this file changes.
# No other meaning or use of this file is supported.

command=@cmd@
work_dir=@work_dir@

repo_name: lazytadpole/codenamesilverfish

license: mit


code:
# This is a generated file and its contents are an internal implementation detail.
# The download step will be re-executed if anything in this file changes.
# No other meaning or use of this file is supported.

method=@method@
command=@cmd@
source_dir=@source_dir@
work_dir=@work_dir@
@extra_repo_info@


code:
# This is a generated file and its contents are an internal implementation detail.
# The patch step will be re-executed if anything in this file changes.
# No other meaning or use of this file is supported.

command (connected)=@cmd@
command (disconnected)=@cmd_disconnected@
work_dir=@work_dir@


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

function(check_file_hash has_hash hash_is_good)
  if("${has_hash}" STREQUAL "")
    message(FATAL_ERROR "has_hash Can't be empty")
  endif()

  if("${hash_is_good}" STREQUAL "")
    message(FATAL_ERROR "hash_is_good Can't be empty")
  endif()

  if("@ALGO@" STREQUAL "")
    # No check
    set("${has_hash}" FALSE PARENT_SCOPE)
    set("${hash_is_good}" FALSE PARENT_SCOPE)
    return()
  endif()

  set("${has_hash}" TRUE PARENT_SCOPE)

  message(STATUS "verifying file...
       file='@LOCAL@'")

  file("@ALGO@" "@LOCAL@" actual_value)

  if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@")
    set("${hash_is_good}" FALSE PARENT_SCOPE)
    message(STATUS "@ALGO@ hash of
    @LOCAL@
  does not match expected value
    expected: '@EXPECT_VALUE@'
      actual: '${actual_value}'")
  else()
    set("${hash_is_good}" TRUE PARENT_SCOPE)
  endif()
endfunction()

function(sleep_before_download attempt)
  if(attempt EQUAL 0)
    return()
  endif()

  if(attempt EQUAL 1)
    message(STATUS "Retrying...")
    return()
  endif()

  set(sleep_seconds 0)

  if(attempt EQUAL 2)
    set(sleep_seconds 5)
  elseif(attempt EQUAL 3)
    set(sleep_seconds 5)
  elseif(attempt EQUAL 4)
    set(sleep_seconds 15)
  elseif(attempt EQUAL 5)
    set(sleep_seconds 60)
  elseif(attempt EQUAL 6)
    set(sleep_seconds 90)
  elseif(attempt EQUAL 7)
    set(sleep_seconds 300)
  else()
    set(sleep_seconds 1200)
  endif()

  message(STATUS "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ...")

  execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep "${sleep_seconds}")
endfunction()

if(EXISTS "@LOCAL@")
  check_file_hash(has_hash hash_is_good)
  if(has_hash)
    if(hash_is_good)
      message(STATUS "File already exists and hash match (skip download):
  file='@LOCAL@'
  @ALGO@='@EXPECT_VALUE@'"
      )
      return()
    else()
      message(STATUS "File already exists but hash mismatch. Removing...")
      file(REMOVE "@LOCAL@")
    endif()
  else()
    message(STATUS "File already exists but no hash specified (use URL_HASH):
  file='@LOCAL@'
Old file will be removed and new file downloaded from URL."
    )
    file(REMOVE "@LOCAL@")
  endif()
endif()

set(retry_number 5)

message(STATUS "Downloading...
   dst='@LOCAL@'
   timeout='@TIMEOUT_MSG@'
   inactivity timeout='@INACTIVITY_TIMEOUT_MSG@'"
)
set(download_retry_codes 7 6 8 15 28)
set(skip_url_list)
set(status_code)
foreach(i RANGE ${retry_number})
  if(status_code IN_LIST download_retry_codes)
    sleep_before_download(${i})
  endif()
  foreach(url IN ITEMS @REMOTE@)
    if(NOT url IN_LIST skip_url_list)
      message(STATUS "Using src='${url}'")

      @TLS_VERIFY_CODE@
      @TLS_CAINFO_CODE@
      @NETRC_CODE@
      @NETRC_FILE_CODE@

      file(
        DOWNLOAD
        "${url}" "@LOCAL@"
        @SHOW_PROGRESS@
        @TIMEOUT_ARGS@
        @INACTIVITY_TIMEOUT_ARGS@
        STATUS status
        LOG log
        @USERPWD_ARGS@
        @HTTP_HEADERS_ARGS@
        )

      list(GET status 0 status_code)
      list(GET status 1 status_string)

      if(status_code EQUAL 0)
        check_file_hash(has_hash hash_is_good)
        if(has_hash AND NOT hash_is_good)
          message(STATUS "Hash mismatch, removing...")
          file(REMOVE "@LOCAL@")
        else()
          message(STATUS "Downloading... done")
          return()
        endif()
      else()
        string(APPEND logFailedURLs "error: downloading '${url}' failed
        status_code: ${status_code}
        status_string: ${status_string}
        log:
        --- LOG BEGIN ---
        ${log}
        --- LOG END ---
        "
        )
      if(NOT status_code IN_LIST download_retry_codes)
        list(APPEND skip_url_list "${url}")
        break()
      endif()
    endif()
  endif()
  endforeach()
endforeach()

message(FATAL_ERROR "Each download failed!
  ${logFailedURLs}
  "
)


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

# Make file names absolute:
#
get_filename_component(filename "@filename@" ABSOLUTE)
get_filename_component(directory "@directory@" ABSOLUTE)

message(STATUS "extracting...
     src='${filename}'
     dst='${directory}'"
)

if(NOT EXISTS "${filename}")
  message(FATAL_ERROR "File to extract does not exist: '${filename}'")
endif()

# Prepare a space for extracting:
#
set(i 1234)
while(EXISTS "${directory}/../ex-@name@${i}")
  math(EXPR i "${i} + 1")
endwhile()
set(ut_dir "${directory}/../ex-@name@${i}")
file(MAKE_DIRECTORY "${ut_dir}")

# Extract it:
#
message(STATUS "extracting... [tar @args@]")
execute_process(COMMAND ${CMAKE_COMMAND} -E tar @args@ ${filename} @options@
  WORKING_DIRECTORY ${ut_dir}
  RESULT_VARIABLE rv
)

if(NOT rv EQUAL 0)
  message(STATUS "extracting... [error clean up]")
  file(REMOVE_RECURSE "${ut_dir}")
  message(FATAL_ERROR "Extract of '${filename}' failed")
endif()

# Analyze what came out of the tar file:
#
message(STATUS "extracting... [analysis]")
file(GLOB contents "${ut_dir}/*")
list(REMOVE_ITEM contents "${ut_dir}/.DS_Store")
list(LENGTH contents n)
if(NOT n EQUAL 1 OR NOT IS_DIRECTORY "${contents}")
  set(contents "${ut_dir}")
endif()

# Move "the one" directory to the final directory:
#
message(STATUS "extracting... [rename]")
file(REMOVE_RECURSE ${directory})
get_filename_component(contents ${contents} ABSOLUTE)
file(RENAME ${contents} ${directory})

# Clean up:
#
message(STATUS "extracting... [clean up]")
file(REMOVE_RECURSE "${ut_dir}")

message(STATUS "extracting... done")


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

if(EXISTS "@gitclone_stampfile@" AND EXISTS "@gitclone_infofile@" AND
  "@gitclone_stampfile@" IS_NEWER_THAN "@gitclone_infofile@")
  message(STATUS
    "Avoiding repeated git clone, stamp file is up to date: "
    "'@gitclone_stampfile@'"
  )
  return()
endif()

execute_process(
  COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@"
  RESULT_VARIABLE error_code
)
if(error_code)
  message(FATAL_ERROR "Failed to remove directory: '@source_dir@'")
endif()

# try the clone 3 times in case there is an odd git clone issue
set(error_code 1)
set(number_of_tries 0)
while(error_code AND number_of_tries LESS 3)
  execute_process(
    COMMAND "@git_EXECUTABLE@"
            clone @git_clone_options@ "@git_repository@" "@src_name@"
    WORKING_DIRECTORY "@work_dir@"
    RESULT_VARIABLE error_code
  )
  math(EXPR number_of_tries "${number_of_tries} + 1")
endwhile()
if(number_of_tries GREATER 1)
  message(STATUS "Had to git clone more than once: ${number_of_tries} times.")
endif()
if(error_code)
  message(FATAL_ERROR "Failed to clone repository: '@git_repository@'")
endif()

execute_process(
  COMMAND "@git_EXECUTABLE@"
          checkout "@git_tag@" @git_checkout_explicit--@
  WORKING_DIRECTORY "@work_dir@/@src_name@"
  RESULT_VARIABLE error_code
)
if(error_code)
  message(FATAL_ERROR "Failed to checkout tag: '@git_tag@'")
endif()

set(init_submodules @init_submodules@)
if(init_submodules)
  execute_process(
    COMMAND "@git_EXECUTABLE@" @git_submodules_config_options@
            submodule update @git_submodules_recurse@ --init @git_submodules@
    WORKING_DIRECTORY "@work_dir@/@src_name@"
    RESULT_VARIABLE error_code
  )
endif()
if(error_code)
  message(FATAL_ERROR "Failed to update submodules in: '@work_dir@/@src_name@'")
endif()

# Complete success, update the script-last-run stamp file:
#
execute_process(
  COMMAND ${CMAKE_COMMAND} -E copy "@gitclone_infofile@" "@gitclone_stampfile@"
  RESULT_VARIABLE error_code
)
if(error_code)
  message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@gitclone_stampfile@'")
endif()


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

function(do_fetch)
  message(VERBOSE "Fetching latest from the remote @git_remote_name@")
  execute_process(
    COMMAND "@git_EXECUTABLE@" --git-dir=.git fetch --tags --force "@git_remote_name@"
    WORKING_DIRECTORY "@work_dir@"
    COMMAND_ERROR_IS_FATAL LAST
  )
endfunction()

function(get_hash_for_ref ref out_var err_var)
  execute_process(
    COMMAND "@git_EXECUTABLE@" --git-dir=.git rev-parse "${ref}^0"
    WORKING_DIRECTORY "@work_dir@"
    RESULT_VARIABLE error_code
    OUTPUT_VARIABLE ref_hash
    ERROR_VARIABLE error_msg
    OUTPUT_STRIP_TRAILING_WHITESPACE
  )
  if(error_code)
    set(${out_var} "" PARENT_SCOPE)
  else()
    set(${out_var} "${ref_hash}" PARENT_SCOPE)
  endif()
  set(${err_var} "${error_msg}" PARENT_SCOPE)
endfunction()

get_hash_for_ref(HEAD head_sha error_msg)
if(head_sha STREQUAL "")
  message(FATAL_ERROR "Failed to get the hash for HEAD:\n${error_msg}")
endif()

execute_process(
  COMMAND "@git_EXECUTABLE@" --git-dir=.git show-ref "@git_tag@"
  WORKING_DIRECTORY "@work_dir@"
  OUTPUT_VARIABLE show_ref_output
)
if(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/remotes/")
  # Given a full remote/branch-name and we know about it already. Since
  # branches can move around, we should always fetch, if permitted.
  if(can_fetch)
    do_fetch()
  endif()
  set(checkout_name "@git_tag@")

elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/tags/")
  # Given a tag name that we already know about. We don't know if the tag we
  # have matches the remote though (tags can move), so we should fetch. As a
  # special case to preserve backward compatibility, if we are already at the
  # same commit as the tag we hold locally, don't do a fetch and assume the tag
  # hasn't moved on the remote.
  # FIXME: We should provide an option to always fetch for this case
  get_hash_for_ref("@git_tag@" tag_sha error_msg)
  if(tag_sha STREQUAL head_sha)
    message(VERBOSE "Already at requested tag: ${tag_sha}")
    return()
  endif()

  if(can_fetch)
    do_fetch()
  endif()
  set(checkout_name "@git_tag@")

elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/heads/")
  # Given a branch name without any remote and we already have a branch by that
  # name. We might already have that branch checked out or it might be a
  # different branch. It isn't fully safe to use a bare branch name without the
  # remote, so do a fetch (if allowed) and replace the ref with one that
  # includes the remote.
  if(can_fetch)
    do_fetch()
  endif()
  set(checkout_name "@git_remote_name@/@git_tag@")

else()
  get_hash_for_ref("@git_tag@" tag_sha error_msg)
  if(tag_sha STREQUAL head_sha)
    # Have the right commit checked out already
    message(VERBOSE "Already at requested ref: ${tag_sha}")
    return()

  elseif(tag_sha STREQUAL "")
    # We don't know about this ref yet, so we have no choice but to fetch.
    if(NOT can_fetch)
      message(FATAL_ERROR
        "Requested git ref \"@git_tag@\" is not present locally, and not "
        "allowed to contact remote due to UPDATE_DISCONNECTED setting."
      )
    endif()

    # We deliberately swallow any error message at the default log level
    # because it can be confusing for users to see a failed git command.
    # That failure is being handled here, so it isn't an error.
    if(NOT error_msg STREQUAL "")
      message(VERBOSE "${error_msg}")
    endif()
    do_fetch()
    set(checkout_name "@git_tag@")

  else()
    # We have the commit, so we know we were asked to find a commit hash
    # (otherwise it would have been handled further above), but we don't
    # have that commit checked out yet. We don't need to fetch from the remote.
    set(checkout_name "@git_tag@")
    if(NOT error_msg STREQUAL "")
      message(WARNING "${error_msg}")
    endif()

  endif()
endif()

set(git_update_strategy "@git_update_strategy@")
if(git_update_strategy STREQUAL "")
  # Backward compatibility requires REBASE as the default behavior
  set(git_update_strategy REBASE)
endif()

if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$")
  # Asked to potentially try to rebase first, maybe with fallback to checkout.
  # We can't if we aren't already on a branch and we shouldn't if that local
  # branch isn't tracking the one we want to checkout.
  execute_process(
    COMMAND "@git_EXECUTABLE@" --git-dir=.git symbolic-ref -q HEAD
    WORKING_DIRECTORY "@work_dir@"
    OUTPUT_VARIABLE current_branch
    OUTPUT_STRIP_TRAILING_WHITESPACE
    # Don't test for an error. If this isn't a branch, we get a non-zero error
    # code but empty output.
  )

  if(current_branch STREQUAL "")
    # Not on a branch, checkout is the only sensible option since any rebase
    # would always fail (and backward compatibility requires us to checkout in
    # this situation)
    set(git_update_strategy CHECKOUT)

  else()
    execute_process(
      COMMAND "@git_EXECUTABLE@" --git-dir=.git for-each-ref "--format=%(upstream:short)" "${current_branch}"
      WORKING_DIRECTORY "@work_dir@"
      OUTPUT_VARIABLE upstream_branch
      OUTPUT_STRIP_TRAILING_WHITESPACE
      COMMAND_ERROR_IS_FATAL ANY  # There is no error if no upstream is set
    )
    if(NOT upstream_branch STREQUAL checkout_name)
      # Not safe to rebase when asked to checkout a different branch to the one
      # we are tracking. If we did rebase, we could end up with arbitrary
      # commits added to the ref we were asked to checkout if the current local
      # branch happens to be able to rebase onto the target branch. There would
      # be no error message and the user wouldn't know this was occurring.
      set(git_update_strategy CHECKOUT)
    endif()

  endif()
elseif(NOT git_update_strategy STREQUAL "CHECKOUT")
  message(FATAL_ERROR "Unsupported git update strategy: ${git_update_strategy}")
endif()

# Check if stash is needed
execute_process(
  COMMAND "@git_EXECUTABLE@" --git-dir=.git status --porcelain
  WORKING_DIRECTORY "@work_dir@"
  RESULT_VARIABLE error_code
  OUTPUT_VARIABLE repo_status
)
if(error_code)
  message(FATAL_ERROR "Failed to get the status")
endif()
string(LENGTH "${repo_status}" need_stash)

# If not in clean state, stash changes in order to be able to perform a
# rebase or checkout without losing those changes permanently
if(need_stash)
  execute_process(
    COMMAND "@git_EXECUTABLE@" --git-dir=.git stash save @git_stash_save_options@
    WORKING_DIRECTORY "@work_dir@"
    COMMAND_ERROR_IS_FATAL ANY
  )
endif()

if(git_update_strategy STREQUAL "CHECKOUT")
  execute_process(
    COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}"
    WORKING_DIRECTORY "@work_dir@"
    COMMAND_ERROR_IS_FATAL ANY
  )
else()
  execute_process(
    COMMAND "@git_EXECUTABLE@" --git-dir=.git rebase "${checkout_name}"
    WORKING_DIRECTORY "@work_dir@"
    RESULT_VARIABLE error_code
    OUTPUT_VARIABLE rebase_output
    ERROR_VARIABLE  rebase_output
  )
  if(error_code)
    # Rebase failed, undo the rebase attempt before continuing
    execute_process(
      COMMAND "@git_EXECUTABLE@" --git-dir=.git rebase --abort
      WORKING_DIRECTORY "@work_dir@"
    )

    if(NOT git_update_strategy STREQUAL "REBASE_CHECKOUT")
      # Not allowed to do a checkout as a fallback, so cannot proceed
      if(need_stash)
        execute_process(
          COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
          WORKING_DIRECTORY "@work_dir@"
          )
      endif()
      message(FATAL_ERROR "\nFailed to rebase in: '@work_dir@'."
                          "\nOutput from the attempted rebase follows:"
                          "\n${rebase_output}"
                          "\n\nYou will have to resolve the conflicts manually")
    endif()

    # Fall back to checkout. We create an annotated tag so that the user
    # can manually inspect the situation and revert if required.
    # We can't log the failed rebase output because MSVC sees it and
    # intervenes, causing the build to fail even though it completes.
    # Write it to a file instead.
    string(TIMESTAMP tag_timestamp "%Y%m%dT%H%M%S" UTC)
    set(tag_name _cmake_ExternalProject_moved_from_here_${tag_timestamp}Z)
    set(error_log_file ${CMAKE_CURRENT_LIST_DIR}/rebase_error_${tag_timestamp}Z.log)
    file(WRITE ${error_log_file} "${rebase_output}")
    message(WARNING "Rebase failed, output has been saved to ${error_log_file}"
                    "\nFalling back to checkout, previous commit tagged as ${tag_name}")
    execute_process(
      COMMAND "@git_EXECUTABLE@" --git-dir=.git tag -a
              -m "ExternalProject attempting to move from here to ${checkout_name}"
              ${tag_name}
      WORKING_DIRECTORY "@work_dir@"
      COMMAND_ERROR_IS_FATAL ANY
    )

    execute_process(
      COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}"
      WORKING_DIRECTORY "@work_dir@"
      COMMAND_ERROR_IS_FATAL ANY
    )
  endif()
endif()

if(need_stash)
  # Put back the stashed changes
  execute_process(
    COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
    WORKING_DIRECTORY "@work_dir@"
    RESULT_VARIABLE error_code
    )
  if(error_code)
    # Stash pop --index failed: Try again dropping the index
    execute_process(
      COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet
      WORKING_DIRECTORY "@work_dir@"
    )
    execute_process(
      COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --quiet
      WORKING_DIRECTORY "@work_dir@"
      RESULT_VARIABLE error_code
    )
    if(error_code)
      # Stash pop failed: Restore previous state.
      execute_process(
        COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet ${head_sha}
        WORKING_DIRECTORY "@work_dir@"
      )
      execute_process(
        COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet
        WORKING_DIRECTORY "@work_dir@"
      )
      message(FATAL_ERROR "\nFailed to unstash changes in: '@work_dir@'."
                          "\nYou will have to resolve the conflicts manually")
    endif()
  endif()
endif()

set(init_submodules "@init_submodules@")
if(init_submodules)
  execute_process(
    COMMAND "@git_EXECUTABLE@"
            --git-dir=.git @git_submodules_config_options@
            submodule update @git_submodules_recurse@ --init @git_submodules@
    WORKING_DIRECTORY "@work_dir@"
    COMMAND_ERROR_IS_FATAL ANY
  )
endif()


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

if(EXISTS "@hgclone_stampfile@" AND EXISTS "@hgclone_infofile@" AND
  "@hgclone_stampfile@" IS_NEWER_THAN "@hgclone_infofile@")
  message(STATUS
    "Avoiding repeated hg clone, stamp file is up to date: "
    "'@hgclone_stampfile@'"
  )
  return()
endif()

execute_process(
  COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@"
  RESULT_VARIABLE error_code
)
if(error_code)
  message(FATAL_ERROR "Failed to remove directory: '@source_dir@'")
endif()

execute_process(
  COMMAND "@hg_EXECUTABLE@" clone -U "@hg_repository@" "@src_name@"
  WORKING_DIRECTORY "@work_dir@"
  RESULT_VARIABLE error_code
)
if(error_code)
  message(FATAL_ERROR "Failed to clone repository: '@hg_repository@'")
endif()

execute_process(
  COMMAND "@hg_EXECUTABLE@" update @hg_tag@
  WORKING_DIRECTORY "@work_dir@/@src_name@"
  RESULT_VARIABLE error_code
)
if(error_code)
  message(FATAL_ERROR "Failed to checkout tag: '@hg_tag@'")
endif()

# Complete success, update the script-last-run stamp file:
#
execute_process(
  COMMAND ${CMAKE_COMMAND} -E copy "@hgclone_infofile@" "@hgclone_stampfile@"
  RESULT_VARIABLE error_code
)
if(error_code)
  message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@hgclone_stampfile@'")
endif()


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

file(MAKE_DIRECTORY
  "@source_dir@"
  "@binary_dir@"
  "@install_dir@"
  "@tmp_dir@"
  "@stamp_dir@"
  "@download_dir@"
  "@log_dir@"
)

set(configSubDirs @CMAKE_CONFIGURATION_TYPES@)
foreach(subDir IN LISTS configSubDirs)
    file(MAKE_DIRECTORY "@stamp_dir@/${subDir}")
endforeach()
if(cfgdir)
  file(MAKE_DIRECTORY "@stamp_dir@${cfgdir}") # cfgdir has leading slash
endif()


code:
cmake_policy(VERSION 3.25)

# Determine the remote URL of the project containing the working_directory.
# This will leave output_variable unset if the URL can't be determined.
function(_ep_get_git_remote_url output_variable working_directory)
  set("${output_variable}" "" PARENT_SCOPE)

  find_package(Git QUIET REQUIRED)

  execute_process(
    COMMAND ${GIT_EXECUTABLE} symbolic-ref --short HEAD
    WORKING_DIRECTORY "${working_directory}"
    OUTPUT_VARIABLE git_symbolic_ref
    OUTPUT_STRIP_TRAILING_WHITESPACE
    ERROR_QUIET
  )

  if(NOT git_symbolic_ref STREQUAL "")
    # We are potentially on a branch. See if that branch is associated with
    # an upstream remote (might be just a local one or not a branch at all).
    execute_process(
      COMMAND ${GIT_EXECUTABLE} config branch.${git_symbolic_ref}.remote
      WORKING_DIRECTORY "${working_directory}"
      OUTPUT_VARIABLE git_remote_name
      OUTPUT_STRIP_TRAILING_WHITESPACE
      ERROR_QUIET
    )
  endif()

  if(NOT git_remote_name)
    # Can't select a remote based on a branch. If there's only one remote,
    # or we have multiple remotes but one is called "origin", choose that.
    execute_process(
      COMMAND ${GIT_EXECUTABLE} remote
      WORKING_DIRECTORY "${working_directory}"
      OUTPUT_VARIABLE git_remote_list
      OUTPUT_STRIP_TRAILING_WHITESPACE
      ERROR_QUIET
    )
    string(REPLACE "\n" ";" git_remote_list "${git_remote_list}")
    list(LENGTH git_remote_list git_remote_list_length)

    if(git_remote_list_length EQUAL 0)
      message(FATAL_ERROR "Git remote not found in parent project.")
    elseif(git_remote_list_length EQUAL 1)
      list(GET git_remote_list 0 git_remote_name)
    else()
      set(base_warning_msg "Multiple git remotes found for parent project")
      if("origin" IN_LIST git_remote_list)
        message(WARNING "${base_warning_msg}, defaulting to origin.")
        set(git_remote_name "origin")
      else()
        message(FATAL_ERROR "${base_warning_msg}, none of which are origin.")
      endif()
    endif()
  endif()

  if(GIT_VERSION VERSION_LESS 1.7.5)
    set(_git_remote_url_cmd_args config remote.${git_remote_name}.url)
  elseif(GIT_VERSION VERSION_LESS 2.7)
    set(_git_remote_url_cmd_args ls-remote --get-url ${git_remote_name})
  else()
    set(_git_remote_url_cmd_args remote get-url ${git_remote_name})
  endif()

  execute_process(
    COMMAND ${GIT_EXECUTABLE} ${_git_remote_url_cmd_args}
    WORKING_DIRECTORY "${working_directory}"
    OUTPUT_VARIABLE git_remote_url
    OUTPUT_STRIP_TRAILING_WHITESPACE
    COMMAND_ERROR_IS_FATAL LAST
    ENCODING UTF-8   # Needed to handle non-ascii characters in local paths
  )

  set("${output_variable}" "${git_remote_url}" PARENT_SCOPE)
endfunction()

function(_ep_is_relative_git_remote output_variable remote_url)
  if(remote_url MATCHES "^\\.\\./")
    set("${output_variable}" TRUE PARENT_SCOPE)
  else()
    set("${output_variable}" FALSE PARENT_SCOPE)
  endif()
endfunction()

# Return an absolute remote URL given an existing remote URL and relative path.
# The output_variable will be set to an empty string if an absolute URL
# could not be computed (no error message is output).
function(_ep_resolve_relative_git_remote
  output_variable
  parent_remote_url
  relative_remote_url
)
  set("${output_variable}" "" PARENT_SCOPE)

  if(parent_remote_url STREQUAL "")
    return()
  endif()

  string(REGEX MATCH
    "^(([A-Za-z0-9][A-Za-z0-9+.-]*)://)?(([^/@]+)@)?(\\[[A-Za-z0-9:]+\\]|[^/:]+)?([/:]/?)(.+(\\.git)?/?)$"
    git_remote_url_components
    "${parent_remote_url}"
  )

  set(protocol "${CMAKE_MATCH_1}")
  set(auth "${CMAKE_MATCH_3}")
  set(host "${CMAKE_MATCH_5}")
  set(separator "${CMAKE_MATCH_6}")
  set(path "${CMAKE_MATCH_7}")

  string(REPLACE "/" ";" remote_path_components "${path}")
  string(REPLACE "/" ";" relative_path_components "${relative_remote_url}")

  foreach(relative_path_component IN LISTS relative_path_components)
    if(NOT relative_path_component STREQUAL "..")
      break()
    endif()

    list(LENGTH remote_path_components remote_path_component_count)

    if(remote_path_component_count LESS 1)
      return()
    endif()

    list(POP_BACK remote_path_components)
    list(POP_FRONT relative_path_components)
  endforeach()

  list(APPEND final_path_components ${remote_path_components} ${relative_path_components})
  list(JOIN final_path_components "/" path)

  set("${output_variable}" "${protocol}${auth}${host}${separator}${path}" PARENT_SCOPE)
endfunction()

# The output_variable will be set to the original git_repository if it
# could not be resolved (no error message is output). The original value is
# also returned if it doesn't need to be resolved.
function(_ep_resolve_git_remote
  output_variable
  git_repository
  cmp0150
  cmp0150_old_base_dir
)
  if(git_repository STREQUAL "")
    set("${output_variable}" "" PARENT_SCOPE)
    return()
  endif()

  _ep_is_relative_git_remote(_git_repository_is_relative "${git_repository}")

  if(NOT _git_repository_is_relative)
    set("${output_variable}" "${git_repository}" PARENT_SCOPE)
    return()
  endif()

  if(cmp0150 STREQUAL "NEW")
    _ep_get_git_remote_url(_parent_git_remote_url "${CMAKE_CURRENT_SOURCE_DIR}")
    _ep_resolve_relative_git_remote(_resolved_git_remote_url "${_parent_git_remote_url}" "${git_repository}")

    if(_resolved_git_remote_url STREQUAL "")
      message(FATAL_ERROR
        "Failed to resolve relative git remote URL:\n"
        "  Relative URL: ${git_repository}\n"
        "  Parent URL:   ${_parent_git_remote_url}"
      )
    endif()
    set("${output_variable}" "${_resolved_git_remote_url}" PARENT_SCOPE)
    return()
  elseif(cmp0150 STREQUAL "")
    cmake_policy(GET_WARNING CMP0150 _cmp0150_warning)
    message(AUTHOR_WARNING
      "${_cmp0150_warning}\n"
      "A relative GIT_REPOSITORY path was detected. "
      "This will be interpreted as a local path to where the project is being cloned. "
      "Set GIT_REPOSITORY to an absolute path or set policy CMP0150 to NEW to avoid "
      "this warning."
    )
  endif()

  set("${output_variable}" "${cmp0150_old_base_dir}/${git_repository}" PARENT_SCOPE)
endfunction()


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

if("@LOCAL@" STREQUAL "")
  message(FATAL_ERROR "LOCAL can't be empty")
endif()

if(NOT EXISTS "@LOCAL@")
  message(FATAL_ERROR "File not found: @LOCAL@")
endif()

if("@ALGO@" STREQUAL "")
  message(WARNING "File will not be verified since no URL_HASH specified")
  return()
endif()

if("@EXPECT_VALUE@" STREQUAL "")
  message(FATAL_ERROR "EXPECT_VALUE can't be empty")
endif()

message(STATUS "verifying file...
     file='@LOCAL@'")

file("@ALGO@" "@LOCAL@" actual_value)

if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@")
  message(FATAL_ERROR "error: @ALGO@ hash of
  @LOCAL@
does not match expected value
  expected: '@EXPECT_VALUE@'
    actual: '${actual_value}'
")
endif()

message(STATUS "verifying file... done")


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

include(CheckIncludeFile)


code:
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

#[=======================================================================[.rst:
FeatureSummary
--------------

Functions for generating a summary of enabled/disabled features.

These functions can be used to generate a summary of enabled and disabled
packages and/or feature for a build tree such as::

    -- The following OPTIONAL packages have been found:
    LibXml2 (required version >= 2.4), XML processing lib, <http://xmlsoft.org>
       * Enables HTML-import in MyWordProcessor
       * Enables odt-export in MyWordProcessor
    PNG, A PNG image library., <http://www.libpng.org/pub/png/>
       * Enables saving screenshots
    -- The following OPTIONAL packages have not been found:
    Lua51, The Lua scripting language., <https://www.lua.org>
       * Enables macros in MyWordProcessor
    Foo, Foo provides cool stuff.

Global Properties
^^^^^^^^^^^^^^^^^

.. variable:: FeatureSummary_PKG_TYPES

The global property :variable:`FeatureSummary_PKG_TYPES` defines the type of
packages used by `FeatureSummary`.

The order in this list is important, the first package type in the list is the
least important, the last is the most important. the of a package can only be
changed to higher types.

The default package types are , ``RUNTIME``, ``OPTIONAL``, ``RECOMMENDED`` and
``REQUIRED``, and their importance is
``RUNTIME < OPTIONAL < RECOMMENDED < REQUIRED``.

.. variable:: FeatureSummary_REQUIRED_PKG_TYPES

The global property :variable:`FeatureSummary_REQUIRED_PKG_TYPES` defines which
package types are required.

If one or more package in this categories has not been found, CMake will abort
when calling :command:`feature_summary` with the
'FATAL_ON_MISSING_REQUIRED_PACKAGES' option enabled.

The default value for this global property is ``REQUIRED``.

.. variable:: FeatureSummary_DEFAULT_PKG_TYPE

The global property :variable:`FeatureSummary_DEFAULT_PKG_TYPE` defines which
package type is the default one.
When calling :command:`feature_summary`, if the user did not set the package type
explicitly, the package will be assigned to this category.

This value must be one of the types defined in the
:variable:`FeatureSummary_PKG_TYPES` global property unless the package type
is set for all the packages.

The default value for this global property is ``OPTIONAL``.

.. variable:: FeatureSummary_<TYPE>_DESCRIPTION

.. versionadded:: 3.9

The global property :variable:`FeatureSummary_<TYPE>_DESCRIPTION` can be defined
for each type to replace the type name with the specified string whenever the
package type is used in an output string.

If not set, the string "``<TYPE>`` packages" is used.

#]=======================================================================]

get_property(_fsPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_PKG_TYPES SET)
if(NOT _fsPkgTypeIsSet)
  set_property(GLOBAL PROPERTY FeatureSummary_PKG_TYPES RUNTIME OPTIONAL RECOMMENDED REQUIRED)
endif()

get_property(_fsReqPkgTypesIsSet GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES SET)
if(NOT _fsReqPkgTypesIsSet)
  set_property(GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES REQUIRED)
endif()

get_property(_fsDefaultPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE SET)
if(NOT _fsDefaultPkgTypeIsSet)
  set_property(GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE OPTIONAL)
endif()

#[=======================================================================[.rst:

Functions
^^^^^^^^^

#]=======================================================================]

function(_FS_GET_FEATURE_SUMMARY _property _var _includeQuiet)

  get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES)
  get_property(_fsDefaultPkgType GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE)

  set(_type "ANY")
  foreach(_fsPkgType ${_fsPkgTypes})
    if("${_property}" MATCHES "${_fsPkgType}_PACKAGES_(NOT_)?FOUND")
      set(_type "${_fsPkgType}")
      break()
    endif()
  endforeach()

  if("${_property}" MATCHES "PACKAGES_FOUND")
    set(_property "PACKAGES_FOUND")
  elseif("${_property}" MATCHES "PACKAGES_NOT_FOUND")
    set(_property "PACKAGES_NOT_FOUND")
  endif()

  set(_currentFeatureText "")
  get_property(_EnabledFeatures  GLOBAL PROPERTY ${_property})
  if(_EnabledFeatures)
    list(REMOVE_DUPLICATES _EnabledFeatures)
  endif(_EnabledFeatures)

  foreach(_currentFeature ${_EnabledFeatures})

    # does this package belong to the type we currently want to list ?
    get_property(_currentType  GLOBAL PROPERTY _CMAKE_${_currentFeature}_TYPE)
    if(NOT _currentType)
      list(FIND _fsPkgTypes "${_fsDefaultPkgType}" _defaultInPkgTypes)
      if("${_defaultInPkgTypes}" STREQUAL "-1")
        string(REGEX REPLACE ";([^;]+)$" " and \\1" _fsPkgTypes_msg "${_fsPkgTypes}")
        string(REPLACE ";" ", " _fsPkgTypes_msg "${_fsPkgTypes_msg}")
        message(FATAL_ERROR "Bad package property type ${_fsDefaultPkgType} used in global property FeatureSummary_DEFAULT_PKG_TYPE. "
                            "Valid types are ${_fsPkgTypes_msg}. "
                            "Either update FeatureSummary_DEFAULT_PKG_TYPE or add ${_fsDefaultPkgType} to the FeatureSummary_PKG_TYPES global property.")
      endif()
      set(_currentType ${_fsDefaultPkgType})
    endif()

    if("${_type}" STREQUAL ANY  OR  "${_type}" STREQUAL "${_currentType}")
      # check whether the current feature/package should be in the output depending on whether it was QUIET or not
      set(includeThisOne TRUE)
      set(_required FALSE)
      # skip QUIET packages, except if they are REQUIRED or INCLUDE_QUIET_PACKAGES has been set
      get_property(_fsReqPkgTypes GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES)
      foreach(_fsReqPkgType ${_fsReqPkgTypes})
        if("${_currentType}" STREQUAL "${_fsReqPkgType}")
          set(_required TRUE)
          break()
        endif()
      endforeach()
      if(NOT _required AND NOT _includeQuiet)
        get_property(_isQuiet  GLOBAL PROPERTY _CMAKE_${_currentFeature}_QUIET)
        if(_isQuiet)
          set(includeThisOne FALSE)
        endif()
      endif()
      get_property(_isTransitiveDepend
        GLOBAL PROPERTY _CMAKE_${_currentFeature}_TRANSITIVE_DEPENDENCY
      )
      if(_isTransitiveDepend)
        set(includeThisOne FALSE)
      endif()

      if(includeThisOne)

        string(APPEND _currentFeatureText "\n * ${_currentFeature}")
        get_property(_info  GLOBAL PROPERTY _CMAKE_${_currentFeature}_REQUIRED_VERSION)
        if(_info)
          string(APPEND _currentFeatureText " (required version ${_info})")
        endif()
        get_property(_info  GLOBAL PROPERTY _CMAKE_${_currentFeature}_DESCRIPTION)
        if(_info)
          string(APPEND _currentFeatureText ", ${_info}")
        endif()
        get_property(_info  GLOBAL PROPERTY _CMAKE_${_currentFeature}_URL)
        if(_info)
          string(APPEND _currentFeatureText ", <${_info}>")
        endif()

        get_property(_info  GLOBAL PROPERTY _CMAKE_${_currentFeature}_PURPOSE)
        foreach(_purpose ${_info})
          string(APPEND _currentFeatureText "\n   ${_purpose}")
        endforeach()

      endif()

    endif()

  endforeach()
  set(${_var} "${_currentFeatureText}" PARENT_SCOPE)
endfunction()

#[=======================================================================[.rst:
.. command:: feature_summary

  ::

    feature_summary( [FILENAME <file>]
                     [APPEND]
                     [VAR <variable_name>]
                     [INCLUDE_QUIET_PACKAGES]
                     [FATAL_ON_MISSING_REQUIRED_PACKAGES]
                     [DESCRIPTION "<description>" | DEFAULT_DESCRIPTION]
                     [QUIET_ON_EMPTY]
                     WHAT (ALL
                          | PACKAGES_FOUND | PACKAGES_NOT_FOUND
                          | <TYPE>_PACKAGES_FOUND | <TYPE>_PACKAGES_NOT_FOUND
                          | ENABLED_FEATURES | DISABLED_FEATURES)
                   )

  The ``feature_summary()`` macro can be used to print information about
  enabled or disabled packages or features of a project.  By default,
  only the names of the features/packages will be printed and their
  required version when one was specified.  Use ``set_package_properties()``
  to add more useful information, like e.g.  a download URL for the
  respective package or their purpose in the project.

  The ``WHAT`` option is the only mandatory option.  Here you specify what
  information will be printed:

  ``ALL``
   print everything
  ``ENABLED_FEATURES``
   the list of all features which are enabled
  ``DISABLED_FEATURES``
   the list of all features which are disabled
  ``PACKAGES_FOUND``
   the list of all packages which have been found
  ``PACKAGES_NOT_FOUND``
   the list of all packages which have not been found

  For each package type ``<TYPE>`` defined by the
  :variable:`FeatureSummary_PKG_TYPES` global property, the following
  information can also be used:

  ``<TYPE>_PACKAGES_FOUND``
   only those packages which have been found which have the type <TYPE>
  ``<TYPE>_PACKAGES_NOT_FOUND``
   only those packages which have not been found which have the type <TYPE>

  .. versionchanged:: 3.1
    With the exception of the ``ALL`` value, these values can be combined
    in order to customize the output. For example:

    .. code-block:: cmake

      feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)

  If a ``FILENAME`` is given, the information is printed into this file.  If
  ``APPEND`` is used, it is appended to this file, otherwise the file is
  overwritten if it already existed.  If the VAR option is used, the
  information is "printed" into the specified variable.  If ``FILENAME`` is
  not used, the information is printed to the terminal.  Using the
  ``DESCRIPTION`` option a description or headline can be set which will be
  printed above the actual content.  If only one type of
  package was requested, no title is printed, unless it is explicitly set using
  either ``DESCRIPTION`` to use a custom string, or ``DEFAULT_DESCRIPTION`` to
  use a default title for the requested type.
  If ``INCLUDE_QUIET_PACKAGES`` is given, packages which have been searched with
  ``find_package(... QUIET)`` will also be listed. By default they are skipped.
  If ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` is given, CMake will abort if a
  package which is marked as one of the package types listed in the
  :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global property has not been
  found.
  The default value for the :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global
  property is ``REQUIRED``.

  .. versionadded:: 3.9
    The ``DEFAULT_DESCRIPTION`` option.

  The :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global property can be
  modified to change the default package type assigned when not explicitly
  assigned by the user.

  .. versionadded:: 3.8
    If the ``QUIET_ON_EMPTY`` option is used, if only one type of package was
    requested, and no packages belonging to that category were found, then no
    output (including the ``DESCRIPTION``) is printed or added to the ``VAR``
    variable.

  Example 1, append everything to a file:

  .. code-block:: cmake

   include(FeatureSummary)
   feature_summary(WHAT ALL
                   FILENAME ${CMAKE_BINARY_DIR}/all.log APPEND)

  Example 2, print the enabled features into the variable
  enabledFeaturesText, including QUIET packages:

  .. code-block:: cmake

   include(FeatureSummary)
   feature_summary(WHAT ENABLED_FEATURES
                   INCLUDE_QUIET_PACKAGES
                   DESCRIPTION "Enabled Features:"
                   VAR enabledFeaturesText)
   message(STATUS "${enabledFeaturesText}")

  Example 3, change default package types and print only the categories that
  are not empty:

  .. code-block:: cmake

   include(FeatureSummary)
   set_property(GLOBAL APPEND PROPERTY FeatureSummary_PKG_TYPES BUILD)
   find_package(FOO)
   set_package_properties(FOO PROPERTIES TYPE BUILD)
   feature_summary(WHAT BUILD_PACKAGES_FOUND
                   Description "Build tools found:"
                   QUIET_ON_EMPTY)
   feature_summary(WHAT BUILD_PACKAGES_NOT_FOUND
                   Description "Build tools not found:"
                   QUIET_ON_EMPTY)

#]=======================================================================]

function(FEATURE_SUMMARY)
# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)
  set(options APPEND
              INCLUDE_QUIET_PACKAGES
              FATAL_ON_MISSING_REQUIRED_PACKAGES
              QUIET_ON_EMPTY
              DEFAULT_DESCRIPTION)
  set(oneValueArgs FILENAME
                   VAR
                   DESCRIPTION)
  set(multiValueArgs WHAT)

  CMAKE_PARSE_ARGUMENTS(_FS "${options}" "${oneValueArgs}" "${multiValueArgs}"  ${_FIRST_ARG} ${ARGN})

  if(_FS_UNPARSED_ARGUMENTS)
    message(FATAL_ERROR "Unknown keywords given to FEATURE_SUMMARY(): \"${_FS_UNPARSED_ARGUMENTS}\"")
  endif()

  if(NOT _FS_WHAT)
    message(FATAL_ERROR "The call to FEATURE_SUMMARY() doesn't set the required WHAT argument.")
  endif()

  if(_FS_DEFAULT_DESCRIPTION AND DEFINED _FS_DESCRIPTION)
    message(WARNING "DEFAULT_DESCRIPTION option discarded since DESCRIPTION is set.")
    set(_FS_DEFAULT_DESCRIPTION 0)
  endif()

  set(validWhatParts "ENABLED_FEATURES"
                     "DISABLED_FEATURES"
                     "PACKAGES_FOUND"
                     "PACKAGES_NOT_FOUND")

  get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES)
  get_property(_fsReqPkgTypes GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES)
  foreach(_fsPkgType ${_fsPkgTypes})
    list(APPEND validWhatParts "${_fsPkgType}_PACKAGES_FOUND"
                               "${_fsPkgType}_PACKAGES_NOT_FOUND")
  endforeach()

  set(title_ENABLED_FEATURES               "The following features have been enabled:")
  set(title_DISABLED_FEATURES              "The following features have been disabled:")
  set(title_PACKAGES_FOUND                 "The following packages have been found:")
  set(title_PACKAGES_NOT_FOUND             "The following packages have not been found:")
  foreach(_fsPkgType ${_fsPkgTypes})
    set(_fsPkgTypeDescription "${_fsPkgType} packages")
    get_property(_fsPkgTypeDescriptionIsSet GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION SET)
    if(_fsPkgTypeDescriptionIsSet)
      get_property(_fsPkgTypeDescription GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION )
    endif()
    set(title_${_fsPkgType}_PACKAGES_FOUND     "The following ${_fsPkgTypeDescription} have been found:")
    set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgTypeDescription} have not been found:")
  endforeach()

  list(FIND validWhatParts "${_FS_WHAT}" indexInList)
  if(NOT "${indexInList}" STREQUAL "-1")
    _FS_GET_FEATURE_SUMMARY( ${_FS_WHAT} _featureSummary ${_FS_INCLUDE_QUIET_PACKAGES} )
    if(_featureSummary OR NOT _FS_QUIET_ON_EMPTY)
      if(_FS_DEFAULT_DESCRIPTION)
        set(_fullText "${title_${_FS_WHAT}}\n${_featureSummary}\n")
      else()
        set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n")
      endif()
    endif()

    if(_featureSummary)
      foreach(_fsReqPkgType ${_fsReqPkgTypes})
        if("${_FS_WHAT}" STREQUAL "${_fsReqPkgType}_PACKAGES_NOT_FOUND")
          set(requiredPackagesNotFound TRUE)
          break()
        endif()
      endforeach()
    endif()

  else()
    if("${_FS_WHAT}" STREQUAL "ALL")

      set(allWhatParts "ENABLED_FEATURES")
      foreach(_fsPkgType ${_fsPkgTypes})
        list(APPEND allWhatParts "${_fsPkgType}_PACKAGES_FOUND")
      endforeach()
      list(APPEND allWhatParts "DISABLED_FEATURES")
      foreach(_fsPkgType ${_fsPkgTypes})
        list(APPEND allWhatParts "${_fsPkgType}_PACKAGES_NOT_FOUND")
      endforeach()
    else()
      set(allWhatParts)
      foreach(part ${_FS_WHAT})
        list(FIND validWhatParts "${part}" indexInList)
        if(NOT "${indexInList}" STREQUAL "-1")
          list(APPEND allWhatParts "${part}")
        else()
          if("${part}" STREQUAL "ALL")
            message(FATAL_ERROR "The WHAT argument of FEATURE_SUMMARY() contains ALL, which cannot be combined with other values.")
          else()
            message(FATAL_ERROR "The WHAT argument of FEATURE_SUMMARY() contains ${part}, which is not a valid value.")
          endif()
        endif()
      endforeach()
    endif()

    set(_fullText "${_FS_DESCRIPTION}")
    foreach(part ${allWhatParts})
      set(_tmp)
      _FS_GET_FEATURE_SUMMARY( ${part} _tmp ${_FS_INCLUDE_QUIET_PACKAGES})
      if(_tmp)
        if(_fullText)
          string(APPEND _fullText "\n-- ")
        endif()
        string(APPEND _fullText "${title_${part}}\n${_tmp}\n")
        foreach(_fsReqPkgType ${_fsReqPkgTypes})
          if("${part}" STREQUAL "${_fsReqPkgType}_PACKAGES_NOT_FOUND")
            set(requiredPackagesNotFound TRUE)
            break()
          endif()
        endforeach()
      endif()
    endforeach()
  endif()

  if(_fullText OR NOT _FS_QUIET_ON_EMPTY)
    if(_FS_FILENAME)
      if(_FS_APPEND)
        file(APPEND "${_FS_FILENAME}" "${_fullText}")
      else()
        file(WRITE  "${_FS_FILENAME}" "${_fullText}")
      endif()

    else()
      if(NOT _FS_VAR)
        message(STATUS "${_fullText}")
      endif()
    endif()

    if(_FS_VAR)
      set(${_FS_VAR} "${_fullText}" PARENT_SCOPE)
    endif()
  endif()

  if(requiredPackagesNotFound  AND  _FS_FATAL_ON_MISSING_REQUIRED_PACKAGES)
    message(FATAL_ERROR "feature_summary() Error: REQUIRED package(s) are missing, aborting CMake run.")
  endif()

endfunction()

#[=======================================================================[.rst:
.. command:: set_package_properties

  ::

    set_package_properties(<name> PROPERTIES
                           [ URL <url> ]
                           [ DESCRIPTION <description> ]
                           [ TYPE (RUNTIME|OPTIONAL|RECOMMENDED|REQUIRED) ]
                           [ PURPOSE <purpose> ]
                          )

  Use this macro to set up information about the named package, which
  can then be displayed via FEATURE_SUMMARY().  This can be done either
  directly in the Find-module or in the project which uses the module
  after the find_package() call.  The features for which information can
  be set are added automatically by the find_package() command.

  ``URL <url>``
    This should be the homepage of the package, or something similar.
    Ideally this is set already directly in the Find-module.

  ``DESCRIPTION <description>``
    A short description what that package is, at most one sentence.
    Ideally this is set already directly in the Find-module.

  ``TYPE <type>``
    What type of dependency has the using project on that package.
    Default is ``OPTIONAL``.  In this case it is a package which can be used
    by the project when available at buildtime, but it also work without.
    ``RECOMMENDED`` is similar to ``OPTIONAL``, i.e.  the project will build if
    the package is not present, but the functionality of the resulting
    binaries will be severely limited.  If a ``REQUIRED`` package is not
    available at buildtime, the project may not even build.  This can be
    combined with the ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` argument for
    ``feature_summary()``.  Last, a ``RUNTIME`` package is a package which is
    actually not used at all during the build, but which is required for
    actually running the resulting binaries.  So if such a package is
    missing, the project can still be built, but it may not work later on.
    If ``set_package_properties()`` is called multiple times for the same
    package with different TYPEs, the ``TYPE`` is only changed to higher
    TYPEs (``RUNTIME < OPTIONAL < RECOMMENDED < REQUIRED``), lower TYPEs are
    ignored.  The ``TYPE`` property is project-specific, so it cannot be set
    by the Find-module, but must be set in the project.
    Type accepted can be changed by setting the
    :variable:`FeatureSummary_PKG_TYPES` global property.

  ``PURPOSE <purpose>``
    This describes which features this package enables in the
    project, i.e.  it tells the user what functionality he gets in the
    resulting binaries.  If set_package_properties() is called multiple
    times for a package, all PURPOSE properties are appended to a list of
    purposes of the package in the project.  As the TYPE property, also
    the PURPOSE property is project-specific, so it cannot be set by the
    Find-module, but must be set in the project.

  Example for setting the info for a package:

  .. code-block:: cmake

    find_package(LibXml2)
    set_package_properties(LibXml2 PROPERTIES
                           DESCRIPTION "A XML processing library."
                           URL "http://xmlsoft.org/")
    # or
    set_package_properties(LibXml2 PROPERTIES
                           TYPE RECOMMENDED
                           PURPOSE "Enables HTML-import in MyWordProcessor")
    # or
    set_package_properties(LibXml2 PROPERTIES
                           TYPE OPTIONAL
                           PURPOSE "Enables odt-export in MyWordProcessor")

    find_package(DBUS)
    set_package_properties(DBUS PROPERTIES
      TYPE RUNTIME
      PURPOSE "Necessary to disable the screensaver during a presentation")
#]=======================================================================]
function(SET_PACKAGE_PROPERTIES _name _props)
  if(NOT "${_props}" STREQUAL "PROPERTIES")
    message(FATAL_ERROR "PROPERTIES keyword is missing in SET_PACKAGE_PROPERTIES() call.")
  endif()

  set(options ) # none
  set(oneValueArgs DESCRIPTION URL TYPE PURPOSE )
  set(multiValueArgs ) # none

  CMAKE_PARSE_ARGUMENTS(_SPP "${options}" "${oneValueArgs}" "${multiValueArgs}"  ${ARGN})

  if(_SPP_UNPARSED_ARGUMENTS)
    message(FATAL_ERROR "Unknown keywords given to SET_PACKAGE_PROPERTIES(): \"${_SPP_UNPARSED_ARGUMENTS}\"")
  endif()

  if(_SPP_DESCRIPTION)
    get_property(_info  GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION)
    if(_info AND NOT "${_info}" STREQUAL "${_SPP_DESCRIPTION}")
      message(STATUS "Warning: Property DESCRIPTION for package ${_name} already set to \"${_info}\", overriding it with \"${_SPP_DESCRIPTION}\"")
    endif()

    set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_SPP_DESCRIPTION}" )
  endif()

  if(_SPP_URL)
    get_property(_info  GLOBAL PROPERTY _CMAKE_${_name}_URL)
    if(_info AND NOT "${_info}" STREQUAL "${_SPP_URL}")
      message(STATUS "Warning: Property URL already set to \"${_info}\", overriding it with \"${_SPP_URL}\"")
    endif()

    set_property(GLOBAL PROPERTY _CMAKE_${_name}_URL "${_SPP_URL}" )
  endif()

  # handle the PURPOSE: use APPEND, since there can be multiple purposes for one package inside a project
  if(_SPP_PURPOSE)
    set_property(GLOBAL APPEND PROPERTY _CMAKE_${_name}_PURPOSE "${_SPP_PURPOSE}" )
  endif()

  get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES)
  get_property(_fsDefaultPkgType GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE)

  # handle the TYPE
  if(DEFINED _SPP_TYPE)
    # Supported types are listed in FeatureSummary_PKG_TYPES according to their priority
    get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES)
    list(FIND _fsPkgTypes ${_SPP_TYPE} _typeIndexInList)
    if("${_typeIndexInList}" STREQUAL "-1" )
      string(REGEX REPLACE ";([^;]+)$" " and \\1" _fsPkgTypes_msg "${_fsPkgTypes}")
      string(REPLACE ";" ", " _fsPkgTypes_msg "${_fsPkgTypes_msg}")
      message(FATAL_ERROR "Bad package property type ${_SPP_TYPE} used in SET_PACKAGE_PROPERTIES(). "
                          "Valid types are ${_fsPkgTypes_msg}." )
    endif()

    get_property(_previousType  GLOBAL PROPERTY _CMAKE_${_name}_TYPE)
    list(FIND _fsPkgTypes "${_previousType}" _prevTypeIndexInList)

    # make sure a previously set TYPE is not overridden with a lower new TYPE:
    if("${_typeIndexInList}" GREATER "${_prevTypeIndexInList}")
      set_property(GLOBAL PROPERTY _CMAKE_${_name}_TYPE "${_SPP_TYPE}" )
    endif()
  endif()

endfunction()

#[=======================================================================[.rst:
.. command:: add_feature_info

  ::

    add_feature_info(<name> <enabled> <description>)

  Use this macro to add information about a feature with the given ``<name>``.
  ``<enabled>`` contains whether this feature is enabled or not. It can be a
  variable or a list of conditions.
  ``<description>`` is a text describing the feature.  The information can
  be displayed using ``feature_summary()`` for ``ENABLED_FEATURES`` and
  ``DISABLED_FEATURES`` respectively.

  .. versionchanged:: 3.8
    ``<enabled>`` can be a list of conditions.

  Example for setting the info for a feature:

  .. code-block:: cmake

     option(WITH_FOO "Help for foo" ON)
     add_feature_info(Foo WITH_FOO "The Foo feature provides very cool stuff.")
#]=======================================================================]
function(ADD_FEATURE_INFO _name _depends _desc)
  set(_enabled 1)
  foreach(_d ${_depends})
    string(REGEX REPLACE " +" ";" _d "${_d}")
    if(${_d})
    else()
      set(_enabled 0)
      break()
    endif()
  endforeach()
  if (${_enabled})
    set_property(GLOBAL APPEND PROPERTY ENABLED_FEATURES "${_name}")
  else ()
    set_property(GLOBAL APPEND PROPERTY DISABLED_FEATURES "${_name}")
  endif ()

  set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_desc}" )
endfunction()

# The stuff below is only kept for compatibility

#[=======================================================================[.rst:
Legacy Macros
^^^^^^^^^^^^^

The following macros are provided for compatibility with previous
CMake versions:

.. command:: set_package_info

  ::

    set_package_info(<name> <description> [ <url> [<purpose>] ])

  Use this macro to set up information about the named package, which
  can then be displayed via ``feature_summary()``.  This can be done either
  directly in the Find-module or in the project which uses the module
  after the :command:`find_package` call.  The features for which information
  can be set are added automatically by the ``find_package()`` command.
#]=======================================================================]
function(SET_PACKAGE_INFO _name _desc)
  message(DEPRECATION "SET_PACKAGE_INFO is deprecated. Use SET_PACKAGE_PROPERTIES instead.")
  unset(_url)
  unset(_purpose)
  if(ARGC GREATER 2)
    set(_url "${ARGV2}")
  endif()
  if(ARGC GREATER 3)
    set(_purpose "${ARGV3}")
  endif()
  set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_desc}" )
  if(NOT _url STREQUAL "")
    set_property(GLOBAL PROPERTY _CMAKE_${_name}_URL "${_url}" )
  endif()
  if(NOT _purpose STREQUAL "")
    set_property(GLOBAL APPEND PROPERTY _CMAKE_${_name}_PURPOSE "${_purpose}" )
  endif()
endfunction()

#[=======================================================================[.rst:
.. command:: set_feature_info

  ::

    set_feature_info(<name> <description> [<url>])

  Does the same as::

    set_package_info(<name> <description> <url>)
#]=======================================================================]
function(SET_FEATURE_INFO)
  message(DEPRECATION "SET_FEATURE_INFO is deprecated. Use ADD_FEATURE_INFO instead.")
  SET_PACKAGE_INFO(${ARGN})
endfunction()

#[=======================================================================[.rst:
.. command:: print_enabled_features

  ::

    print_enabled_features()

  Does the same as

  .. code-block:: cmake

    feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
#]=======================================================================]
function(PRINT_ENABLED_FEATURES)
  message(DEPRECATION "PRINT_ENABLED_FEATURES is deprecated. Use
    feature_summary(WHAT ENABLED_FEATURES DESCRIPTION \"Enabled features:\")")
  FEATURE_SUMMARY(WHAT ENABLED_FEATURES  DESCRIPTION "Enabled features:")
endfunction()

#[=======================================================================[.rst:
.. command:: print_disabled_features

  ::

    print_disabled_features()

  Does the same as

  .. code-block:: cmake

    feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
#]=======================================================================]
function(PRINT_DISABLED_FEATURES)
  message(DEPRECATION "PRINT_DISABLED_FEATURES is deprecated. Use
    feature_summary(WHAT DISABLED_FEATURES DESCRIPTION \"Disabled features:\")")
  FEATURE_SUMMARY(WHAT DISABLED_FEATURES  DESCRIPTION "Disabled features:")
endfunction()