function(get_relative_link OUTPUT PATH)
  if (PATH MATCHES "^[$]<[$]<CONFIG:DEBUG>:")
    set(${OUTPUT} "" PARENT_SCOPE)
    return()
  endif()
  string(REGEX REPLACE "^[$]<[$]<NOT:[$]<CONFIG:DEBUG>>:(.*)>$" "\\1" PATH "${PATH}")

  get_filename_component(NAME "${PATH}" NAME_WE)
  if (IS_ABSOLUTE ${PATH})
    get_filename_component(DIRECTORY_NAME "${PATH}" DIRECTORY)
    get_filename_component(FULL_NAME "${PATH}" NAME)
    string(REGEX REPLACE "^lib([^.]+).*$" "\\1" LIB_NAME "${FULL_NAME}")
    # If the regex didn't match (no lib prefix), fall back to name without extension
    if ("${LIB_NAME}" STREQUAL "${FULL_NAME}")
      set(LIB_NAME "${NAME}")
    endif()
    set(${OUTPUT} "-L\"${DIRECTORY_NAME}\" -l${LIB_NAME}" PARENT_SCOPE)
    return()
  endif()

  if (NOT WIN32 AND NAME MATCHES "^lib")
    string(REGEX REPLACE "^lib" "-l" LINK "${NAME}")
  elseif (NAME MATCHES "^-")
    set(LINK "${NAME}")
  else()
    string(CONCAT LINK "-l" "${NAME}")
  endif()
  set(${OUTPUT} "${LINK}" PARENT_SCOPE)
endfunction()

function(generate_pkgconfig TARGET DESCRIPTION)
  # message("Generating pkg-config for ${TARGET}")
  get_filename_component(PREFIX "${CMAKE_INSTALL_PREFIX}" REALPATH)

  get_target_property(LIBRARY_TYPE "${TARGET}" TYPE)
  if ("${LIBRARY_TYPE}" STREQUAL "INTERFACE_LIBRARY")
    get_target_property(LIST "${TARGET}" INTERFACE_LINK_LIBRARIES)
  else()
    get_target_property(LIST "${TARGET}" LINK_LIBRARIES)
  endif()

  if ("${LIST}" STREQUAL "LIST-NOTFOUND")
    set(LIST "")
  endif()

  set(INTERFACE_LIBS "")
  if ("${LIBRARY_TYPE}" STREQUAL "INTERFACE_LIBRARY")
    set(PROPAGATED "")
    foreach (DEP ${LIST})
      if (TARGET "${DEP}")
        get_target_property(DEP_TYPE "${DEP}" TYPE)
        if ("${DEP_TYPE}" STREQUAL "STATIC_LIBRARY" OR "${DEP_TYPE}" STREQUAL "SHARED_LIBRARY")
          list(APPEND INTERFACE_LIBS "${DEP}")
          get_target_property(DEP_LIBS "${DEP}" LINK_LIBRARIES)
          if (NOT "${DEP_LIBS}" STREQUAL "DEP_LIBS-NOTFOUND")
            list(APPEND PROPAGATED ${DEP_LIBS})
          endif()
        else()
          list(APPEND PROPAGATED "${DEP}")
        endif()
      else()
        list(APPEND PROPAGATED "${DEP}")
      endif()
    endforeach()
    if (PROPAGATED)
      list(REMOVE_DUPLICATES PROPAGATED)
    endif()
    set(LIST "${PROPAGATED}")
  endif()

  set(REQS "")
  set(LIBS "")
  foreach (LIB ${LIST})
    if (TARGET "${LIB}")
      if ("${LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY")
        get_target_property(LIB_TYPE "${LIB}" TYPE)
        if ("${LIB_TYPE}" STREQUAL "STATIC_LIBRARY")
          continue()
        endif()
      endif()
      set(HAS_REQS 1)
      list(APPEND REQS "${LIB}")
    else()
      set(HAS_LIBS 1)
      get_relative_link(LINK "${LIB}")
      if (NOT "${LINK}" STREQUAL "")
        list(APPEND LIBS "${LINK}")
      endif()
    endif()
  endforeach()

  if (HAS_REQS)
    set(REQUIRES "")
    foreach (REQ ${REQS})
      set(REQUIRES "${REQUIRES} ${REQ}")
    endforeach()
    set(REQUIRES "Requires.private:${REQUIRES}\n")
  endif()
  if (HAS_LIBS)
    set(LIBRARIES "")
    list(REVERSE LIBS)
    list(REMOVE_DUPLICATES LIBS)
    foreach (LIB ${LIBS})
      set(LIBRARIES " ${LIB}${LIBRARIES}")
    endforeach()
    set(LIBRARIES "Libs.private:${LIBRARIES}\n")
  endif()

  if (IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
    set(PKGCONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
  else()
    set(PKGCONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
  endif()

  if (IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
    set(PKGCONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
  else()
    set(PKGCONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
  endif()

  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig")

  get_target_property(TARGET_OUTPUT_NAME "${TARGET}" OUTPUT_NAME)
  if ("${TARGET_OUTPUT_NAME}" STREQUAL "TARGET_OUTPUT_NAME-NOTFOUND")
    set(TARGET_OUTPUT_NAME "${TARGET}")
  endif()

  if ("${LIBRARY_TYPE}" STREQUAL "INTERFACE_LIBRARY")
    set(LIBS_LINE "")
    foreach (ILIB ${INTERFACE_LIBS})
      get_target_property(ILIB_OUTPUT_NAME "${ILIB}" OUTPUT_NAME)
      if ("${ILIB_OUTPUT_NAME}" STREQUAL "ILIB_OUTPUT_NAME-NOTFOUND")
        set(ILIB_OUTPUT_NAME "${ILIB}")
      endif()
      set(LIBS_LINE "${LIBS_LINE} -l${ILIB_OUTPUT_NAME}")
    endforeach()
    set(LIBS_LINE "Libs: -L\"${PKGCONFIG_LIBDIR}\"${LIBS_LINE}")
  else()
    set(LIBS_LINE "Libs: -L\"${PKGCONFIG_LIBDIR}\" -l${TARGET_OUTPUT_NAME}")
  endif()

  get_target_property(_td_iface_defs "${TARGET}" INTERFACE_COMPILE_DEFINITIONS)
  set(CFLAGS_DEFS "")
  if (NOT "${_td_iface_defs}" STREQUAL "_td_iface_defs-NOTFOUND")
    foreach(_def ${_td_iface_defs})
      string(APPEND CFLAGS_DEFS " -D${_def}")
    endforeach()
    unset(_def)
  endif()
  unset(_td_iface_defs)

  file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${TARGET}.pc" CONTENT
"prefix=${PREFIX}

Name: ${TARGET}
Description: ${DESCRIPTION}
Version: ${PROJECT_VERSION}

CFlags: -I\"${PKGCONFIG_INCLUDEDIR}\"${CFLAGS_DEFS}
${LIBS_LINE}
${REQUIRES}${LIBRARIES}")

  if ("${LIBRARY_TYPE}" STREQUAL "STATIC_LIBRARY" OR "${LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY" OR
      "${LIBRARY_TYPE}" STREQUAL "INTERFACE_LIBRARY")
    install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${TARGET}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
  else()
    message(FATAL_ERROR "Don't know how to handle ${TARGET} of type ${LIBRARY_TYPE}")
  endif()
endfunction()
