1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[CMake] Unify scripts for generating VCS headers

Previously, there were two different scripts for generating VCS headers:
one used by LLVM and one used by Clang and lldb. They were both similar,
but different. They were both broken in their own ways, for example the
one used by Clang didn't properly handle monorepo resulting in an
incorrect version information reported by Clang.

This change unifies two the scripts by introducing a new script that's
used from both LLVM, Clang and lldb, ensures that the new script
supports both monorepo and standalone SVN and Git setups, and removes
the old scripts.

Differential Revision: https://reviews.llvm.org/D57063

llvm-svn: 353268
This commit is contained in:
Petr Hosek 2019-02-06 03:51:00 +00:00
parent 135121a399
commit ec05af2652
7 changed files with 183 additions and 326 deletions

View File

@ -239,7 +239,7 @@ endif()
include(VersionFromVCS)
option(LLVM_APPEND_VC_REV
"Embed the version control system revision id in LLVM" ON)
"Embed the version control system revision in LLVM" ON)
set(PACKAGE_NAME LLVM)
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
@ -791,13 +791,12 @@ set(LLVM_SRPM_USER_BINARY_SPECFILE ${CMAKE_CURRENT_SOURCE_DIR}/llvm.spec.in
set(LLVM_SRPM_BINARY_SPECFILE ${CMAKE_CURRENT_BINARY_DIR}/llvm.spec)
set(LLVM_SRPM_DIR "${CMAKE_CURRENT_BINARY_DIR}/srpm")
# SVN_REVISION and GIT_COMMIT get set by the call to add_version_info_from_vcs.
# DUMMY_VAR contains a version string which we don't care about.
add_version_info_from_vcs(DUMMY_VAR)
if ( SVN_REVISION )
set(LLVM_RPM_SPEC_REVISION "r${SVN_REVISION}")
elseif ( GIT_COMMIT )
set (LLVM_RPM_SPEC_REVISION "g${GIT_COMMIT}")
get_source_info(${CMAKE_CURRENT_SOURCE_DIR} revision repository)
string(LENGTH "${revision}" revision_length)
if(revision MATCHES "^[0-9]+$" AND revision_length LESS 40)
set(LLVM_RPM_SPEC_REVISION "r${revision}")
else()
set(LLVM_RPM_SPEC_REVISION "${revision}")
endif()
configure_file(

View File

@ -1717,35 +1717,35 @@ function(setup_dependency_debugging name)
set_target_properties(${name} PROPERTIES RULE_LAUNCH_COMPILE ${sandbox_command})
endfunction()
# Figure out if we can track VC revisions.
function(find_first_existing_file out_var)
foreach(file ${ARGN})
function(find_first_existing_vc_file path out_var)
if(EXISTS "${path}/.svn")
set(svn_files
"${path}/.svn/wc.db" # SVN 1.7
"${path}/.svn/entries" # SVN 1.6
)
foreach(file IN LISTS svn_files)
if(EXISTS "${file}")
set(${out_var} "${file}" PARENT_SCOPE)
return()
endif()
endforeach()
endfunction()
macro(find_first_existing_vc_file out_var path)
find_program(git_executable NAMES git git.exe git.cmd)
# Run from a subdirectory to force git to print an absolute path.
execute_process(COMMAND ${git_executable} rev-parse --git-dir
WORKING_DIRECTORY ${path}/cmake
else()
find_package(Git)
if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --git-dir
WORKING_DIRECTORY ${path}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_dir
OUTPUT_VARIABLE git_output
ERROR_QUIET)
if(git_result EQUAL 0)
string(STRIP "${git_dir}" git_dir)
set(${out_var} "${git_dir}/logs/HEAD")
# some branchless cases (e.g. 'repo') may not yet have .git/logs/HEAD
string(STRIP "${git_output}" git_output)
get_filename_component(git_dir ${git_output} ABSOLUTE BASE_DIR ${path})
# Some branchless cases (e.g. 'repo') may not yet have .git/logs/HEAD
if (NOT EXISTS "${git_dir}/logs/HEAD")
file(WRITE "${git_dir}/logs/HEAD" "")
endif()
else()
find_first_existing_file(${out_var}
"${path}/.svn/wc.db" # SVN 1.7
"${path}/.svn/entries" # SVN 1.6
)
set(${out_var} "${git_dir}/logs/HEAD" PARENT_SCOPE)
endif()
endmacro()
endif()
endif()
endfunction()

View File

@ -1,39 +0,0 @@
# CMake project that writes Subversion revision information to a header.
#
# Input variables:
# SRC - Source directory
# HEADER_FILE - The header file to write
#
# The output header will contain macros FIRST_REPOSITORY and FIRST_REVISION,
# and SECOND_REPOSITORY and SECOND_REVISION if requested, where "FIRST" and
# "SECOND" are substituted with the names specified in the input variables.
# Chop off cmake/modules/GetSVN.cmake
get_filename_component(LLVM_DIR "${CMAKE_SCRIPT_MODE_FILE}" PATH)
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${LLVM_DIR}/cmake/modules")
include(VersionFromVCS)
# Handle strange terminals
set(ENV{TERM} "dumb")
function(append_info name path)
add_version_info_from_vcs(REVISION ${path})
string(STRIP "${REVISION}" REVISION)
file(APPEND "${HEADER_FILE}.txt"
"#define ${name} \"${REVISION}\"\n")
endfunction()
append_info(${NAME} "${SOURCE_DIR}")
# Copy the file only if it has changed.
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${HEADER_FILE}.txt" "${HEADER_FILE}")
file(REMOVE "${HEADER_FILE}.txt")

View File

@ -0,0 +1,53 @@
# CMake script that writes version control information to a header.
#
# Input variables:
# NAMES - A list of names for each of the source directories.
# <NAME>_SOURCE_DIR - A path to source directory for each name in NAMES.
# HEADER_FILE - The header file to write
#
# The output header will contain macros <NAME>_REPOSITORY and <NAME>_REVISION,
# where "<NAME>" is substituted with the names specified in the input variables,
# for each of the <NAME>_SOURCE_DIR given.
get_filename_component(LLVM_DIR "${CMAKE_SCRIPT_MODE_FILE}" PATH)
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
list(APPEND CMAKE_MODULE_PATH "${LLVM_DIR}/cmake/modules")
include(VersionFromVCS)
# Handle strange terminals
set(ENV{TERM} "dumb")
function(append_info name path)
if(path)
get_source_info("${path}" revision repository)
endif()
if(revision)
file(APPEND "${HEADER_FILE}.tmp"
"#define ${name}_REVISION \"${revision}\"\n")
else()
file(APPEND "${HEADER_FILE}.tmp"
"#undef ${name}_REVISION\n")
endif()
if(repository)
file(APPEND "${HEADER_FILE}.tmp"
"#define ${name}_REPOSITORY \"${repository}\"\n")
else()
file(APPEND "${HEADER_FILE}.tmp"
"#undef ${name}_REPOSITORY\n")
endif()
endfunction()
foreach(name IN LISTS NAMES)
if(NOT DEFINED ${name}_SOURCE_DIR)
message(FATAL_ERROR "${name}_SOURCE_DIR is not defined")
endif()
append_info(${name} "${${name}_SOURCE_DIR}")
endforeach()
# Copy the file only if it has changed.
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${HEADER_FILE}.tmp" "${HEADER_FILE}")
file(REMOVE "${HEADER_FILE}.tmp")

View File

@ -1,141 +0,0 @@
# CMake project that writes Subversion revision information to a header.
#
# Input variables:
# SOURCE_DIRS - A list of source directories.
# NAMES - A list of macro prefixes for each of the source directories.
# HEADER_FILE - The header file to write
#
# The output header will contain macros <NAME>_REPOSITORY and <NAME>_REVISION,
# where "<NAME>" and is substituted with the names specified in the input
# variables, for each of the SOURCE_DIRS given.
# Chop off cmake/modules/GetSVN.cmake
get_filename_component(LLVM_DIR "${CMAKE_SCRIPT_MODE_FILE}" PATH)
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
# Handle strange terminals
set(ENV{TERM} "dumb")
macro(get_source_info_svn path revision repository)
# If svn is a bat file, find_program(Subversion) doesn't find it.
# Explicitly search for that here; Subversion_SVN_EXECUTABLE will override
# the find_program call in FindSubversion.cmake.
find_program(Subversion_SVN_EXECUTABLE NAMES svn svn.bat)
# FindSubversion does not work with symlinks. See PR 8437
if (NOT IS_SYMLINK "${path}")
find_package(Subversion)
endif()
if (Subversion_FOUND)
subversion_wc_info( ${path} Project )
if (Project_WC_REVISION)
set(${revision} ${Project_WC_REVISION} PARENT_SCOPE)
endif()
if (Project_WC_URL)
set(${repository} ${Project_WC_URL} PARENT_SCOPE)
endif()
endif()
endmacro()
macro(get_source_info_git_svn path revision repository)
find_program(git_executable NAMES git git.exe git.cmd)
if (git_executable)
execute_process(COMMAND ${git_executable} svn info
WORKING_DIRECTORY ${path}
TIMEOUT 5
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_output)
if (git_result EQUAL 0)
string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
"\\2" git_svn_rev "${git_output}")
set(${revision} ${git_svn_rev} PARENT_SCOPE)
string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
"\\2" git_url "${git_output}")
set(${repository} ${git_url} PARENT_SCOPE)
endif()
endif()
endmacro()
macro(get_source_info_git path revision repository)
find_program(git_executable NAMES git git.exe git.cmd)
if (git_executable)
execute_process(COMMAND ${git_executable} log -1 --pretty=format:%H
WORKING_DIRECTORY ${path}
TIMEOUT 5
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_output)
if (git_result EQUAL 0)
set(${revision} ${git_output} PARENT_SCOPE)
endif()
execute_process(COMMAND ${git_executable} remote -v
WORKING_DIRECTORY ${path}
TIMEOUT 5
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_output)
if (git_result EQUAL 0)
string(REGEX REPLACE "^(.*\n)?[^ \t]+[ \t]+([^ \t\n]+)[ \t]+\\(fetch\\).*"
"\\2" git_url "${git_output}")
set(${repository} "${git_url}" PARENT_SCOPE)
endif()
endif()
endmacro()
function(get_source_info path revision repository)
if (EXISTS "${path}/.svn")
get_source_info_svn("${path}" revision repository)
elseif (EXISTS "${path}/.git/svn/refs")
get_source_info_git_svn("${path}" revision repository)
elseif (EXISTS "${path}/.git")
get_source_info_git("${path}" revision repository)
endif()
endfunction()
function(append_info name path)
get_source_info("${path}" revision repository)
string(STRIP "${revision}" revision)
string(STRIP "${repository}" repository)
file(APPEND "${HEADER_FILE}.txt"
"#define ${name}_REVISION \"${revision}\"\n")
file(APPEND "${HEADER_FILE}.txt"
"#define ${name}_REPOSITORY \"${repository}\"\n")
endfunction()
function(validate_inputs source_dirs names)
list(LENGTH source_dirs source_dirs_length)
list(LENGTH names names_length)
if (NOT source_dirs_length EQUAL names_length)
message(FATAL_ERROR
"GetSVN.cmake takes two arguments: a list of source directories, "
"and a list of names. Expected two lists must be of equal length, "
"but got ${source_dirs_length} source directories and "
"${names_length} names.")
endif()
endfunction()
if (DEFINED SOURCE_DIRS AND DEFINED NAMES)
validate_inputs("${SOURCE_DIRS}" "${NAMES}")
list(LENGTH SOURCE_DIRS source_dirs_length)
math(EXPR source_dirs_max_index ${source_dirs_length}-1)
foreach(index RANGE ${source_dirs_max_index})
list(GET SOURCE_DIRS ${index} source_dir)
list(GET NAMES ${index} name)
append_info(${name} ${source_dir})
endforeach()
endif()
# Allow -DFIRST_SOURCE_DIR arguments until Clang migrates to the new
# -DSOURCE_DIRS argument.
if(DEFINED FIRST_SOURCE_DIR)
append_info(${FIRST_NAME} "${FIRST_SOURCE_DIR}")
if(DEFINED SECOND_SOURCE_DIR)
append_info(${SECOND_NAME} "${SECOND_SOURCE_DIR}")
endif()
endif()
# Copy the file only if it has changed.
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${HEADER_FILE}.txt" "${HEADER_FILE}")
file(REMOVE "${HEADER_FILE}.txt")

