How can I package the installed files in CMAKE - cmake

I install some files into a folder with CMake Install command. Then I want to package the folder into a zip or tar. How can i do it in cmake. I mean thar after executing the make install I can also get the zip file
PS:
I have tried
install(CODE "execute_process(COMMAND tar -cf ${CMAKE_PROJECT_NAME}.tar ${CMAKE_PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})")
But the install order of CMake is undefined across different directories

You can use cpack. The easiest way just include(CPack) into your root CMakeLists.txt, then make package would be available. Default formats exactly what you asked (.zip for Windows, various .tar for *NIX). To make other packages (RPM, DEB, MSI, EXE) you better to get familiar with documentation.

Since you the install order is undefined across the directories,you can try stating the dependency explicitly or make a list of all directories to be installed and use it in DEPENDS of your custom command which will install the package. cmake -P cmake_install.cmake will install the files to your directory.
add_custom_command(
OUTPUT ${tar_package}
DEPENDS ${deps}
# Install in a temporary dir
COMMAND cmake
-DCOMPONENT=${component}
-DCMAKE_INSTALL_PREFIX=${install_dir}
-P ${CMAKE_BINARY_DIR}/cmake_install.cmake
# make tar or whatever you want
COMMAND tar -czf
${tar_package}
-C ${install_dir} .
)

Related

Build in a linux container fails to find gtest (using vcpkg and CMake)

I've tried build a project in a container and have some very (simple?) problem.
I have a couple of unit tests that use gtest and chose to use vcpkg to build it since I aim to target windows/linux machines.
When I build on my or someone else's computer everything seem to work, but when I build the project in the container it fails to find the include files for gtest.
Is there anything I missed in the CMake integration with vcpkg that needs to be done for my project?
My current state is that I start the container and use an interactive shell to manually build everything inside it (so I can try debug the issue).
Here is my Dockerfile:
FROM ubuntu:20.04
# Needed to be set for the cmake package to be installed properly without interactive input
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install git -y
RUN apt-get install gcc-10 -y
RUN apt-get install g++-10 -y
# Set gcc/g++ so they default to the installed versions
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 1
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 1
RUN apt-get install cmake -y
# zip / pkg-config were required for vcpkg to build some dependencies
RUN apt-get install zip -y
RUN apt-get install pkg-config -y
# below are convenience for opening a shell terminal in the docker image
RUN apt-get install vim -y
RUN apt-get install curl -y
# enables tab-completion and some colors
RUN curl -L https://raw.githubusercontent.com/docker/compose/1.29.2/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
# copy local files to be built
COPY scripts /build/scripts
COPY src /build/src
COPY CMakeLists.txt /build
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg)
message( FATAL_ERROR
"Clone vcpkg at ${CMAKE_CURRENT_SOURCE_DIR}\n"
"cd ${CMAKE_CURRENT_SOURCE_DIR}\n"
"git clone https://github.com/Microsoft/vcpkg.git --depth 1\n"
"cd vcpkg\n"
"./bootstrap-vcpkg.sh"
"./vcpkg install gtest:x64-linux"
)
endif()
if (WIN32)
set(CMAKE_GENERATOR_PLATFORM x64) # Force 64 bits
elseif (LINUX)
set(VCPKG_TARGET_TRIPLET "x64-linux")
endif()
# Setup vcpkg toolchain
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "Vcpkg toolchain")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/runtime)
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
project(TheProject)
find_package(GTest CONFIG REQUIRED)
include_directories(
"src/cpp"
)
add_subdirectory(src)
EDIT: If I hardcode the include paths / library paths to point to the vcpkg installed directory in the CMakeLists.txt everything works, but I thought it should only be necessary to setup the toolchain file for it to work.
The unmodified toolchain-integration works like a charm outside any container (on a computer).
How can I avoid this hack? It will not scale at all later on.
Below is the hack that make everything work (not needed on a computer):
include_directories(
"src/cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/installed/x64-linux/include"
)
link_directories(
"${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/installed/x64-linux/lib"
)

How to install cmake-gui latest version on Ubuntu

