I have a git repository with another repository as a submodule. I wish to symlink single files from the submodule into my repository, instead of maintaining file(COPY ...) lines in CMakeLists.txt. As it is a repository, the symlinks have to be relative.
Is it possible to tell cmake, to either resolve the symlink to an absolute path, before copying it or copy the linked file instead?
I am looking for a general option. If I have to add specific commands for each file, I might as well use file(COPY ...)
The cmake version used is 3.16.3
Some Background:
We have a server application, which can be build against various front-ends. Each front-end requires its own configuration, but they share some files.
To automate the configuration we use a config-generator-script. This script consumes a set of files and directories, which are prepared by cmake from a source.
I want to share some files between these configurations, by adding the configuration repository, maintained by the developer of the application, as a submodule to my configuration repository.
To me, symlinks are easier to maintain and better visible. Partly because the CMakeLists.txt is usually not touched during updates, except to change the version. Some of the files-to-be-linked are referenced to in other source files and might be needed for reference during development. If a developer does not know, that this file is copied from someplace else during build generation, the missing file might lead to some confusion.
Example:
- Generate git repository, using the following template for a cmake environment: https://github.com/ChimeraTK/project-template
- Add the following directories to the repository:
<repository>/shared/dir/file
<repository>/dir
- Generate symlink in repository/dir/ via:
cd <repository>/dir
ln -s ../shared/dir/file .
- Add CMakeLists.txt with the following content:
project(example NONE)
set(${PROJECT_NAME}_MAJOR_VERSION 00)
set(${PROJECT_NAME}_MINOR_VERSION 01)
set(${PROJECT_NAME}_PATCH_VERSION 00)
include(cmake/set_version_numbers.cmake)
include(cmake/config_generator_project.cmake)
- Call cmake in some build directory
cmake <path_to_repository>
Result: Broken symlink <build-dir>/dir/file, instead of a file or symlink.
The short answer is: Yes, it is possible, but not easy.
The longer answer:
First, I have to explain a misunderstanding of mine. I am so used to working with this project template, that I assumed, copying the source files into a build directory is an innate process of cmake. It is not. It is actually described in one of the cmake-scripts in the project template.
Second, there is no single command or option, to tell cmake to resolve a link by copying the linked file (At least not up till cmake version 3.16). Instead I replaced the following command:
with this function:
This function copies all files in a directory and its sub-directories to a destination, but if the file is a relative symlink, instead of the symlink-files it copies the target file, but changes its name to the one of the symlink-file.
This way I can use symlinks in the project to point to shared resources outside of the project directory, as well as for symlinking to files in the same directory, i.e. chain-linking (a symlink, which contains just a filename, is also considered non-absolute).
This function could be easily modified, to generate symbolic or hard links to the target, instead of copying the target file or to work on a single file instead of a directory.
Update
Since the answer above, I learned of an alternative and easier way, to solve my problem. file(COPY) has the flag FOLLOW_LINK_CHAIN, which function is described in the documentation as follows:
This led me to believe, that it only maintains chain links, as they are common for libraries. But after testing it, I learned, that it works for me as well. Here is, what it does:
So this is my solution: