How to with CPack generate the WIX package? - cmake

I used cmake 3.12.0. There are exists one cmake project that creates one console application. I add the ability of package generation to that cmake project:
# ... above cmake code for one console application creation
# below code that I add:
# pack
set (A_PACK_DESCRIPTION_SUMMARY "${PROJECT_NAME} - CMake Assistant Solution")
set (A_INSTALL_PREFIX Consolas)
set(CPACK_WIX_PRODUCT_GUID "F9AAAAE2-D6AF-4EA4-BF46-B3E265400CC8")
set(CPACK_WIX_UPGRADE_GUID "F9AAAAE2-D6AF-4EA4-BF46-B3E265400CC7")
set(CPACK_GENERATOR "WIX")
include(CPack)
With other generators (NSIS, 7Z, ZIP, DEB) all works fine but with WIX appears followed error:
...path\files.wxs(11) : error LGHT0091 : Duplicate symbol 'Component:CM_C_EMPTY_INSTALL_ROOT' found. This typically means that an Id is duplicated. Check to make sure all your identifiers of a given type (File, Component, Feature) are unique.
Why it happens and how to fix it?

This appears to be caused by this bug
Basically you use add_subdirectory(xxx EXCLUDE_FROM_ALL) where the subdirectory has a install(... COMPONENT ...) call. The installed files are excluded from the subdirectory, but still creates COMPONENTs, which are now empty and break wix.
As a workaround, you can add:
set(CPACK_COMPONENTS_ALL Unspecified)
in CMakeLists.txt to exclude all the empty components.

If it helps any, I had this problem and found that I had INSTALL commands that specified only Release Configurations but then tried to build the package using the Debug build configuration. By just switching to building the package specifying the Release configuration all went as expected (Wasted most of an afternoon before I figured this out!)

Related

Qt example project fails to build (No CMake configuration found)

I am trying to simply open Qt6.4.1 sensors example project, but it says that no CMake configuration found. I already made some simple Qt6 applications for Windows, and i have entire Qt6.4.1 package installed, so cant blame on bad installation. There is an error on line find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick Sensors Svg) in CMakeLists.txt. Full error message:
C:\Qt\Examples\Qt-6.4.1\sensors\sensorsshowcase\CMakeLists.txt:12: error: By not providing "FindQt6.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "Qt6", but CMake did not find one. Could not find a package configuration file provided by "Qt6" with any of the following names: Qt6Config.cmake qt6-config.cmake Add the installation prefix of "Qt6" to CMAKE_PREFIX_PATH or set "Qt6_DIR" to a directory containing one of the above files. If "Qt6" provides a separate development package or SDK, be sure it has been installed.
Pass the path to the directory containing the Qt6 files via CMAKE_PREFIX_PATH cache variable during configuration.
Note: Make sure to specify the type of the variable as PATH or use forward slashes as path separator for this to work properly.
E.g. for me I'd need to pass
-D CMAKE_PREFIX_PATH=D:/Qt/6.4.1/msvc2019_64
to tell CMake to look into the directory containing the Qt6.4.1 files compiled with MSVC.
Make sure that the directory you pass contains the file lib/cmake/Qt6/Qt6Config.cmake; this is the file find_package(Qt6 REQUIRED COMPONENTS ...) is looking for.
You can also fix your project setup that previously failed by adding the cache variable.
cmake -D CMAKE_PREFIX_PATH=D:/Qt/6.4.1/msvc2019_64 path/to/build_dir
Note: Don't forget to add the -A ... option when configuring a VS project; CMake defaults to Win32 as architecture, at least on my system.
You could add this info to a CMAKE_PREFIX_PATH environment variable, if you don't want to specify the info cache variable for every single project using qt 6 that you want to set up on your machine.

cmake not finding package configuration file

