# CMake error while trying to file(COPY) framework with FOLLOW\_SYMLINK\_CHAIN

**URL:** https://discourse.cmake.org/t/cmake-error-while-trying-to-file-copy-framework-with-follow-symlink-chain/9739
**Category:** Code
**Tags:** os:macos
**Created:** [December 30, 2023, 1:42am UTC](https://discourse.cmake.org/t/cmake-error-while-trying-to-file-copy-framework-with-follow-symlink-chain/9739 "2023-12-30T01:42:29Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![CompSciDude](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/e95f7d/32.png) [@CompSciDude](https://discourse.cmake.org/u/CompSciDude)
#### Post date: [December 30, 2023, 1:42am UTC](https://discourse.cmake.org/t/cmake-error-while-trying-to-file-copy-framework-with-follow-symlink-chain/9739/1 "2023-12-30T01:42:30Z")

</div>

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.

```auto
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?

---

<div class="post-metadata">

### Author: ![CompSciDude](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/e95f7d/32.png) [@CompSciDude](https://discourse.cmake.org/u/CompSciDude)
#### Post date: [December 30, 2023, 2:11am UTC](https://discourse.cmake.org/t/cmake-error-while-trying-to-file-copy-framework-with-follow-symlink-chain/9739/2 "2023-12-30T02:11:22Z")

</div>

(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.

```auto
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.

```auto
# 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.

```auto
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.

---

<div class="post-metadata">

### Author: ![CompSciDude](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/e95f7d/32.png) [@CompSciDude](https://discourse.cmake.org/u/CompSciDude)
#### Post date: [December 30, 2023, 3:45am UTC](https://discourse.cmake.org/t/cmake-error-while-trying-to-file-copy-framework-with-follow-symlink-chain/9739/3 "2023-12-30T03:45:07Z")

</div>

To get around this limitation, I created my own function called CopyQtFramework

```auto

# 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()

```
