Copy files instead of hard-linking on Windows
Fixes an issue on Windows where when source and build directory are on different drives hard-linking to files or directory fails as it doesn't work across filesystem boundaries. Note that symlinking is also not possible because it requires administrator privileges on Windows. The solution copies the files using the built-in cmake `configure_file(src dest COPYONLY)` command. As this command only operates on files, if a directory is specified the files will be globbed recursively and through symlinks. Signed-off-by: Dominik Gschwind <dominik.gschwind99@gmail.com>
This commit is contained in:
parent
f421d45869
commit
c6d16362f3
2 changed files with 18 additions and 20 deletions
|
@ -120,38 +120,33 @@ endif()
|
||||||
|
|
||||||
# Create a symbolic link from ${base_name} in the binary directory
|
# Create a symbolic link from ${base_name} in the binary directory
|
||||||
# to the corresponding path in the source directory.
|
# to the corresponding path in the source directory.
|
||||||
|
# Note: Copies the file(s) on Windows.
|
||||||
function(link_to_source base_name)
|
function(link_to_source base_name)
|
||||||
# Get OS dependent path to use in `execute_process`
|
|
||||||
if (CMAKE_HOST_WIN32)
|
|
||||||
#mklink is an internal command of cmd.exe it can only work with \
|
|
||||||
string(REPLACE "/" "\\" link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
|
|
||||||
string(REPLACE "/" "\\" target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
|
|
||||||
else()
|
|
||||||
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
|
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
|
||||||
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
|
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
|
||||||
endif()
|
|
||||||
|
|
||||||
# Linking to non-existent file is not desirable. At best you will have a
|
# Linking to non-existent file is not desirable. At best you will have a
|
||||||
# dangling link, but when building in tree, this can create a symbolic link
|
# dangling link, but when building in tree, this can create a symbolic link
|
||||||
# to itself.
|
# to itself.
|
||||||
if (EXISTS ${target} AND NOT EXISTS ${link})
|
if (EXISTS ${target} AND NOT EXISTS ${link})
|
||||||
if (CMAKE_HOST_UNIX)
|
if (CMAKE_HOST_UNIX)
|
||||||
set(command ln -s ${target} ${link})
|
execute_process(COMMAND ln -s ${target} ${link}
|
||||||
else()
|
|
||||||
if (IS_DIRECTORY ${target})
|
|
||||||
set(command cmd.exe /c mklink /j ${link} ${target})
|
|
||||||
else()
|
|
||||||
set(command cmd.exe /c mklink /h ${link} ${target})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(COMMAND ${command}
|
|
||||||
RESULT_VARIABLE result
|
RESULT_VARIABLE result
|
||||||
ERROR_VARIABLE output)
|
ERROR_VARIABLE output)
|
||||||
|
|
||||||
if (NOT ${result} EQUAL 0)
|
if (NOT ${result} EQUAL 0)
|
||||||
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
|
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
if (IS_DIRECTORY ${target})
|
||||||
|
file(GLOB_RECURSE files FOLLOW_SYMLINKS LIST_DIRECTORIES false RELATIVE ${target} "${target}/*")
|
||||||
|
foreach(file IN LISTS files)
|
||||||
|
configure_file("${target}/${file}" "${link}/${file}" COPYONLY)
|
||||||
|
endforeach(file)
|
||||||
|
else()
|
||||||
|
configure_file(${target} ${link} COPYONLY)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endfunction(link_to_source)
|
endfunction(link_to_source)
|
||||||
|
|
||||||
|
|
3
ChangeLog.d/fix_hard_link_across_drives
Normal file
3
ChangeLog.d/fix_hard_link_across_drives
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Bugfix
|
||||||
|
* Fix a build issue on Windows where the source and build directory could not be on
|
||||||
|
different drives (#5751).
|
Loading…
Reference in a new issue