cpack MSI installation exceeding 2GB - packing into multiple CAB files - cmake

I am using cpack and Wix to create an MSI installer containing media files.
I am getting catastrophic failure, I read, due to cabinet file exceeding 2GB.
If I understand correctly, I can split the installation package into multiple CAB files.
Simplified CMakeLists.txt:
cmake_minimum_required(VERSION 3.14)
project(content 1.0.0 LANGUAGES CXX)
install(DIRECTORY video
DESTINATION "."
FILES_MATCHING REGEX ".+\.(avi|mp4)")
install(DIRECTORY images
DESTINATION "."
FILES_MATCHING PATTERN "*.png")
set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/misc/wix_patch.xml")
include(CPack)
I am not sure if it is correct, but I can add more media elements in wix_patch.xml:
<CPackWiXPatch>
<CPackWiXFragment Id="#PRODUCT">
<Media Id='2' Cabinet='package1.cab' EmbedCab='no'/>
<Media Id='3' Cabinet='package2.cab' EmbedCab='no'/>
</CPackWiXFragment>
</CPackWiXPatch>
Now the question arises, how can I assign DiskId attribute to files included in the CMake file?
How can I split files into these cabinet files?
If I am correct, in Wix file I would write:
<File Source="./vid.mp4" DiskId="2" />
To assign vid.mp4 file to package2.cab.
How can I achieve that using CPack?

Maybe you don't need to deal with cabinet files at all.
Starting from Wix 3.6 you can use <MediaTemplate/> to let Wix automatically generate multiple cabinets. See http://www.joyofsetup.com/2011/06/21/wix-and-cabinetry/
However, to use this with CPack, you have to specify your own template file using CPACK_WIX_TEMPLATE as the default template (https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/Internal/CPack/WIX.template.in) uses <Media/> which cannot coexist with <MediaTemplate/>.

Related

I tried to build something, but this error came and I couldn't get SW also

By not providing "FindSW.cmake" in CMAKE_MODULE_PATH this project has asked
CMake to find a package configuration file provided by "SW", but CMake did
not find one.
Could not find a package configuration file provided by "SW" with any of
the following names:
SWConfig.cmake
sw-config.cmake
Add the installation prefix of "SW" to CMAKE_PREFIX_PATH or set "SW_DIR" to
a directory containing one of the above files. If "SW" provides a separate
development package or SDK, be sure it has been installed.
What I am trying to build is leptonica, but I can't do it without having there .cmake files, and I have no idea how I can get them, since I couldn't build SW.

Install a target defined in an included directory [duplicate]

