1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

Make paths in generated llvm-lit relative as well.

This builds on top of D77184. With this, I can rename my build directory
to a different name and `bin/llvm-lit ../llvm-project/clang/test
../llvm-project/llvm/test` still succeeds.

I haven't tried copying the build dir to a different machine to run
tests there yet, but I tried something like it a few months ago and it
worked back then.

Changes:
- Make configure_lit_site_cfg() store the main / generated config pair
  interleaved in the LLVM_LIT_CONFIG_FILES list and postpone converting
  it to python code to llvm-lit's CMakeList.
- Pull the relpath code into a new function make_paths_relative() and
  call that in llvm-lit's CMakeList, prior to converting the list to
  python code.
- Pull the path() function into a variable and use that in llvm-lit's
  CMakeList too.

Differential Revision: https://reviews.llvm.org/D77496
This commit is contained in:
Nico Weber 2020-04-04 20:25:27 -04:00
parent 8ffdfd4312
commit f4821b445c
2 changed files with 75 additions and 39 deletions

View File

@ -1391,6 +1391,52 @@ macro(set_llvm_build_mode)
endif ()
endmacro()
# Takes a list of path names in pathlist and a base directory, and returns
# a list of paths relative to the base directory in out_pathlist.
# Paths that are on a different drive than the basedir (on Windows) or that
# contain symlinks are returned absolute.
# Use with LLVM_LIT_PATH_FUNCTION below.
function(make_paths_relative out_pathlist basedir pathlist)
# Passing ARG_PATH_VALUES as-is to execute_process() makes cmake strip
# empty list entries. So escape the ;s in the list and do the splitting
# outselves. cmake has no relpath function, so use Python for that.
string(REPLACE ";" "\\;" pathlist_escaped "${pathlist}")
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "\n
import os, sys\n
base = sys.argv[1]
def haslink(p):\n
if not p or p == os.path.dirname(p): return False\n
return os.path.islink(p) or haslink(os.path.dirname(p))\n
def relpath(p):\n
if not p: return ''\n
if os.path.splitdrive(p)[0] != os.path.splitdrive(base)[0]: return p\n
if haslink(p) or haslink(base): return p\n
return os.path.relpath(p, base).replace(os.sep, '/')\n
sys.stdout.write(';'.join(relpath(p) for p in sys.argv[2].split(';')))"
${basedir}
${pathlist_escaped}
OUTPUT_VARIABLE pathlist_relative)
set(${out_pathlist} "${pathlist_relative}" PARENT_SCOPE)
endfunction()
# Converts a file that's relative to the current python file to an absolute
# path. Since this uses __file__, it has to be emitted into python files that
# use it and can't be in a lit module. Use with make_paths_relative().
string(CONCAT LLVM_LIT_PATH_FUNCTION
# Lit converts config paths to lower case in discovery.py, before
# loading the config. This causes __file__ to be all lower-case (including
# the drive letter), but several clang tests pass -include %s and a
# clang warning checks that passed case matches on-disk cache. So it's
# important that this restores the on-disk case of the prefix.
"# Allow generated file to be relocatable.\n"
"def path(p):\n"
" if not p: return ''\n"
" p = os.path.join(os.path.dirname(os.path.abspath(__file__)), p)\n"
" p = os.path.normpath(p).replace(os.sep, '/')\n"
" if os.name == 'nt' and os.path.isabs(p): return p[0].upper() + p[1:]\n"
" return p\n"
)
# This function provides an automatic way to 'configure'-like generate a file
# based on a set of common and custom variables, specifically targeting the
# variables needed for the 'lit.site.cfg' files. This function bundles the
@ -1453,20 +1499,9 @@ function(configure_lit_site_cfg site_in site_out)
set(HOST_CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}")
set(HOST_LDFLAGS "${CMAKE_EXE_LINKER_FLAGS}")
set(LIT_SITE_CFG_IN_HEADER "# Autogenerated from ${site_in}\n# Do not edit!")
# Lit converts config paths to lower case in discovery.py, before
# loading the config. This causes __file__ to be all lower-case (including
# the drive letter), but several clang tests pass -include %s and a
# clang warning checks that passed case matches on-disk cache. So it's
# important that this restores the on-disk case of the prefix.
string(CONCAT LIT_SITE_CFG_IN_HEADER "${LIT_SITE_CFG_IN_HEADER}\n\n"
"# Allow generated lit.site.cfg.py to be relocatable.\n"
"def path(p):\n"
" if not p: return ''\n"
" p = os.path.normpath(os.path.join(os.path.dirname(__file__), p)).replace(os.sep, '/')\n"
" if os.name == 'nt' and os.path.isabs(p): return p[0].upper() + p[1:]\n"
" return p\n"
string(CONCAT LIT_SITE_CFG_IN_HEADER
"# Autogenerated from ${site_in}\n# Do not edit!\n\n"
"${LLVM_LIT_PATH_FUNCTION}"
)
# Override config_target_triple (and the env)
@ -1493,27 +1528,9 @@ function(configure_lit_site_cfg site_in site_out)
endforeach()
list(REMOVE_AT ARG_PATH_VALUES 0)
# Compute paths relative to the directory containing output lit.site.cfg.py.
# Passing ARG_PATH_VALUES as-is to execute_process() makes cmake strip
# empty list entries. So escape the ;s in the list and do the splitting
# outselves. cmake has no relpath function, so use Python for that.
string(REPLACE ";" "\\;" ARG_PATH_VALUES_ESCAPED "${ARG_PATH_VALUES}")
get_filename_component(OUTPUT_DIR ${site_out} DIRECTORY)
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "\n
import os, sys\n
base = sys.argv[1]
def haslink(p):\n
if not p or p == os.path.dirname(p): return False\n
return os.path.islink(p) or haslink(os.path.dirname(p))\n
def relpath(p):\n
if not p: return ''\n
if os.path.splitdrive(p)[0] != os.path.splitdrive(base)[0]: return p\n
if haslink(p) or haslink(base): return p\n
return os.path.relpath(p, base).replace(os.sep, '/')\n
sys.stdout.write(';'.join(relpath(p) for p in sys.argv[2].split(';')))"
${OUTPUT_DIR}
${ARG_PATH_VALUES_ESCAPED}
OUTPUT_VARIABLE ARG_PATH_VALUES_RELATIVE)
make_paths_relative(
ARG_PATH_VALUES_RELATIVE "${OUTPUT_DIR}" "${ARG_PATH_VALUES}")
list(LENGTH ARG_PATHS len_paths)
list(LENGTH ARG_PATH_VALUES len_path_values)
@ -1537,10 +1554,10 @@ sys.stdout.write(';'.join(relpath(p) for p in sys.argv[2].split(';')))"
configure_file(${site_in} ${site_out} @ONLY)
if (EXISTS "${ARG_MAIN_CONFIG}")
set(PYTHON_STATEMENT "map_config('${ARG_MAIN_CONFIG}', '${site_out}')")
get_property(LLVM_LIT_CONFIG_MAP GLOBAL PROPERTY LLVM_LIT_CONFIG_MAP)
set(LLVM_LIT_CONFIG_MAP "${LLVM_LIT_CONFIG_MAP}\n${PYTHON_STATEMENT}")
set_property(GLOBAL PROPERTY LLVM_LIT_CONFIG_MAP ${LLVM_LIT_CONFIG_MAP})
# Remember main config / generated site config for llvm-lit.in.
get_property(LLVM_LIT_CONFIG_FILES GLOBAL PROPERTY LLVM_LIT_CONFIG_FILES)
list(APPEND LLVM_LIT_CONFIG_FILES "${ARG_MAIN_CONFIG}" "${site_out}")
set_property(GLOBAL PROPERTY LLVM_LIT_CONFIG_FILES ${LLVM_LIT_CONFIG_FILES})
endif()
endfunction()

