CMake/CPack command for InstallDirRegKey - cmake

In an NSIS script file, it is possible to set the following, to use a registry entry as the install directory:
InstallDirRegKey HKCU "Software\Test" "RegEntry"
I was wondering if it would be possible to set this command from a cmake file, so that the NSIS script is automatically generated. Much in the same way the directory of an install can be set like:
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "testDir")
Many thanks

I'm not following exactly what you're trying to do, but if you just want a custom command in the NSIS file, you can do this:
list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
InstallDirRegKey HKCU \"Software\\Test\" \"RegEntry\"
")
Be careful of the backslashes, needed to escape the double quote and the literal backslash. I think you might need 4 backslashes instead of 2 for the literal backslash, but try it and see. Check the resulting NSIS file, and add more backslashes as necessary.
EDIT:
There's another, much more complete way to customize the NSIS install script. According to this: http://cmake.org/Wiki/CMake:CPackNSISAdvancedTips you can copy NSIS.template.in (from your CMake installation) into your source tree (in a directory that's on your CMAKE_MODULE_PATH) and modify it.

list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
InstallDirRegKey HKCU \"Software\\Test\" \"RegEntry\"
")
translates on my machine to
InstallDirRegKey HKCU ;Software\Test" "RegEntry;`
Try rather
list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
InstallDirRegKey HKCU 'Software\\\\Test' 'RegEntry'
")

Related

Specify Location of Cmake Find[Package]

I'm trying to find a given package using a FindX.cmake file. Unfortunately, it seems like it continues to use one located at /A/FindX.cmake, rather than a different one at /B/FindX.cmake. Is there a way to specify the location of which Find[Package].cmake is used by find_package(X)?
Simply add path /B to the beginning of the CMAKE_MODULE_PATH variable:
set(CMAKE_MODULE_PATH "/B" ${CMAKE_MODULE_PATH})
Such way CMake will prefer FindX.cmake script from /B to scripts in other directories.

cpack and install(CODE ...) - CPACK_PACKAGING_INSTALL_PREFIX vs CMAKE_INSTALL_PREFIX

as a "post-install hook" I need to execute an install command like
install(CODE "execute_process(COMMAND some_command ${CMAKE_INSTALL_PREFIX}/some_folder"))
which creates a file in some_folder based on the files which were previously installed into some_folder (it compiles an index/cache of those files).
This works fine for the install target, however as soon as using cpack ${CMAKE_INSTALL_PREFIX} is not the correct location anymore.
Is there a variable like ${CMAKE_CURRENT_INSTALL_PREFIX} that always points towards the current installation directory, regardless of wether the default install target or cpack is used and can be used for this purpose?
The only alternative I see is to try to execute the command at an earlier stage on the original files, create a temporary file and install the temporary file. Unfortunately this is much more error prone, as some_command should be run on the "final" files after installation (in order to create a valid cache)
The answer turns out to be extremely simple (kudos to Nils Gladitz from IRC):
Escaping the variable ${CMAKE_INSTALL_PREFIX} with a backslash delays its expansion until install time at which it holds the correct value also for installs via CPack:
install(CODE "execute_process(COMMAND some_command \${CMAKE_INSTALL_PREFIX}/some_folder"))

cmake detect empty directory during build time

I have a custom command that is executed if a directory exists. I need to know if the directory is not empty before executing another command.
Question: How to read, detect or get the number of files of a directory?
You can run regular CMake code as script using cmake -P as part of build process.
The script itself would contain somethng like
file(GLOB RESULT DIR)
list(LENGTH RESULT RES_LEN)
if(RES_LEN EQUAL 0)
# DIR is empty, do something
endif()

Customizing NSIS installer using CPACK

I am trying to customize an NSIS installer using CMAKE and CPACK.
In particular I would like to include in the generated project.nsi an external script.
Something like:
!include "#SCRIPT_PATH#\#SCRIPT_NAME#.nsh"
To do so I am following the example shown here: https://gitlab.kitware.com/cmake/community/-/wikis/doc/cpack/NSISAdvancedTips
I have copied the template script file (NSIS.template.in) and added the required commands.
I now need to configure the two variables "#SCRIPT_PATH# and #SCRIPT_NAME# accordingly.
I tried to set them like standard CMAKE variables
SET(SCRIPT_PATH "somePath")
SET(SCRIPT_NAME "someName")
but the template variables are simply left blank by CPACK
Any clue?
I have found a working solution.
Start by adding a placeholder in the main NSIS.template.in where you want to insert new commands, for instance:
#NSIS_ADDITIONAL_SCRIPT#
Then you need to configure a template file containing options that will be passed to the CPACK build.
The CPackOptions.cmake contains the following:
SET(NSIS_ADDITIONAL_SCRIPT ${NSIS_ADDITIONAL_SCRIPT})
Then in your CMAKE script before including CPACK you need to set the NSIS_ADDITIONAL_SCRIPT variable (the path is reworked in order to have the correct set of backslashes on window systems)
SET(scriptPath "[path to the script location]" )
FILE(TO_NATIVE_PATH ${scriptPath} scriptPath )
STRING(REPLACE "\\" "\\\\" scriptPath ${scriptPath} )
and finally configure the CPackOption.cmake file (watch out for the correct number of slashes and comas)
SET(NSIS_ADDITIONAL_SCRIPT " \"!include \\\"${scriptPath}\\\" \\n \" ")
CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/CMakeConf/CPackOptions.cmake ${PROJECT_BINARY_DIR}/CPackOptions.cmake)
If you do everything correctly:
by configuring and generating the CMAKE script you will find the file CPackOptions.cmake in your project build folder.
This configured file will be then used by CPACK to fill in the variable added in the NSIStemplate.in.
The final generated project.nsi will contain the additional !include instruction

How can I get cmake command from cmake-gui?

I use cmake-gui to configure OpenCV, and I want to use same configure on some other computer.
Cause I use ssh without X forwarding, so I can't use cmake-gui to configure again.
I don't kown how to use cmake to complete my configure, so I wonder that cmake-gui can generate the command use for cmake?
Is there anyway to do this?
There is an option called: Tools-> Show my Changes which displays exactly what you have configured relating to the original configuration. One version are the copy&paste command line parameters and the other version is nicely human readable.
By default you cannot do what you want because that path is stored in CMAKE_COMMAND which is an INTERNAL variable so it is not visible in the GUI. You can manually read it from the cache using a command like grep CMAKE_COMMAND CMakeCache.txt | cut -d = -f 2. Alternatively you can update your CMakeLists.txt to put the value of CMAKE_COMMAND in the cache so that you can read it using the GUI. For example:
set(USED_CMAKE_PATH ${CMAKE_COMMAND} CACHE FILEPATH
"The path to the CMake executable used to configure this project" FORCE)
Additionally if you are using the "Unix Makefiles" generator there are two targets provided for this:
rebuild_cace which is equivalent to cmake .
edit_cache which is equivalent to ccmake . or cmake-gui . depending upon your install.
Note: I used CMake version 2.8.10.2 to test this, but I expect it to work with any version.