I am using Qt Creator as IDE and MSVC 2019.
I built and installed the pagmo library from the source. Now I am trying to use it for my project.
Even though the installation seems fine, when I try to load it I get strange errors, telling me that "pagmo" is not found. In particular:
error:
By not providing "FindPagmo.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Pagmo",
but CMake did not find one.
Could not find a package configuration file provided by "Pagmo" with any
of the following names:
PagmoConfig.cmake
pagmo-config.cmake
Add the installation prefix of "Pagmo" to CMAKE_PREFIX_PATH or set
"Pagmo_DIR" to a directory containing one of the above files. If
"Pagmo" provides a separate development package or SDK, be sure it has
been installed.
In my CMakeLists.txt I have set the following command:
find_package(Pagmo REQUIRED)
Now, as far as I know FindPagmo.cmake does not exist, BUT I am giving as input parameter Pagmo_DIR, which contains the file pagmo-config.cmake. I can't understand why CMake is not finding it. I also tried to set CMAKE_MODULE_PATH to the same folder but nothing changed.
Does anybody have suggestions on how to solve this problem?
I am setting pagmo directory as follows:
-DPagmo_DIR = C:\Lib\pagmo\install\debug\lib\cmake\pagmo
in that folder I have the following files:
Findpagmo_IPOPT.cmake;
pagmo_export.cmake;
pagmo_export-debug.cmake;
pagmo-config.cmake;
pagmo-config-version.cmake;
PagmoFindBoost.cmake

cmake find_package unable to find Eigen3Config.cmake spectra Windows

I am using Eigen3 with spectra (https://spectralib.org/), a library built on top of Eigen. Spectra uses find_package to find Eigen, and comes up with the error:
Could not find a package configuration file provided by "Eigen3" with any
of the following names:
Eigen3Config.cmake
eigen3-config.cmake
Looking through the directory of Eigen, I found that there were no files by those names, but rather one called Eigen3Config.cmake.in. I tried copying the file and renaming it Eigen3Config.cmake, but that gave me a different error of
find_package Error reading CMake code from "C:/Program Files
(x86)/Eigen3/cmake/Eigen3Config.cmake".
which was somewhat expected, but it does tell me that it can at least find the directory where Eigen3Config.cmake.in is. I'm assuming that either find_package is supposed to use Eigen3Config.cmake.in, or Eigen3Config.cmake.in is supposed to generate Eigen3Config.cmake, but i'm very new to cmake, so i'm not sure. How do I fix this?
There is no need to build/install Eigen to use it if you include it manually, as done in the getting started example (https://eigen.tuxfamily.org/dox/GettingStarted.html#title0)
But in order to be found by CMake, you will need to build / install it, as explained in the INSTALL file. https://gitlab.com/libeigen/eigen/-/blob/master/INSTALL
Usually, your error is followed by an hint asking you to set the variable Eigen3_DIR (or something similar) to point the build/install dir of the target project (Eigen3 here). It appears typically when you have built but not installed the project.
So:
Build Eigen
Install it (optional)
For spectra set the cmake var Eigen3_DIR to /path/to/Eigen/build . (if eigen not install or still not found)
These steps worked for me:
Install Eigen
Create a build directory for Eigen
cd into the build directory created
run "cmake ../"Your Eigen Source Directory""
After this is done, in your CMakeLists.txt of your project, you'll want to add "find_package( Eigen3 REQUIRED)" and "include_directories( ${EIGEN3_INCLUDE_DIR})".

CMake - how to block executing installation scripts during packaging?

My CMakeLists.txt file contains commands, which should be executed by make install, and all this works fine. The sample CMakeLists.txt below is a short excerpt from my actual CMake file (the tm0001.cpp content is not important here - it might be any C++ program):
cmake_minimum_required(VERSION 3.12)
project(tm0001)
set(CMAKE_CXX_STANDARD 11)
add_executable(${PROJECT_NAME} tm0001.cpp)
install(
TARGETS ${PROJECT_NAME}
DESTINATION /usr/local/bin
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
install(CODE "message(\"-- This must be called during installation only\")")
set(CPACK_PACKAGE_CONTACT "HEKTO")
set(CPACK_GENERATOR "DEB")
include(CPack)
I see the message command is executed by make package as well, which is not I want.
How to tell CMake not to execute installation scripts by the make package command? I couldn't find any way to do that with the CMake if command.
As it already said in the comment, it's an extremely bad idea to "work w/ systemd" (and doing anything not related to build or packaging of your project) from install commands. The install command (even SCRIPT and CODE signatures) are intended to be used for install actions and not for any other side effects.
The correct way to act here is to produce a native package (DEB/RPM) w/ post-install script, where using the system-provided macros (like described here), you can install your package properly. Take a look to CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA for the way to provide package install actions.
The other bad thing is to use the hardcoded path (/usr/bin/). And BTW, a better place for the (pure) daemon app I suggest /usr/sbin/. Take a look to GNUInstallDirs module shipped w/ CMake for further references.
What I did was to specify install commands with CODE/SCRIPT as separate component e.g. install(CODE ... COMPONENT post-install).
Then also added other non-code install commands as a different component e.g. install(FILES ... COMPONENT files-install)
The CPack then needs to be configured to package only files-install component (solution to this can be found easily - hint: use CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE, CPACK_COMPONENTS_ALL and CPACK_(RPM/DEB/...)_COMPONENT_INSTALL variables).
Of course then the resulting package won't run these CODE components during installing the package - they need to be added separately as a post install script.
I'm answering my own question, because the existing answer doesn't address my main problem. I couldn't find any way (on the CMake level) to block install commands from running during make package - even the postinst script is called by this command.
Fortunately, I could modify the postinst script itself to do nothing in case it's called not by the dpkg:
if [ -z ${DPKG_ADMINDIR} ]; then
echo "postinst: missing 'dpkg' environment (not an error during packaging)"
exit 0
fi
It's a trick of course, but it worked for me.

CLion: issue with Cmake configuration types

I understand that by default, Clion creates the binary files for a project loaded in Clion in all the four configurations:
(Debug;Release;MinSizeRel;RelWithDebInfo)
as well as one called: __default__.
I am using a third party cmake module which downloads an external project in a way that add_subdirectory() can be run on it so it would be included in the root project.
add_subdirectory(${downloaded_proj_src_dir} ${downloaded_proj_bin_dir} EXCLUDE_FROM_ALL)
In this setup, if I decide to place the child project outside the binary directory of the root project, I get:
Error:Binary directories outside of CMake build directory are not supported. Most likely this error is caused by an add_subdirectory command with an explicitly specified binary_dir argument.
which is an understandable restriction by CMake.
now if I instead decide to set the binary directory of the downloaded project in a subdirectory of the binary directory of the parent project, ie:
set(downloaded_proj_bin_dir "${CMAKE_BINARY_DIR}/${downloaded_proj}-build")
...
add_subdirectory(${downloaded_proj_src_dir} ${downloaded_proj_bin_dir} EXCLUDE_FROM_ALL)
I will get the file created in the parent binary directory of all the build configurations because ${CMAKE_BINARY_DIR} is different for each configuration. To avoid seeing all these directories listed on the project view sidebar, I have set the CMAKE_CONFIGURATION_TYPES to be Debug. But even then, I get:
Error:Configuration Debug
The current CMakeCache.txt directory /path/Debug/downloaded_proj_bin/CMakeCache.txt is different than the directory /path/__default__/downloaded_proj_bin/CMakeCache.txt where CMakeCache.txt was created. This may result in binaries being created in the wrong place. If you are not sure, reedit the CMakeCache.txt
Clearly something is going on with this __default__ configuration which I don't understand. So the question is, what is the significance of this default configuration and why should there be a conflict here?
P.s. Setting the configuration to __default__ does not solve the problem as I will have a __default__0 configuration created instead and get the same error.
Update: some further observations
My enviornment variables set in IDE don't have any effect on the cmake builds.
Cmake "options" however which presumably will be passed as arguments to cmake do seem to work.
-D CMAKE_CONFIGURATION_TYPES=Debug.
When I specify the command line option, I get
Warning:Manually-specified variables were not used by the project:
CMAKE_CONFIGURATION_TYPES
But it clearly does have the effect of no longer creating the other build configurations. My guess is that this message relates to the __default__ build which is ignoring the argument.
Even in the case of specifying CMAKE_CONFIGURATION_TYPES in the IDE, I still get the additional __default__ build which is apparently unaffected by the CMAKE_CONFIGURATION_TYPES assignment.
Logging: message("Build type: ${CMAKE_BUILD_TYPE} ) does not return any build_type.
Outputting message(and generator: ${CMAKE_GENERATOR} ") returns "Unix-make files" for both, so both are being generated with the same generator.
Taking a diff from the CMakeCache.txt files, I can see that they are identical.
Do you have in DownloadProject.cmake the right setting? for:
set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}")
I had the same problem trying to set google test(with the help of https://github.com/Crascit/DownloadProject) and my _DownloadProjectDir was setted as "test". Maybe when I moved this cmake file in my project Clion changed that automatically.
So, it turns out that you can sort this out quite easily by adding the following line above line 145 in DownloadProject.cmake:
file(REMOVE "${DL_ARGS_DOWNLOAD_DIR}/CMakeCache.txt")
This seems to be because CLion copies the default across to the other configurations and doesn't clear the cache. This is a problem only because DownloadProject creates a project within the project (I think...). Anyway, deleting this file before configuring the CMakeLists.txt by-passes this issue. I'll submit a pull request to the DownloadProject repository as this doesn't seem to have any adverse effects when not using CLion.