我們KDE在breeze-icons項目中偶然發現了這個問題。它廣泛使用符號鏈接,在Windows上,我們必須以某種方式將它們解析爲真實文件。這在ECMWinResolveSymlinks.cmake模塊中完成。
在執行時,我不得不解決長命令行問題。我將長文件列表分成一個「列表清單」,其中每個子列表都比8192短。由於CMake中的列表是用;
分隔的普通字符串,因此不能輕鬆創建「列表清單」之類的東西。我不得不使用另一個分隔符:
來區分間接的級別。之後,我在每個子列表的循環中調用git
。分裂的代碼如下所示:
# In functions like _checkout_symlinks() the command line can become too lengthy for Windows.
# So we partition it, but in a hacky way due to CMake doesn't have list of lists.
function(_portioned_list outvar)
list(LENGTH ARGN arglen)
if(arglen EQUAL 0)
set(${outvar} "" PARENT_SCOPE)
return()
endif()
set(init)
set(tail)
math(EXPR range "${arglen} - 1")
foreach(i RANGE ${range})
list(GET ARGN ${i} v)
string(LENGTH "${init}" initlen)
string(LENGTH ${v} vlen)
math(EXPR sumlen "${initlen} + ${vlen}")
if(sumlen LESS 8192)
list(APPEND init ${v})
else()
list(APPEND tail ${v})
endif()
endforeach()
_portioned_list(tail_portioned ${tail})
string(REPLACE ";" ":" init "${init}") # Generally this is not safe, because filepath can contain ':' character. But not on Windows. Phew.
set(${outvar} ${init} ${tail_portioned} PARENT_SCOPE)
endfunction()
它可以用於像:
file(GLOB ${dir}/* files)
_portioned_list(portioned_files ${files})
foreach(fs IN LISTS portioned_files)
# convert back to CMake list
string(REPLACE ":" ";" fs ${fs})
execute_process(COMMAND ${somecommand} ${fs}
endforeach()