110 lines
4.1 KiB
CMake
110 lines
4.1 KiB
CMake
# CMake Module to generate Source Link JSON for the MSVC compiler
|
|
#
|
|
# Microsoft defines Source Link as the following:
|
|
#
|
|
# > Source Link is a developer productivity feature that allows unique
|
|
# > information about an assembly's original source code to be embedded in its
|
|
# > PDB during compilation.
|
|
# https://github.com/dotnet/designs/blob/master/accepted/diagnostics/source-link.md
|
|
#
|
|
# Specifically, this script will embedded information into the PDB of where to
|
|
# download the source code from. This will allow developers to use the PDB without
|
|
# the source located on disk.
|
|
#
|
|
# This script currently only works with GitHub but could be extended to support
|
|
# other source control servers. Any server which hosts their code as raw source
|
|
# over HTTP should work.
|
|
#
|
|
include(GitCommands)
|
|
|
|
# Warn if this is included and the compilier doesn't support source link
|
|
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
|
|
if ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER_EQUAL "19.20")
|
|
# Good to go!
|
|
elseif("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER_EQUAL "19.14")
|
|
message(STATUS "SourceLink enabled but case insensative")
|
|
else()
|
|
message(WARNING "SourceLink will not work on version of MSVC less than 19.14")
|
|
endif()
|
|
else()
|
|
message(WARNING "SourceLink will not work on the ${CMAKE_C_COMPILER_ID} compiler")
|
|
endif()
|
|
|
|
# REPO_ROOT is the path to the repository where code it stored.
|
|
#
|
|
# SOURCE_LINK_JSON_PATH is the file to output the json
|
|
function(source_link REPO_ROOT SOURCE_LINK_JSON_PATH)
|
|
if (NOT (IS_DIRECTORY ${REPO_ROOT}))
|
|
message(FATAL_ERROR "\"${REPO_ROOT}\" is not a directory")
|
|
endif()
|
|
|
|
get_git_remote_url(${REPO_ROOT} GIT_REMOTE)
|
|
get_git_current_hash(${REPO_ROOT} GIT_CURRENT_HASH)
|
|
|
|
build_source_link_rule(${REPO_ROOT} ${GIT_REMOTE} ${GIT_CURRENT_HASH} ROOT_RULE)
|
|
|
|
set(SOURCE_LINK_RULES)
|
|
list(APPEND SOURCE_LINK_RULES ${ROOT_RULE})
|
|
|
|
# Also build rules for submodules
|
|
run_git_submodule_foreach("echo $displaypath,$sha1,`git config --get remote.origin.url`" ${REPO_ROOT} SUBMODULE_INFO)
|
|
|
|
if (NOT ("${SUBMODULE_INFO}" STREQUAL ""))
|
|
# Turn output of new lines into a CMake list
|
|
string(REPLACE "\r\n" ";" SUBMODULE_INFO ${SUBMODULE_INFO})
|
|
string(REPLACE "\n" ";" SUBMODULE_INFO ${SUBMODULE_INFO})
|
|
|
|
foreach(ITEM ${SUBMODULE_INFO})
|
|
# Turn each line into a list of path;hash;url
|
|
string(REPLACE "," ";" SUBMODULE ${ITEM})
|
|
list(GET SUBMODULE 0 LOCAL_PATH)
|
|
list(GET SUBMODULE 1 CURRENT_HASH)
|
|
list(GET SUBMODULE 2 REMOTE)
|
|
string(CONCAT LOCAL_PATH "${REPO_ROOT}/" ${LOCAL_PATH})
|
|
build_source_link_rule(${LOCAL_PATH} ${REMOTE} ${CURRENT_HASH} RULE)
|
|
list(APPEND SOURCE_LINK_RULES ${RULE})
|
|
endforeach()
|
|
endif()
|
|
|
|
set(OUTPUT)
|
|
string(APPEND OUTPUT "{\n")
|
|
string(APPEND OUTPUT "\"documents\": {\n")
|
|
string(JOIN ",\n" EXPANDED_RULES ${SOURCE_LINK_RULES})
|
|
string(APPEND OUTPUT "${EXPANDED_RULES}\n")
|
|
string(APPEND OUTPUT "}\n")
|
|
string(APPEND OUTPUT "}\n")
|
|
|
|
file(WRITE ${SOURCE_LINK_JSON_PATH} ${OUTPUT})
|
|
|
|
endfunction()
|
|
|
|
function(build_source_link_rule LOCAL_PATH GIT_REMOTE GIT_CURRENT_HASH OUTPUT)
|
|
# Verify local path exists
|
|
if (NOT (IS_DIRECTORY ${LOCAL_PATH}))
|
|
message(FATAL_ERROR "${LOCAL_PATH} is not a directory")
|
|
endif()
|
|
|
|
# Change local path to native path
|
|
file(TO_NATIVE_PATH "${LOCAL_PATH}/*" LOCAL_PATH)
|
|
# Escape any backslashes for JSON
|
|
string(REPLACE "\\" "\\\\" LOCAL_PATH ${LOCAL_PATH})
|
|
|
|
# Verify this is a GitHub URL
|
|
# In the future we could support other source servers but currently they
|
|
# are not supported
|
|
if (NOT ("${GIT_REMOTE}" MATCHES "https://github\\.com"))
|
|
message(STATUS "Unable to sourcelink remote: \"${GIT_REMOTE}\". Unknown host")
|
|
return()
|
|
endif()
|
|
|
|
string(REPLACE ".git" "" RAW_GIT_URL ${GIT_REMOTE})
|
|
string(REPLACE "github.com" "raw.githubusercontent.com" RAW_GIT_URL ${RAW_GIT_URL})
|
|
string(CONCAT RAW_GIT_URL ${RAW_GIT_URL} "/${GIT_CURRENT_HASH}/*")
|
|
|
|
set(${OUTPUT} "\"${LOCAL_PATH}\" : \"${RAW_GIT_URL}\"" PARENT_SCOPE)
|
|
|
|
endfunction(build_source_link_rule)
|
|
|
|
|
|
|