When does CMAKE_CURRENT_BINARY_DIR resolve symlinks?

Hi,

I have a project in a directory where two directory components are symbolic links (to directories). Normally I’m use to see CMAKE_* paths to be “logical” (i.e. what “pwd -L” shows). However, under circumstances some symlinks are resolved, sometimes even all, so that some CMAKE_* paths are “physical” (i.e. what “pwd -P” shows).

Under what circumstances CMAKE_CURRENT_BINARY_DIR and CMAKE_SOURCE_DIR do resolve symbolic links?

In my current situation I see that CMAKE_SOURCE_DIR is logical, as expected, but CMAKE_CURRENT_BINARY_DIR is neither logical nor physical but “mixed”: the last symlink is resolved, but not all. I tried to make a minimal example but there both got “mixed”. When I specify a path component too much plus extra “…” (resulting in the same) in cmake argument, then I see CMAKE_SOURCE_DIR logical and CMAKE_CURRENT_BINARY_DIR “mixed”. This is not exactly my sitation but I don’t understand it either.

When are symlinks resolved? How to use “logical” paths everywhere?

Let me show an example.

sdettmer@farm21-1:/tmp/cmake-test/symlink-test $ find /tmp/project_root*|xargs ls -ld
lrwx... /tmp/project_root -> project_root.physical
drwx... /tmp/project_root.physical
lrwx... /tmp/project_root.physical/app1 -> application1.physical
drwx... /tmp/project_root.physical/application1.physical
drwx... /tmp/project_root.physical/application1.physical/build
drwx... /tmp/project_root.physical/application1.physical/prj
-rw-... /tmp/project_root.physical/application1.physical/prj/CMakeLists.txt

CMakeLists.txt

cmake_minimum_required(VERSION 3.6.2)
project(PRJ1)
message(STATUS "CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}")
message(STATUS "CMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}")

now some invocations:

sdettmer@farm21-1:/tmp/project_root/app1/build $ rm -rf * ; cmake ../prj/
-- CMAKE_SOURCE_DIR=/tmp/project_root/application1.physical/prj
-- CMAKE_CURRENT_BINARY_DIR=/tmp/project_root/application1.physical/build
# both "mixed" (project root is not resolved, but app1 is resolved)

sdettmer@farm21-1:/tmp/project_root/app1/build $ rm -rf * ; cmake ../../app1/prj/
-- CMAKE_SOURCE_DIR=/tmp/project_root/app1/prj
-- CMAKE_CURRENT_BINARY_DIR=/tmp/project_root/application1.physical/build
# SOURCE is "logical" as expected, BINARY is "mixed" (only app1 is resolved)

sdettmer@farm21-1:/tmp/project_root/app1/build $ rm -rf * ; cmake /tmp/project_root/app1/prj
-- CMAKE_SOURCE_DIR=/tmp/project_root/app1/prj
-- CMAKE_CURRENT_BINARY_DIR=/tmp/project_root/application1.physical/build
# same: SOURCE is "logical" as expected, BINARY is "mixed" (only app1 is resolved)

I would like to have:

-- CMAKE_SOURCE_DIR=/tmp/project_root/app1/prj
-- CMAKE_CURRENT_BINARY_DIR=/tmp/project_root/app1/build

When does CMAKE_CURRENT_BINARY_DIR resolve symlinks in which parts of the path? How to avoid this?

Background is that I have generated header files in ${CMAKE_CURRENT_BINARY_DIR}/libaryX/include/ = /tmp/project_root/app1/build and I’m using ccache with CCACHE_WORKDIR=/tmp/project_root/app1 - which requires BINARY to be below SOURCE. The paths in real project are more complicated, here it is just to illustrate my question.

Any ideas?

cmake version 3.6.2
g++ 4.4.3 and newer

I cannot upload as attachment since I’m a new user, so I try uuencoded :slight_smile:

begin-base64 664 cmake-symlink-test.tgz
H4sIABP5cF4AA+2WXU+CUBjHufZTMNeFXqjnhXO46sKQlSXYANu6YqSsMFGC
41ZrffcO5lrpaOIw13p+N7Dn8PJwfvwPiDjpJOliGo6Fny4WQjkASKLruoIY
1jmVW4LkLl3V1yiYcqphHREm64RgWVLJ18baycNLFo2DWcXNLTMRpKqqZJNQ
iDhMi47zzK7VOm/1zAuz5RmW61sDu+JWjoHY8P85zZ3q7vHhn+3knxKkIKwz
ghWVVddCMeC/wH+QJLiae5TJ/8o/0TRCZP5lCzPZi4gWcwz5Pwg/+t+e/L1W
hRL5J4Tn/qlOGOT/NyjrP0mnpd+B3f1zHbNV/lmef/B/ePbxb1jBYziIMpG1
xfMOf4y5YM61Qv8Ukw3/Mv5cUdHhH//f+x/H0qUfR/MoXsZ+Gj4tozScNG5M
x+0PbZW2eZs0a+s3pHHtXOJmrRaHWRbchw3X63ojV63n5Xpzq2xY3SvTd4cj
xzD9Xt85PXndLL0VnmaMHMe0Pf+sb3ed22+nbw/llzn2TP5Nyub/bhnNJiW/
ACW+/xrSuBxniCJY/wEAAAAAAAAAAAAAAAAAAAAAAPbhHXR+w2kAKAAA
====

EDIT: Attached cmake-symlink-test.tgz

Steffen

This is part of the “translation map” in CMake. We trust the $PWD environment variable as the “canonical” spelling if it ends up resolving to the same as getcwd(). Referring to the source directory by relative path gets into the interesting difference of whether we should resolve it as the filesystem does (via getcwd()) or logically (via $PWD). This is an interesting use case for our replacement plan of the translation map.

Cc: @brad.king

See CMake Issue 16228 for more about the “translation map” logic, its intended purpose, and problems encountered due to it.