cmake_path(APPEND) with a variable gives unexpected result

I’m using CMake 3.29.0 on Ubuntu 20.04.6 LTS

The objective is to create an application configuration file that is generated with user-configurable directories in ccmake.

What I want to do is:

  • Specify a project root directory, typically /var/my-project.
  • Separately specify subdirectories, like a staging subdirectory, e.g. /staging/

I then want to create a CI_CD_STAGING_DIR_PATH variable by concatenating the project root directory and the staging subdirectory names. (i.e. /var/my-project/staging/)

# Initialise variables
set(THIS_EXECUTABLE_NAME delta-deployment)
set(CI_CD_PROJECT_ROOT_DIR "/var/my-project/" CACHE STRING "Root project directory")
set(CI_CD_STAGING_SUBDIR "/${THIS_EXECUTABLE_NAME}/staging/" CACHE STRING "Staging subdirectory")

# Do some path cleanup and convert to absolute path
cmake_path(SET CI_CD_PROJECT_ROOT_DIR NORMALIZE "${CI_CD_PROJECT_ROOT_DIR}/")
cmake_path(ABSOLUTE_PATH CI_CD_PROJECT_ROOT_DIR NORMALIZE)

# Concatenate root dir and subdir (this is where things go awry)
cmake_path(APPEND CI_CD_STAGING_DIR {CI_CD_PROJECT_ROOT_DIR} ${CI_CD_STAGING_SUBDIR})
message("CI_CD_PROJECT_ROOT_DIR " ${CI_CD_PROJECT_ROOT_DIR})
message("CI_CD_STAGING_DIR " ${CI_CD_STAGING_DIR})

What I expect to see is this:

 CI_CD_PROJECT_ROOT_DIR /var/my-project/
 CI_CD_STAGING_DIR /var/my-project/delta-deployment/staging/

What I actually see is:

 CI_CD_PROJECT_ROOT_DIR /var/my-project/
 CI_CD_STAGING_DIR /delta-deployment/staging/

So I do a test by replacing the cmake_path(APPEND) with some hard-coded values

cmake_path(APPEND CI_CD_STAGING_DIR "yadda" "foo" "bar")

Now I see

 CI_CD_PROJECT_ROOT_DIR /var/my-project/
 CI_CD_STAGING_DIR yadda/foo/bar

Then I change it to

cmake_path(APPEND CI_CD_STAGING_DIR "yadda" "foo" "bar" "${CI_CD_STAGING_SUBDIR}")

And I see

 CI_CD_PROJECT_ROOT_DIR /var/my-project/
 CI_CD_STAGING_DIR /delta-deployment/staging/

To the untrained eye it seems like cmake_path(APPEND) doesn’t work when one of the arguments is a variable; you only get the value of one variable and none of the others, including hard-coded values.

Any suggestions from the pros here?

The observed behavior has nothing to do with the fact a variable is used of not.
If you read carefully the documentation related to cmake_path(APPEND) you will see that the result depends on the semantics of arguments.
In your case, the variable CI_CD_STAGING_SUBDIR is an absolute path, so this implies the discard of previous arguments!
To get the expected results:

# Initialise variables
set(THIS_EXECUTABLE_NAME delta-deployment)
set(CI_CD_PROJECT_ROOT_DIR "/var/my-project/" CACHE STRING "Root project directory")
set(CI_CD_STAGING_SUBDIR "${THIS_EXECUTABLE_NAME}/staging/" CACHE STRING "Staging subdirectory")

# Do some path cleanup and convert to absolute path
cmake_path(SET CI_CD_PROJECT_ROOT_DIR NORMALIZE "${CI_CD_PROJECT_ROOT_DIR}")
cmake_path(ABSOLUTE_PATH CI_CD_PROJECT_ROOT_DIR NORMALIZE)

# Concatenate root dir and subdir (this is where things go awry)
cmake_path(APPEND CI_CD_STAGING_DIR "${CI_CD_PROJECT_ROOT_DIR}" "${CI_CD_STAGING_SUBDIR}")