Skip to content

Commit 7b428b1

Browse files
N3xedlaukik-hase
authored andcommitted
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 <[email protected]>
1 parent 17c0cf3 commit 7b428b1

File tree

2 files changed

+22
-21
lines changed

2 files changed

+22
-21
lines changed

CMakeLists.txt

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -120,35 +120,33 @@ endif()
120120

121121
# Create a symbolic link from ${base_name} in the binary directory
122122
# to the corresponding path in the source directory.
123+
# Note: Copies the file(s) on Windows.
123124
function(link_to_source base_name)
124-
# Get OS dependent path to use in `execute_process`
125-
if (CMAKE_HOST_WIN32)
126-
#mklink is an internal command of cmd.exe it can only work with \
127-
string(REPLACE "/" "\\" link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
128-
string(REPLACE "/" "\\" target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
129-
else()
130-
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
131-
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
132-
endif()
125+
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
126+
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
133127

134-
if (NOT EXISTS ${link})
128+
# Linking to non-existent file is not desirable. At best you will have a
129+
# dangling link, but when building in tree, this can create a symbolic link
130+
# to itself.
131+
if (EXISTS ${target} AND NOT EXISTS ${link})
135132
if (CMAKE_HOST_UNIX)
136-
set(command ln -s ${target} ${link})
133+
execute_process(COMMAND ln -s ${target} ${link}
134+
RESULT_VARIABLE result
135+
ERROR_VARIABLE output)
136+
137+
if (NOT ${result} EQUAL 0)
138+
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
139+
endif()
137140
else()
138141
if (IS_DIRECTORY ${target})
139-
set(command cmd.exe /c mklink /j ${link} ${target})
142+
file(GLOB_RECURSE files FOLLOW_SYMLINKS LIST_DIRECTORIES false RELATIVE ${target} "${target}/*")
143+
foreach(file IN LISTS files)
144+
configure_file("${target}/${file}" "${link}/${file}" COPYONLY)
145+
endforeach(file)
140146
else()
141-
set(command cmd.exe /c mklink /h ${link} ${target})
147+
configure_file(${target} ${link} COPYONLY)
142148
endif()
143149
endif()
144-
145-
execute_process(COMMAND ${command}
146-
RESULT_VARIABLE result
147-
ERROR_VARIABLE output)
148-
149-
if (NOT ${result} EQUAL 0)
150-
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
151-
endif()
152150
endif()
153151
endfunction(link_to_source)
154152

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Bugfix
2+
* Fix a build issue on Windows where the source and build directory could not be on
3+
different drives (#5751).

0 commit comments

Comments
 (0)