Consider the following CMakeLists.txt file:
add_subdirectory(execA)
add_subdirectory(libB)
install(TARGETS execA libB
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
I get the following error:
install TARGETS given target "execA" which does not exist in this
directory
execA and libB have their own CMakeList.txt files and are located under project directory, as well as the build directory I'm running cmake (cmake ..):
project
|------ CMakeList.txt (the one with the code)
|----execA
| \- .cpp, .hpp and CMakelist.txt
|----libB
| \- .cpp, .hpp and CMakelist.txt
|---- lib
|---- bin
\---- build (where I´m commanding: $ cmake ..
How do I fix this error?
According to this bugreport, install(TARGETS) command flow accepts only targets created within the same directory.
So you need either move the add_library() call into the top-level directory, or split install(TARGETS) call into per-target ones, and move each of them into the corresponding subdirectory.
Since CMake 3.13 install(TARGETS) can work even with targets created in other directories.
install(TARGETS) can install targets that were created in other directories. When using such cross-directory install rules, running make install (or similar) from a subdirectory will not guarantee that targets from other directories are up-to-date.
Even though it would help seeing the CMakeLists.txt files contained in the subdirectories, I guess they contain add_executable and/or add_library statements to create your stuff.
Also, because of your example, I guess you are using the same name of your directories for your targets.
That said, you should know that symbols defined in a CMakeLists.txt file in a subdirectory are not visible by default within the context of the CMakeLists.txt file in the parent directory. Because of that, you should rather move your install statements within the CMakeLists.txt files within your subdirectories.
This should solve the problem, if my thoughts were right. Otherwise, I strongly suggest you to post in your question also the content of the other files above mentioned.
Anyway, the error is quite clear.
The file that contains the install statement for the target named X does not contain a target creation statement (add_executable and the others) that gives birth to that target, so it goes on saying that that target does not exist in that directory.
This still seems to be a pain point in CMake 3.11.
In our codebase, we have many targets defined in subdirectories and need to create an assortment of installers with different configurations and (potentially overlapping) combinations of targets.
Here's my solution:
Before calling add_subdirectory in your root CMakeLists.txt file, create a GLOBAL property with the names of the target(s) you want to include in your installer.
Wrap target creation functions (add_executable, etc.) in your own custom functions. Within those functions check if the target is present in the global property, and invoke install accordingly.
That approach allows you to centralize installer configuration.
Also: To support creation of multiple installers, we populate our global list along with other installer properties in separate .cmake files. When we invoke cmake, we pass the name of the installer configuration CMake file as a command-line argument. Our root CMakeLists.txt file simply calls include with that file.

How do I specify the files I want CPack to pack into an RPM?

I'm making two rpms with CPack using its component feature. I want one to have .so files and the other to have all header files. I couldn't find any similar questions regarding packaging files in the component feature.
(DEVEL" is the component for my devel rpm)
Right now I have set(CPACK_RPM_DEVEL_INSTALL_FILES path/../file1
...
path/../file2)
just with all my files separated by returns but that does not work at all. What is the correct statement to provide a list of files I need in the rpm?
Currently it produces 3 rpms (I assume the third will just be a complete one with all files which I'm fine generating and not using). Two of the rpms have every file in the repo in them and the third just has two CMake files in it.
cpack_add_component(DEVEL)
//Skipping version, description, name, setting source_dir...
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
set(CPACK_COMPONENTS_GROUPING ONE_PER_GROUP)
set(CPACK_COMPONENT_DEVEL_DISPLAY_NAME "devel")
set(CPACK_RPM_DEVEL_INSTALL_FILES "/usr/include/opentracing/noop.h
...
/usr/include/opentracing/version.h")
set(CPACK_COMPONENT_DIST_REQUIRED TRUE)
set(CPACK_COMPONENT_DEVEL_REQUIRED TRUE)
set(CPACK_COMPONENTS_ALL DIST DEVEL)
I am calling this from linux command line with cpack -G rpm
In your CMakelists.txt, add something like:
install(TARGETS outputfiles... RUNTIME DESTINATION bin LIBRARY DESTINATION lib)
Then you can use
make package
in your build directory.

CMake does not compíle Qt5 generate from buildroot

I generate a tarball with Qt5 using Buildroot 2014.05.
When I uncompressed this files to compile my project using CMake I receive the following error message:
CMake Error at <project> /sysroot/usr/lib/cmake/Qt5Core/Qt5CoreConfig.cmake:27 (message):
The imported target "Qt5::Core" references the file
"<project>/host/usr/bin/qmake"
but this file does not exist. Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
"/<project>/sysroot/usr/lib/cmake/Qt5Core/Qt5CoreConfigExtras.cmake"
but not all the files it references.
I'm using the cmake configs under
<project>/sysroot/usr/lib/cmake/
and my CMakeLists.txt
set(CMAKE_PREFIX_PATH <project>/sysroot/usr/lib/cmake/QtWidgets/ )
find_package(Qt5Widgets REQUIRED)
Any suggestion?
Buildroot 2014.05 does not have qmake to install
This part: I generate a tarball with Qt5 using Buildroot does make much sense. What do you mean exactly by this ?
If by this you mean that you tarball'ed the contents of output/host/ (which is the toolchain and all the libraries that you need to build applications for your target), then beware that it is not relocatable. So it has to be installed in the same location as the one it was generated in. So for now, if you want to do this, you should set the BR2_HOST_DIR configuration option to something like /opt/<something>/, and then tarball that up and uncompress it on the other machines where you want to use the toolchain.
It's in our TODO-list to make this relocatable.

CPack doesn't include mfc100.dll

I thought this directive includes the necessary runtime libraries in my NSIS installer generated by CPack:
include(InstallRequiredSystemLibraries)
But it doesn't. When I install my application with this installer on another PC, it complains that mfc100.dll is missing - it isn't included in the installer. Trying to set MFC linking to static leads to a myriad of errors when compiling, so this isn't an option.
Can I manually figure out the path where I can get mfc100.dll from and copy it to the install directory in the CMake script, so that it will be included in the NSIS installer? Are there other options to include it?
The trick is to tell CPack to include them:
set(CMAKE_INSTALL_MFC_LIBRARIES ON)
include(InstallRequiredSystemLibraries)