View File

@ -3,90 +3,92 @@
# existence of certain subdirectories under SOURCE_DIR (if provided as an
# extra argument, otherwise uses CMAKE_CURRENT_SOURCE_DIR).
function(add_version_info_from_vcs VERS)
SET(SOURCE_DIR ${ARGV1})
if("${SOURCE_DIR}" STREQUAL "")
SET(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
endif()
string(REPLACE "svn" "" result "${${VERS}}")
if( EXISTS "${SOURCE_DIR}/.svn" )
set(result "${result}svn")
# FindSubversion does not work with symlinks. See PR 8437
if( NOT IS_SYMLINK "${SOURCE_DIR}" )
function(get_source_info_svn path revision repository)
# If svn is a bat file, find_program(Subversion) doesn't find it.
# Explicitly search for that here; Subversion_SVN_EXECUTABLE will override
# the find_program call in FindSubversion.cmake.
find_program(Subversion_SVN_EXECUTABLE NAMES svn svn.bat)
find_package(Subversion)
endif()
# Subversion module does not work with symlinks, see PR8437.
get_filename_component(realpath ${path} REALPATH)
if(Subversion_FOUND)
subversion_wc_info( ${SOURCE_DIR} Project )
subversion_wc_info(${realpath} Project)
if(Project_WC_REVISION)
set(SVN_REVISION ${Project_WC_REVISION} PARENT_SCOPE)
set(result "${result}-r${Project_WC_REVISION}")
set(${revision} ${Project_WC_REVISION} PARENT_SCOPE)
endif()
if(Project_WC_URL)
set(LLVM_REPOSITORY ${Project_WC_URL} PARENT_SCOPE)
set(${repository} ${Project_WC_URL} PARENT_SCOPE)
endif()
endif()
else()
find_program(git_executable NAMES git git.exe git.cmd)
endfunction()
if( git_executable )
# Run from a subdirectory to force git to print an absoute path.
execute_process(COMMAND ${git_executable} rev-parse --git-dir
WORKING_DIRECTORY ${SOURCE_DIR}/cmake
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_dir
ERROR_QUIET)
if(git_result EQUAL 0)
# Try to get a ref-id
string(STRIP "${git_dir}" git_dir)
set(result "${result}git")
if( EXISTS ${git_dir}/svn )
# Get the repository URL
execute_process(COMMAND
${git_executable} svn info
WORKING_DIRECTORY ${SOURCE_DIR}
TIMEOUT 5
function(get_source_info_git path revision repository)
find_package(Git)
if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --git-dir
WORKING_DIRECTORY ${path}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_output
ERROR_QUIET)
if(git_result EQUAL 0)
string(REGEX MATCH "URL: ([^ \n]*)" svn_url ${git_output})
if(svn_url)
set(LLVM_REPOSITORY ${CMAKE_MATCH_1} PARENT_SCOPE)
endif()
endif()
# Get the svn revision number for this git commit if one exists.
execute_process(COMMAND ${git_executable} svn find-rev HEAD
WORKING_DIRECTORY ${SOURCE_DIR}
TIMEOUT 5
string(STRIP "${git_output}" git_output)
get_filename_component(git_dir ${git_output} ABSOLUTE BASE_DIR ${path})
if(EXISTS "${git_dir}/svn/refs")
execute_process(COMMAND ${GIT_EXECUTABLE} svn info
WORKING_DIRECTORY ${path}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_head_svn_rev_number
OUTPUT_STRIP_TRAILING_WHITESPACE)
if( git_result EQUAL 0 AND git_output)
set(SVN_REVISION ${git_head_svn_rev_number} PARENT_SCOPE)
set(git_svn_rev "-svn-${git_head_svn_rev_number}")
else()
set(git_svn_rev "")
endif()
endif()
# Get the git ref id
execute_process(COMMAND
${git_executable} rev-parse --short HEAD
WORKING_DIRECTORY ${SOURCE_DIR}
TIMEOUT 5
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_ref_id
OUTPUT_STRIP_TRAILING_WHITESPACE)
OUTPUT_VARIABLE git_output)
if(git_result EQUAL 0)
set(GIT_COMMIT ${git_ref_id} PARENT_SCOPE)
set(result "${result}${git_svn_rev}-${git_ref_id}")
string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
"\\2" git_svn_rev "${git_output}")
set(${revision} ${git_svn_rev} PARENT_SCOPE)
string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
"\\2" git_url "${git_output}")
set(${repository} ${git_url} PARENT_SCOPE)
endif()
else()
set(result "${result}${git_svn_rev}")
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
WORKING_DIRECTORY ${path}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_output)
if(git_result EQUAL 0)
string(STRIP "${git_output}" git_output)
set(${revision} ${git_output} PARENT_SCOPE)
endif()
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref --symbolic-full-name @{upstream}
WORKING_DIRECTORY ${path}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_output
ERROR_QUIET)
if(git_result EQUAL 0)
string(REPLACE "/" ";" branch ${git_output})
list(GET branch 0 remote)
else()
set(remote "origin")
endif()
execute_process(COMMAND ${GIT_EXECUTABLE} remote get-url ${remote}
WORKING_DIRECTORY ${path}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_output
ERROR_QUIET)
if(git_result EQUAL 0)
string(STRIP "${git_output}" git_output)
set(${repository} ${git_output} PARENT_SCOPE)
else()
set(${repository} ${path} PARENT_SCOPE)
endif()
endif()
endif()
endif()
set(${VERS} ${result} PARENT_SCOPE)
endfunction(add_version_info_from_vcs)
endfunction()
function(get_source_info path revision repository)
if(EXISTS "${path}/.svn")
get_source_info_svn("${path}" revision_info repository_info)
else()
get_source_info_git("${path}" revision_info repository_info)
endif()
set(${repository} "${repository_info}" PARENT_SCOPE)
set(${revision} "${revision_info}" PARENT_SCOPE)
endfunction()