When installing from package-manager, cmake-gui or cmake-qt-gui are shipped with an older version of cmake.
Even after I build and install cmake's latest version from source, cmake-gui continues to use the older version.
How to force cmake-gui to use cmake latest version builded from source?
The cmake-gui package from repository has a built-in cmake, those two have the same version.
Steps to install cmake-gui latest version.
Install checkinstall to easily remove cmake in the future: sudo apt-get install checkinstall;
Download latest cmake from official site;
Extract the compressed file to some folder;
Open a terminal inside that folder;
Execute: ./bootstrap --qt-gui;
Execute: checkinstall -D make install; You will be prompted with some questions, answer them;
Finished installation! Type cmake at Ubuntu's search bar and you will see a CMake icon;
Verify the version clicking at help >> about;
An alternative to the above.
Check if you have an old version of cmake with cmake --version. If so, remove it with sudo apt-get purge cmake
Download latest cmake from official site
Extract the downloaded cmake-x.xx.x file to your Desktop and then open a terminal inside that file.
Execute: ./bootstrap --qt-gui
After finished, run gmake as prompted.
Move cmake-x.xx.x file to /opt/ directory by going up to your Desktop with the terminal and then running sudo mv cmake-x.xx.x /opt/
Declare cmake binary as global by writing export PATH=/opt/cmake-x.xx.x/bin:$PATH in your ~.bashrc file.
Source with source .bashrc
You will then be able to open cmake or cmake-gui with your terminal from any path in your computer.

How to build RPM for fedora/RH and DEB for debian/ubuntu with cpack on one machine

I want to generate .deb and .rpm packages from multiple CMake C++ projects with CPack.
This works, if i build .deb packages on debian and .rpm packages on Fedora. But if i build them cross-distro, they get the paths wrong.
Have a look at one of my libraries where i tried to set this up: https://github.com/tfc/pprintpp
My workflow is:
cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr <src>
make
cpack -G DEB/RPM
The package contains:
headers
pkg-config file
cmake config file
When pkg-config and cmake are installed, they usually come with tools-specific search paths that are set distro-specific
If i use DEB on Fedora, the package installs libraries and pkgconfig/cmake files in /usr/lib64/... whereas cmake and pkg-config are configured to expect them in /usr/lib/<pkgconfig/cmake>.
If i use RPM on Debian, the package installs them in /usr/lib/... which is where Fedora doesn't look for them.
I need some way to generate such packages from one single distro, ideally even any distro.
Is there a way to instruct CMake and/or CPack to "do it right" without hardcoding too many things into my cmake files or calls?

Create a shared library for dlib

Following the instructions to compile dlib using cmake (here) generates a static dlib library:
cd examples
mkdir build
cd build
cmake ..
cmake --build . --config Release
How can I instruct cmake to generate a shared (.so) library instead?
If you want to make a .so file then do this:
cd dclib/dlib
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=1 ..
make
sudo make install
On a unix system, that will install dlib system wide. This means installing the .so file and also the header files so you can compile programs with a command like g++ main.cpp -ldlib. Finally, on linux systems you will also need to run sudo ldconfig after installing any new shared libraries.
However, for most users, I would recommend using CMake as shown in the examples. That way would allow you to enable or disable debugging modes whenever you want and also makes distributing the project easier, both in source form and compiled form. For example, if you wanted to compile on windows then shared libraries are definitely not the way to go. Moreover, using CMake as shown in the examples will always work in a straightforward manner without any setup.
According to dlib/CMakeLists.txt, standalone (not from examples) building of dlib also creates shared library named dlib-shared:
mkdir shared_build # Build directory can be any
cd shared_build
cmake ..
cmake --build . --config Release
make install # Install library for make it acessible for others
For use this library in examples, you need to add definition of dlib library into your examples/CMakeLists.txt before include(../dlib/cmake).
examples/CMakeLists.txt:
...
PROJECT(examples)
add_library(dlib SHARED IMPORTED) # Imported(!) dlib target
set_target_properties(dlib PROPERTIES IMPORTED_LOCATION "<full path to the installed dlib-shared library file>")
# Now it is safe to include other dlib infrustucture - it won't build dlib again.
include(../dlib/cmake)
...

CMake missing modules directory

