I try to copy Qt frameworks with a file(COPY) command with FOLLOW_SYMLINK_CHAIN. When it tries copying the Resources symlink, I get this error.
CMake Error at /Users/administrator/CMakeProjectTemplate/cmake/CopySymlinkChain.cmake:17 (file):
file COPY cannot make directory
"/Users/administrator/CMakeProjectTemplate/Release/install/QtCore.framework/Resources":
Too many levels of symbolic links.
I go into the Release/instal/QtCore.framework directory and I only see the symlink for the Resources directory, but nothing else. Not sure what is going on here. Would someone give some advice or insight into the problem?
(I would upload a sample project, but I cannot, since I am a new user, so I will just comment as much as I can about a sample project.)
- Create a framework with similar structure to that of a Qt framework.
administrator@Administrators-MacBook-Pro TestCopyFramework % ls -lR A_Framework.framework
total 0
lrwxr-xr-x 1 administrator staff 22 Dec 29 20:00 A_Framework -> Versions/A/A_Framework
lrwxr-xr-x 1 administrator staff 18 Dec 29 19:59 Headers -> Versions/A/Headers
lrwxr-xr-x 1 administrator staff 20 Dec 29 20:00 Resources -> Versions/A/Resources
drwxr-xr-x 5 administrator staff 160 Dec 29 20:00 Versions
A_Framework.framework/Versions:
total 0
drwxr-xr-x 6 administrator staff 192 Dec 29 20:00 A
lrwxr-xr-x 1 administrator staff 1 Dec 29 19:59 Current -> A
A_Framework.framework/Versions/A:
total 0
-rw-r--r-- 1 administrator staff 0 Dec 29 19:58 A_Framework
drwxr-xr-x 2 administrator staff 64 Dec 29 19:58 Headers
drwxr-xr-x 2 administrator staff 64 Dec 29 19:58 Resources
A_Framework.framework/Versions/A/Headers:
total 0
A_Framework.framework/Versions/A/Resources:
total 0
- Create a script that will copy a source to a destination while copying symlink chains.
# Copy symlink chains
message(STATUS "CMAKE_ARGC: ${CMAKE_ARGC}")
foreach(i RANGE 0 ${CMAKE_ARGC} 1)
message(STATUS "CMAKE_ARGV${i}: ${CMAKE_ARGV${i}}")
list(APPEND ARGV ${CMAKE_ARGV${i}})
endforeach()
message(STATUS "ARGV: ${ARGV}")
set(options "")
set(oneValueArgs "DESTINATION")
set(multiValueArgs "SOURCES")
cmake_parse_arguments(COPY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV})
message(STATUS "COPY_SOURCES: ${COPY_SOURCES}")
message(STATUS "COPY_DESTINATION: ${COPY_DESTINATION}")
file(COPY
${COPY_SOURCES}
DESTINATION ${COPY_DESTINATION}
FOLLOW_SYMLINK_CHAIN)
- Run cmake to invoke the script to attempt to copy A_Framework.framework to a destination.
administrator@Administrators-MacBook-Pro TestCopyFramework % cmake -P CopySymlinkChain.cmake -- SOURCES A_Framework.framework DESTINATION A_DestFramework
-- CMAKE_ARGC: 8
-- CMAKE_ARGV0: cmake
-- CMAKE_ARGV1: -P
-- CMAKE_ARGV2: CopySymlinkChain.cmake
-- CMAKE_ARGV3: --
-- CMAKE_ARGV4: SOURCES
-- CMAKE_ARGV5: A_Framework.framework
-- CMAKE_ARGV6: DESTINATION
-- CMAKE_ARGV7: A_DestFramework
-- CMAKE_ARGV8:
-- ARGV: cmake;-P;CopySymlinkChain.cmake;--;SOURCES;A_Framework.framework;DESTINATION;A_DestFramework
-- COPY_SOURCES: A_Framework.framework
-- COPY_DESTINATION: A_DestFramework
CMake Error at CopySymlinkChain.cmake:17 (file):
file COPY cannot make directory
"/Users/administrator/TestCopyFramework/A_DestFramework/A_Framework.framework/Resources":
Too many levels of symbolic links.
Long story short, it fails.
To get around this limitation, I created my own function called CopyQtFramework
# Function to copy a Qt module framework.
# Parameters:
# MODULE_NAME is the name of the Qt module. Framework folder assumed to be Qt${MODULE_NAME}.framework.
# SOURCE_PATH is the path to the framework.
# DESTINATION_PATH is the path to which to copy the framework.
function(CopyQtFramework
MODULE_NAME
SOURCE_PATH
DESTINATION_PATH
)
# message(STATUS "ARGC: ${ARGC}")
# message(STATUS "ARGV: ${ARGV}")
# message(STATUS "ARGN: ${ARGN}")
set(options "")
set(oneValueArgs "TARGET;SOURCE_PATH;MODULE_NAME;DESTINATION_PATH")
set(multiValueArgs "")
cmake_parse_arguments(FRAMEWORK "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV})
# message(STATUS "FRAMEWORK_SOURCE_PATH: ${FRAMEWORK_SOURCE_PATH}")
# message(STATUS "FRAMEWORK_MODULE_NAME: ${FRAMEWORK_MODULE_NAME}")
# message(STATUS "FRAMEWORK_DESTINATION_PATH: ${FRAMEWORK_DESTINATION_PATH}")
# ================================================================================
# Qt Frameworks are structured as followed:
# * Qt<module>.framework
# * Headers -> Versions/A/Headers
# * Qt<module> -> Versions/A/Qt<module>
# * Resources -> Versions/A/Resources
# * Versions
# * A
# * Headers
# * Qt<module>
# * Resources
# * Current -> A
# ================================================================================
# Make all directories
file(MAKE_DIRECTORY
${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework) # Qt<module>.framework
file(MAKE_DIRECTORY
${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions) # Qt<module>.framework/Versions
file(MAKE_DIRECTORY
${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A) # Qt<module>.framework/Versions/A
file(MAKE_DIRECTORY
${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Headers) # Qt<module>.framework/Versions/A/Headers
file(MAKE_DIRECTORY
${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Resources) # Qt<module>.framework/Versions/A/Resources
# Copy contents of directories
file(GLOB_RECURSE FRAMEWORK_HEADERS_FILES ${FRAMEWORK_SOURCE_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Headers/*)
file(COPY
${FRAMEWORK_HEADERS_FILES}
DESTINATION ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Headers)
file(GLOB_RECURSE FRAMEWORK_RESOURCES_FILES ${FRAMEWORK_SOURCE_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Resources/*)
file(COPY
${FRAMEWORK_RESOURCES_FILES}
DESTINATION ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Resources)
file(COPY
${FRAMEWORK_SOURCE_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Qt${FRAMEWORK_MODULE_NAME}
DESTINATION ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A)
# Create the symlinks
file(CREATE_LINK ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Headers ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Headers SYMBOLIC)
file(CREATE_LINK ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Resources ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Resources SYMBOLIC)
file(CREATE_LINK ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/Current SYMBOLIC)
file(CREATE_LINK ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Versions/A/Qt${FRAMEWORK_MODULE_NAME} ${FRAMEWORK_DESTINATION_PATH}/Qt${FRAMEWORK_MODULE_NAME}.framework/Qt${FRAMEWORK_MODULE_NAME} SYMBOLIC)
endfunction()