Issue with the install phase of package

Currently, for windows, I use a local installation area. Between Qt, and other 3rd party shared libraries, its difficult to have a user create installation otherwise. To do so, I have used for sometime, and it works great, setting the CMAKE_INSTALL_PREFIX to the following

SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/Install)
IF(${CMAKE_INSTALL_CONFIG_NAME} MATCHES “^([Dd][Ee][Bb][Uu][Gg])$”)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}.debug)
ENDIF()

Some of the 3rd party libraries, unfortunately, do not differentiate debug vs release, thus the need to have “Install” and “Install.debug”

This works great, except during the actual install phase, we need to add some INSTALL( CODE ) to do the same thing

IF("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES “^([Dd][Ee][Bb][Uu][Gg])$”)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}.debug)
ENDIF()

No big deal, it was figured out, and works great.

However, we to be able to create a package in debug as well…

And here is where the problem comes in, the CPack system, doesnt use the CMAKE_INSTALL_PREFIX variable in the same manner… So the files get installed into the “debug” directory, however, the packaging looks in the non-debug area, which is empty.

Is there any variable that is set during the Package phase that I can use as a guard?

if ( NOT CPACK_RUNNING_NOW )

endif()

Or does anyone have any other solution for this?


Scott Aron Bloom

    February 27

Currently, for windows, I use a local installation area. Between Qt, and other 3rd party shared libraries, its difficult to have a user create installation otherwise. To do so, I have used for sometime, and it works great, setting the CMAKE_INSTALL_PREFIX to the following

SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/Install)

IF(${CMAKE_INSTALL_CONFIG_NAME} MATCHES “^([Dd][Ee][Bb][Uu][Gg])$”)

SET(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}.debug)

ENDIF()

Some of the 3rd party libraries, unfortunately, do not differentiate debug vs release, thus the need to have “Install” and “Install.debug”

This works great, except during the actual install phase, we need to add some INSTALL( CODE ) to do the same thing

IF(“${CMAKE_INSTALL_CONFIG_NAME}” MATCHES “^([Dd][Ee][Bb][Uu][Gg])$”)

SET(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}.debug)

ENDIF()

No big deal, it was figured out, and works great.

However, we to be able to create a package in debug as well…

And here is where the problem comes in, the CPack system, doesnt use the CMAKE_INSTALL_PREFIX variable in the same manner… So the files get installed into the “debug” directory, however, the packaging looks in the non-debug area, which is empty.

Is there any variable that is set during the Package phase that I can use as a guard?

if ( NOT CPACK_RUNNING_NOW )

endif()

You cannot do that in your CMakeLists.txt because CPack runs when CMake doesn’t anymore. Thus CPack does not read/execute the content of your CMakeLists.txt.

See: https://cmake.org/cmake/help/v3.12/module/CPack.html#variable:CPACK_PROJECT_CONFIG_FILE

Or does anyone have any other solution for this?

CPack is using https://cmake.org/cmake/help/latest/variable/CPACK_PACKAGING_INSTALL_PREFIX.html

and not CNAKE_INSTALL_PREFIX.

Yes and no.

CPack, absolutely runs a a cmake install to a local area under _CPack_Packages directory. It installs to the local area, and then “packages” up the install area. The problem is, I cant find a way to have it look in the .debug directory. It creates the “app-version-os” area but installs to “app-version-os.debug” area because of the install prefix that is used…

The CPACK_PACKAGING_INSTALL_PREFIX doesnt work the same way at all, when set the packaging fails completely.

the question I have… is if CPack is what is being called (it is), and it has its own “install” system, that doesnt use the same system as the cmake system… Why??

The INSTALL(CODE) mechanism, creates the install control script.

So some more experimenting…

If I blow away the build area’s install directories… CPack fails…

However, if I remove part of it, (anything but the main target) CPack creates a full and valid install area, in the “debug” directory

However, it still looks for files in the original, non-debug suffixed directory

If I modify the CPACK_PACKAGE_FILE_NAME to point to the debug… It then installs to .debug.debug

Which means, it is definitely using the CMake logic above to append it.

OK… So I think I may have tracked down the issue…and its probably a user misunderstanding.

Turning on verbose reporting in cpack…

If I set a variable in the CPACK_PROPERTIES_FILE, that variable is NOT sent forward to the install system that CPack calls

At the end of my generated CPackConfig.cmake, I put the following

MESSAGE( STATUS “CPACK_RUNNING=${CPACK_RUNNING}” )

and the following is reported, as expected

CPack: Enable Verbose
CPack Verbose: Read CPack config file: ./CPackConfig.cmake
CPack Verbose: Read CPack configuration file: C:/Users/sbloom/sb/scottaronbloom/BSACalc/build/CPackConfig.cmake
– CPACK_RUNNING=1

When I put the same inside the cmake_install.cmake

CPack: - Install project: BSACalc
CPack Verbose: Install configuration: “Debug”
CPack Verbose: CPACK_RUNNING=

Not sure how to get around this

I won’t be able to experiment with your setup because I won’t be behind a computer before saturday. So yes CPack uses CMake generated install script but he won’t read CMakeLists.txt.

I suspect your issue relies on your INSTALL(CODE…) which does not support DESTDIR mechanism which may be used by CPack for some generator.

I suggest you provide a minimal example reproducing your issue.

I won’t look at it before Saturday but may be others will step in.

I have some more questions:

which CPack generator are you using?

which version of CMake are you using?

Thanks Ill work on the minimal example… I do have a github location that Ill post it in… It will most likely be a simple cmake file and a trivial main.cpp