View File

@ -1,38 +1,21 @@
find_first_existing_vc_file(llvm_vc "${LLVM_MAIN_SRC_DIR}")
find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc)
# The VC revision include that we want to generate.
set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/VCSRevision.h")
set(get_svn_script "${LLVM_CMAKE_PATH}/GenerateVersionFromCVS.cmake")
set(generate_vcs_version_script "${LLVM_CMAKE_PATH}/GenerateVersionFromVCS.cmake")
file(WRITE "${version_inc}.undef" "#undef LLVM_REVISION\n")
if((DEFINED llvm_vc) AND LLVM_APPEND_VC_REV)
execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files
"${version_inc}.undef" "${version_inc}"
RESULT_VARIABLE files_not_equal
OUTPUT_QUIET
ERROR_QUIET)
# Remove ${version_inc} if it doesn't define a revision. This will force it
# to be regenerated when toggling LLVM_APPEND_VC_REV from OFF to ON.
if(NOT files_not_equal)
file(REMOVE "${version_inc}")
if(llvm_vc AND LLVM_APPEND_VC_REV)
set(llvm_source_dir ${LLVM_MAIN_SRC_DIR})
endif()
# Create custom target to generate the VC revision include.
add_custom_command(OUTPUT "${version_inc}"
DEPENDS "${llvm_vc}" "${get_svn_script}"
COMMAND
${CMAKE_COMMAND} "-DSOURCE_DIR=${LLVM_MAIN_SRC_DIR}"
"-DNAME=LLVM_REVISION"
DEPENDS "${llvm_vc}" "${generate_vcs_version_script}"
COMMAND ${CMAKE_COMMAND} "-DNAMES=LLVM"
"-DLLVM_SOURCE_DIR=${llvm_source_dir}"
"-DHEADER_FILE=${version_inc}"
-P "${get_svn_script}")
else()
# Make sure ${version_inc} doesn't define a revision
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${version_inc}.undef" "${version_inc}")
endif()
file(REMOVE "${version_inc}.undef")
-P "${generate_vcs_version_script}")
# Mark the generated header as being generated.
set_source_files_properties("${version_inc}"