View File

@ -1,7 +1,26 @@
get_property(LLVM_LIT_CONFIG_MAP GLOBAL PROPERTY LLVM_LIT_CONFIG_MAP)
get_property(LLVM_LIT_CONFIG_FILES GLOBAL PROPERTY LLVM_LIT_CONFIG_FILES)
list(LENGTH LLVM_LIT_CONFIG_FILES file_len)
math(EXPR file_last "${file_len} - 1")
get_llvm_lit_path(LIT_BASE_DIR LIT_FILE_NAME)
# LLVM_LIT_CONFIG_FILES contains interleaved main config (in the source tree)
# and site config (in the build tree) pairs. Make them relative to
# llvm-lit and then convert them to map_config() calls.
if("${CMAKE_CFG_INTDIR}" STREQUAL ".")
make_paths_relative(
LLVM_LIT_CONFIG_FILES "${LIT_BASE_DIR}" "${LLVM_LIT_CONFIG_FILES}")
endif()
set(LLVM_LIT_CONFIG_MAP "${LLVM_LIT_PATH_FUNCTION}\n")
foreach(i RANGE 0 ${file_last} 2)
list(GET LLVM_LIT_CONFIG_FILES ${i} main_config)
math(EXPR i1 "${i} + 1")
list(GET LLVM_LIT_CONFIG_FILES ${i1} site_out)
set(map "map_config(path('${main_config}'), path('${site_out}'))")
set(LLVM_LIT_CONFIG_MAP "${LLVM_LIT_CONFIG_MAP}\n${map}")
endforeach()
set(LLVM_SOURCE_DIR ${LLVM_MAIN_SRC_DIR})
if(NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".")