Warning, /frameworks/extra-cmake-modules/modules/ECMWinResolveSymlinks.cmake is written in an unsupported language. File is not indexed.
0001 # SPDX-FileCopyrightText: 2016 Gleb Popov <6yearold@gmail.com> 0002 # 0003 # SPDX-License-Identifier: BSD-3-Clause 0004 0005 #[=======================================================================[.rst: 0006 ECMWinResolveSymlinks 0007 -------------------------- 0008 0009 Resolve pseudo-symlinks created by git when cloning on Windows. 0010 0011 :: 0012 0013 ecm_win_resolve_symlinks(<dir>) 0014 0015 When git checks out a repository with UNIX symlinks on Windows machine, 0016 it creates a text file for each symlink, containing a relative path to the 0017 real file. 0018 This function would recursively walk over specified directory and replace 0019 pseudo-symlinks with corresponding real file's contents. It would then run 0020 ``git update-index --assume-unchanged`` on them to trick git. 0021 0022 This is useful for projects like "breeze-icons" that contain many identical 0023 icons implemented as symlinks. 0024 0025 Since 5.28 0026 #]=======================================================================] 0027 0028 function(ECM_WIN_RESOLVE_SYMLINKS _dir) 0029 get_filename_component(dir ${_dir} ABSOLUTE) 0030 find_program(GIT_EXECUTABLE git) 0031 if(NOT GIT_EXECUTABLE) 0032 message(SEND_ERROR "Git executable not found!") 0033 endif() 0034 0035 message(STATUS "Resolving symlinks in ${dir}...") 0036 _find_symlinks(${dir} symlinks) 0037 _portioned_list(symlinks ${symlinks}) 0038 foreach(s IN LISTS symlinks) 0039 string(REPLACE ":" ";" s ${s}) 0040 _assume_unchanged(NO ${dir} "${s}") 0041 _checkout_symlinks(${dir} "${s}") 0042 _resolve_symlinks(${dir} "${s}") 0043 _assume_unchanged(YES ${dir} "${s}") 0044 endforeach() 0045 message(STATUS "Resolving symlinks in ${dir}... Done.") 0046 0047 # touch cache every build to force CMake to re-run these functions every time 0048 if(NOT TARGET wrs_touch_cache) 0049 add_custom_target(wrs_touch_cache ALL 0050 COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/CMakeCache.txt 0051 ) 0052 endif() 0053 endfunction() 0054 0055 function(_assume_unchanged mode dir symlinks) 0056 if(mode) 0057 set(flag --assume-unchanged) 0058 else() 0059 set(flag --no-assume-unchanged) 0060 endif() 0061 0062 execute_process(COMMAND ${GIT_EXECUTABLE} update-index ${flag} ${symlinks} 0063 WORKING_DIRECTORY ${dir} 0064 ) 0065 endfunction() 0066 0067 function(_find_symlinks dir outvar) 0068 execute_process(COMMAND ${GIT_EXECUTABLE} ls-files -s 0069 WORKING_DIRECTORY ${dir} 0070 OUTPUT_VARIABLE out 0071 OUTPUT_STRIP_TRAILING_WHITESPACE 0072 ) 0073 0074 set(${outvar}) 0075 if(out) 0076 string(REPLACE "\n" ";" out ${out}) 0077 0078 foreach(f IN LISTS out) 0079 # 120000 0db97052931e18484b6705f3bc644484ef9403b0 0 <tab> icons-dark/actions/16/CVnamespace.svg 0080 string(REPLACE "\t" ";" f "${f}") 0081 string(REPLACE " " ";" f "${f}") 0082 list(GET f 0 mode) 0083 if(mode STREQUAL "120000") 0084 list(GET f 3 symlink) 0085 list(APPEND ${outvar} ${symlink}) 0086 endif() 0087 endforeach() 0088 endif() 0089 set(${outvar} ${${outvar}} PARENT_SCOPE) 0090 endfunction() 0091 0092 # In functions like _checkout_symlinks() the command line can become too lengthy for Windows. 0093 # So we partition it, but in a hacky way due to CMake doesn't have list of lists. 0094 function(_portioned_list outvar) 0095 list(LENGTH ARGN arglen) 0096 0097 if(arglen EQUAL 0) 0098 set(${outvar} "" PARENT_SCOPE) 0099 return() 0100 endif() 0101 0102 set(init) 0103 set(tail) 0104 math(EXPR range "${arglen} - 1") 0105 foreach(i RANGE ${range}) 0106 list(GET ARGN ${i} v) 0107 string(LENGTH "${init}" initlen) 0108 string(LENGTH ${v} vlen) 0109 math(EXPR sumlen "${initlen} + ${vlen}") 0110 if(sumlen LESS 8192) 0111 list(APPEND init ${v}) 0112 else() 0113 list(APPEND tail ${v}) 0114 endif() 0115 endforeach() 0116 0117 _portioned_list(tail_portioned ${tail}) 0118 string(REPLACE ";" ":" init "${init}") # Generally this is not safe, because filepath can contain ':' character. But not on Windows. Phew. 0119 set(${outvar} ${init} ${tail_portioned} PARENT_SCOPE) 0120 endfunction() 0121 0122 function(_checkout_symlinks dir symlinks) 0123 execute_process(COMMAND ${GIT_EXECUTABLE} checkout ${symlinks} 0124 WORKING_DIRECTORY ${dir} 0125 ) 0126 endfunction() 0127 0128 function(_resolve_symlinks dir symlinks) 0129 foreach(s IN LISTS symlinks) 0130 file(READ ${dir}/${s} sdata) 0131 get_filename_component(sdir ${dir}/${s} DIRECTORY) 0132 set(f "${sdir}/${sdata}") 0133 file(READ ${f} fdata) 0134 file(WRITE ${dir}/${s} ${fdata}) 0135 endforeach() 0136 endfunction()