Im currently using cpack/cmake 3.15.19101501-MSVC_2, but was able to reproduce it with the normally downloaded 3.15.7

Thanks.

Note, this appears to mostly be due to the multi-config allowance of Visual Studio…

I created a simple testcase on github

Running Visual Studio 2019, but not using the integrated cmake. Note I have not tried the integrated cmake flow under VS.

clone https://github.com/scottaronbloom/TestCPack.git
cd TestCPack
mkdir build
cd build
cmake ..
cmake --build . --target TestCPack --config Debug
cmake --install . --config Debug
cpack -C Debug --config ./CPackConfig.cmake -G ZIP -V

Note: Cpack installs to _CPack_Packages/Win64/ZIP/TestCPack-1.2.3-win64.debug
However, if you look inside the _CPack_Packages/Win64/ZIP directory, you will see 2 directories, one with, and one without the .debug suffix

The one without the suffix, is empty, the one with is fully populated.

If you examine the resulting zip file, it is empty.

Thanks, and let me know if you need anything further.

Wondering if you were able to take a look.

Yes but I have a small reproducibility issue. Your code assume the CMake generator is a multi-config one. I don’t have access to a Windows platform (because I don’t do dev on Windows nowadays) and there is currently no multi-config generator on Linux beside the fresh new Nina MultiConfig.

All that said I observe a :slight_smile: similar behavior on Linux with the makefile generator.
You can see how cpack is somehow ignoring your custom install dir by adding --debug to your cpack call, i.e.:

cpack -C Debug --config ./CPackConfig.cmake -G ZIP -V --debug

you’ll see something like:
[xxx] cmCPackArchiveGenerator.cxx:232 Toplevel: <prefix>/_CPack_Packages/Linux/ZIP/TestCPack-1.2.3-Linux
i.e. no debug.

My guess: CPack does not seems to take into account the “-C Debug” for computing the toplevel directory. The fact is I don’t how it would guess it since you craft it yourself with the INSTALL(CODE...) part so that CPack has no clue where the to-be-packaged files are to be found…

You can trick cpack by telling it (using internal CPack variable CPACK_TEMPORARY_DIRECTORY) where:

cpack -D CPACK_TEMPORARY_DIRECTORY=<prefix>/TestCPack/build/_CPack_Packages/Linux/ZIP/TestCPack-1.2.3-Linux.debug -C Debug --config ./CPackConfig.cmake -G ZIP -V --debug

with this I bet you’ll have the expected result.

Now this is a non robust hack that will certainly fail silently if any internal CPack change are done.
Basically I think that you cannot trick CPack with the destination directory you want it to use.
So fiddling with CMAKE_INSTALL_PREFIX in INSTALL(CODE ...) is a bad idea.

I think CPack lacks the feature you want: packaging several project configuration at once.
I.e. currently you can ask CPack to install & package one project configuration i.e. Debug, Release etc… but you cannot decide the name of the directory of the internal CPack temporary area used for packaging.

So when you say:

This is a wrong assumption. CPack autonomously handle where the file are installed in its staging area. So you can ask CPack to use the Debug config for the package but CPack decide where to install it and then looks there for packaging.

So my question is, why do you need the INSTALL( CODE ... doesn’t CPack works as expected when you remove it ?

Thanks for the info. But as you ask, it comes down to the question

I dont really need it for CPack… I do however need it for CMake install

On windows, when creating an install directory, it can be critical to differentiate from Debug and Release builds. The C runtime libraries are different, and for some 3rd party tools, they dont differentiate by name (using a ‘d’ suffix is typical). So if you have a lib name mylib.dll and its named the same thing for debug and release, its critical that your debug build picks up the correct version (and vice versa for release builds)

The process I put in place to build, debug, and deploy was to use cmake install, to create 100% isolated install directories (both linux and windows). It works great, and Ive been very happy with the results.

The CMake default install directories on windows, are admin protected (as they should be) so the INSTALL_PREFIX gets set to be a subdirectory of the binary area. This works great, and allows developers on the team, to have the ability to fully deploy a release area locally. It also allows for the install tools to simply “zip it up”. I really love the cmake install. however until now, we used cpack on linux, and an external install system on windows (not nsis)

In looking into nsis, is when I hit this problem for debug builds. We normally dont ship a debug build, however, internally we might use the cpack -G zip for obvious reasons.

One thing that I did try, is using a variable “CPACK_RUNNING_CPACK” or something along those lines. So using a -D CPACK_RUNNING_CPACK=1 or setting it via CPackConfig.cmake via the CPACK_PROPERTIES_FILE I thought would work, but the cmake variables sent forward when the install phase is called from cpack doesnt set the variable.

Do you know of anyway to set a variable in CPack, that is set when install is called?

Yes I think I do.
If you use a CPACK_PROJECT_CONFIG_FILE
https://cmake.org/cmake/help/v3.17/module/CPack.html#variable:CPACK_PROJECT_CONFIG_FILE,

This file will be loaded (by CPack) when CPack runs so that any variables defined in this file are visible
in the context of CPack execution.

In your CMakeLists.txt you usually do something like:

configure_file("${PROJECT_SOURCE_DIR}/CPackOptions.cmake.in"
               "${PROJECT_BINARY_DIR}/CPackOptions.cmake" @ONLY)
set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CPackOptions.cmake")

...
include(CPack)

There is some description on the way this file may be used here:
https://gitlab.kitware.com/cmake/community/-/wikis/doc/cpack/PackageGenerators#overall-usage-common-to-all-generators

Unfortunately, I had already tried this, and get the same results. While this lets me setup different variables on a per config basis. Those same variables are not passed along when cpack runs its install phase.