Just can't get the location of the project's source tree to CPack.

I’m trying to create an nsis installer via the GH Actions runners.
I’ve defined some code in the INSTALL section, to copy and bundle all the libs (I’m using a shell script , rather than the built-in functionality).

The problem is, I just can’t get the install script to know where the source tree is located at.
Of course, my first instinct was to just use CMAKE_SOURCE_DIR, when that didn’t work, I tried other versions (such as PROJECT_SOUR_DIR and <TARGET>_SOURCE_DIR), none of which work.

Then I realized CPACK should be able to get variables that start with CPACK, so I made a CPACK_TOP_SOURCE_DIR which is set the CMAKE_SOURCE_DIR; again, didn’t work. I reasoned maybe it’s because it was being re-set on every run (including CPack) and thus was being set to empty during install. So, I came up with the following:

if (CMAKE_SOURCE_DIR AND (NOT (CMAKE_SOURCE_DIR STREQUAL CPACK_TOP_SOURCE_DIR)))
		set (CPACK_TOP_SOURCE_DIR "${CMAKE_SOURCE_DIR}" CACHE INTERNAL "Source directory to be used by CPack." FORCE)
endif()

Looking into CPackConfig.txt shows that it apparently works:

runneradmin@fv-az250-215 MINGW64 /d/a/performous/performous/performous/build
# cat CPackConfig.cmake | grep TOP_SOURCE                                                                                         
set(CPACK_TOP_SOURCE_DIR "D:/a/performous/performous/performous")

But again, this doesn’t work during the install phase.

install(CODE [[
		message ("SOURCE DIR IS: ${CPACK_TOP_SOURCE_DIR}")
]])

prints

CPack: Install projects
CPack: - Run preinstall target for: Performous
CPack: - Install project: Performous []
SOURCE DIR IS: 

What am I doing wrong, and how can I fix it? At this point, the only idea I’m getting is to maybe use a file instead of a variable, and then read the contents of the file, but that’s an even nastier hack that what I’m already using…

Could you explain why you need the source directory in the install script in the first place? Just in case there’s a more elegant solution

I’m running a script to gather and copy runtime dependencies (that does a better job than the built-in functionality) and I needed the source to pass folders and options properly to it.

I managed to solve it in a very hacky but functional way. I first check if CMAKE_SOURCE_DIR is set; if it is, I write its value to a temp file, which I then read during the install phase. It’s dirty but it works.

Gotcha. “Whatever works” is usually the only sensible option with CMake :slight_smile: . If you do ever want to revisit it though:

CPack does have your variable as you saw. If you were to e.g. make a custom NSIS project file template, you’d have access to that variable inside that template.

cmake_install.txt, which is run by CPack in order to build an installation folder it can compress, and is the thing with your message( call in it, does not have access to the variable.

The problem is that cmake_install.cmake is what runs the install(CODE, and it’s invoked as a separate script with something like cmake -P cmake_install.cmake, so it gets none of your variables.

So cmake_install.cmake has the message("SOURCE DIR IS: ${CPACK_TOP_SOURCE_DIR}" but that var is never set in the context of the install script. You can move the variable into the installation like this:

install(CODE "set(CPACK_TOP_SOURCE_DIR ${CPACK_TOP_SOURCE_DIR})")
install(CODE [[
    message("Source dir = ${CPACK_TOP_SOURCE_DIR}")
]])

And then if you re-run cmake and either cmake --install . --prefix . or cpack you’ll find your message correctly printed. You’ll find both the set( and message( lines inside the cmake_install.cmake.