I've installed CMake 2.8.11.2 package from CMake's website for Mac 64-bit. We recently upgraded a project from Qt 4 to Qt 5 and the CMake upgrade is mandatory for CMake to use Qt 5. However, when I type cmake . I get the following error:
CMake Error: Could not find CMAKE_ROOT !!!
CMake has most likely not been installed correctly.
Modules directory not found in
/Applications/CMake 2.8-11.app/Contents/bin
CMake Error: Error executing cmake::LoadCache(). Aborting.
I can confirm, there is no modules directory in the bin folder. I really don't know how to resolve this error, or how to get the modules needed.
Do hash -r to clear the cache, then do cmake --version.
It should work.
I had the same problem after upgrading on Ubuntu.
Removing cmake and the cmake-data package before performing the update solved it for me.
sudo apt-get remove cmake cmake-data
Now perform the update via
sudo -E add-apt-repository -y ppa:george-edison55/cmake-3.x
sudo -E apt-get update
sudo apt-get install cmake
This worked for me :
cd cmake-3.4.3
./bootstrap --prefix=/usr
make
sudo make install
Additionally, you may encounter the same error when running CMake from Cygwin. This may be caused by a PATH variable listing /bin before /usr/bin: in this case CMake is launched as /bin/cmake instead of /usr/bin/cmake, and trying to load modules from //share/cmake-X.Y.Z (which is a UNC path on Windows) instead of /usr/share/cmake-X.Y.Z.
Explicitly export'ing a correct CMAKE_ROOT isn't helpful, and cmake keeps displaying the same misleading message.
The issue can be solved by setting PATH to /usr/bin:/bin:/everything/else in your .bash_profile.
I was able to fix this error on Linux (for other who may be searching for answer on Linux) while trying to upgrade cmake 2.8.11 to 2.8.12 by exporting the CMAKE_ROOT environment variable like so:
export CMAKE_ROOT=/path_to_install/cmake-2.8.12.2-Linux-i386/share/cmake-2.8
The share directory should be on the same level as your bin directory.
I got the same error message upgrading cmake-3.5.1 to cmake-3.7.1 on Ubuntu 16.04.01 LTS. I just updated the repositories with
sudo apt-get update
Then
cmake --version
brought up the correct and upgraded cmake version and the error messages was gone.
In my opinion/case this is a developer "problem". I suspect this occurs mostly to new developers so I go a bit deeper to put it in the right perspective:
To "not mess with" the original system files used for daily work and separate the new compiled and volatile programs in a separate location it is common to not just change but add/mount a complete folder structure similar to the original OS folder structure in a special "development" location.
So more or less a mirrored folder structure of the original one but connected/linked to the original resources.
There for we need to add an environment variable to our user bash profile where we tell the system: "link our development folders to the following direction/dir."
On Arch Linux this is done in a file in ~/.bashrc - that is linked/forwarded in/by the ~/.bash_profile ("~" stands for /home/your user name/) and MacOS/Unix will be similar.
To do that there are 2 ways:
you can open the .bashrc file and add your environment path to the bottom of it
or
you can use "export" to put the environment variables to the right place in your user bash file.
for kde development e.g. you need to add a path at the end of the ~/.bashrc file like so:
# Adding the kdesrc-build directory to the path
export PATH="$HOME/kde/src/kdesrc-build:$PATH"
what basically tells the system: the development is done in the /home/user name/kde/src folder - there are your files. You can choose where you want to locate your development environment.
If you execute cmake it "thinks" your files are in the original OS folder and the "Could not find CMAKE_ROOT" - message will disappear because it finds all your files since properly linked from your development folder structure to your system folder structure.
So basically to solve the problem you could just execute cmake in the right system folder - it just could mess up your system if the program or make files are not proper done so it is pulled to the home folder development folder structure. And you just have to tell that cmake, so it can find all needed files to compile your stuff, including the CMAKE_ROOT.
Another problem could be that cmake isn't properly installed.
On Arch Linux systems that can be made sure by using the "sudo pacman -Syu cmake" command and it copies the files in the right direction and sets the right user variables to get it executed and reinstall cmake if necessary.
Btw, if you are on other systems like Debian make sure to use a Debian apt repository, it can differ from the Ubuntu repository, especially if you compile for the chosen system.
I tried to write a general "beginners in mind" overview to get em a fundamental picture. Executing cmake in the right folder solved that exact problem for me that was asked for.
(Actual that flags works for the actual cmake version from the official arch repository:
1:
cd /home/ivanovic/kde/src/program_name
than:
2:
cmake -S/home/ivanovic/kde/src/program_name -B/home/ivanovic/kde/build/program_name -DCMAKE_INSTALL_PREFIX=/home/ivanovic/kde/usr -DCMAKE_BUILD_TYPE=Debug
Pay attention that between -S and /home/... is no space, same at -B and /home/...
This worked fine for my kde system software builds.
)
If anyone gets the following error:
Modules directory not found in
/usr/share/cmake-3.20
cmake version 3.20.2
Solution which worked for me:
sudo cp -r /share/cmake-3.20 /usr/share/
The above command copies the cmake-3.20 directory from /share to /usr/share
This also happened to me on a fresh install of Ubuntu 21.04 and was fixed by installing it from "snap":
sudo snap install cmake --classic
(and then making sure that /snap/bin is in $PATH)
tl;dr: check the permission of folder /usr/local/share/cmake-x.xx.
I had a similar problem with the cmake that I build from source code. I compile the code with the following command.
./configure
make
sudo make install
and the binary files were placed into /usr/local/bin as expected. But I will encounter the same problem when executing cmake without sudo privilege. This is because the normal user don't have reading permission with folder /usr/local/share/cmake-3.xx.
The error went away when I give myself the permission to read/execute, with the command.
sudo chmod 755 /usr/local/share/cmake-3.xx
(xx will be the specific version that you installed.)