cmake: install executables and create links to them - cross-platform

I'm using cmake and cpack to build my project and build packages. I'm creating a few executables in my project, let's call them EXE1 and EXE2.
When creating different versions of these executables, I want to name to reflect the version of the executable (let's say EXE1_1.0.0). I can change the name of the output for a target by doing set_target_properties.
However, now when doing an install, I want to do create a symlink to this versioned name of the executable, i.e. I want to have
the "versioned" executable installed in bin directory, i.e. EXE1_1.0.0
create a symlink to the "versioned" executable, i.e. create symlink EXE1, which points to EXE1_1.0.0
Can someone suggest me how to do this?
Second question is:
How to install configuration files /etc/MYPROJECT/ directory? What DESTINATION I need to use for configuration files, like I use bin for executables and lib for libraries? Is using an absolute path like /etc an acceptable practice with cmake?

I asked this question on cmake mailing list subsequently, and this is the response I received:
The validity of the answer will depend on which CMake version you use
and which set of platform you want to support.
Symlinks are not that portable
a) Creation may not be [currently] done portably but if you are
targeting Unix you can use cmake -E create_symlink to create one.
b) Depending on the CPack generator you use and CMake/CPack version
symlinks may be embedded in the package or not.
i.e. CPack pre 2.8.7 cannot create ZIP archive which contains
symlinks CPack 2.8.8 can do that now.
Then you can use an install(SCRIPT ... or install(CODE ...) to do that
at install time.
Another option if you are using RPM is to use package specific post
install script. cpack --help-variable
CPACK_RPM_POST_INSTALL_SCRIPT_FILE
this last solution will off course only work for CPack RPM.
For second question
You can use absolute destination path, they should be handled just
fine by CPack DEB and RPM, I don't know for other.
If your software should be installed on Windows this is won't work
with archive generator (ZIP, TGZ, etc...) and/or NSIS.
May be you can do something like:
if(UNIX AND NOT APPLE) set(CONFDEST "/etc/${CMAKE_PROJECT_NAME}")
else() set(CONFDEST "etc") endif()
install(FILES yourconffile DESTINATION ${CONFDEST})

Related

How can I manage the installation directory with CMake when cross-compiling?

I am cross-compiling a C library using CMake and a toolchain file. My toolchain file sets CMAKE_SYSROOT to the appropriate value so compilation works with no issues. However, when installing, the library does not install to the directory pointed to by CMAKE_SYSROOT. I can achieve that effect by running make install DESTDIR=xxx though.
I understand that there are two separate concepts here:
The cross-compilation toolchain, which consists of binaries that can be run on my local architecture
The CMAKE_SYSROOT which is the root directory of a target-architecture filesystems, containing header files and libraries, passed to e.g. gcc through the --sysroot flag.
I have two questions:
Is it a good idea to conflate the sysroot where my cross-compilation toolchain lives, with the sysroot where all my cross-compiled libraries will be installed? It feels to me like it should be the same, but am not sure, and to CMake it appears they are distinct concepts. Update: answered in the comments below, these are indeed distinct concepts.
What is the modern CMake way to specify the installation directory when cross-compiling like described above? Update: I believe this should be the same as CMAKE_SYSROOT, and I feel CMake should offer a way to only define this once somewhere.
Thanks!
There is no interference between sysroot and install directory (prefix).
Sysroot is given by CMAKE_SYSROOT variable and denotes prefix for tools used during build process.
Install directory(prefix) is given by CMAKE_INSTALL_PREFIX variable and denotes the path, where the project will be used upon installation. E.g. with install prefix /usr/local the project's executable foo expects to be run as /usr/local/bin/foo.
Note, that with default installation procedure, CMake installs files to the host machine. For install files onto the target machine, this procedure is needed to be adjusted. Parameter DESTDIR=xxx for make install is a way for install files directly to the target machine. Another way is to create a package (e.g. with CPack) on host, and install that package on target machine.
Note, that in the above paragraph it is irrelevant, whether cross-compilation took a place or not: it is possible to build the project on one machine and install it to the other, but similar one, without any cross-compilation.

cmake: difference between "make install" and "make package"

I'm using CMake to generate my makefiles. My deployable target is an RPM, and that's all working well. Per the file system guidelines, my RPM installs to
/opt/mytool
/bin - executables
/lib64 - libraries
/etc/opt/mytool - configuration files
The RPM gets built by CPack using make package
During development testing, I don't want to install an RPM. It requires elevated privileges and limits any given machine to one (developer) version at a time. Before I got all the RPM stuff working, I was able to "make install" and create a simple install tree like this:
install
/opt/mytool
bin
lib64
However, the introduction of the config files to a different location has gummed up the works. I'd like this to be extended to include
install
/etc/opt/mytool
but I can live without it. Unfortunately, when I try make install I get this error:
Install the project...
-- Install configuration: "Debug"
CMake Error at cmake_install.cmake:49 (file):
file cannot create directory: /etc/opt/mytool. Maybe need administrative
privileges.
The offending part of the CMakeLists.txt file is
install(FILES ${PROJECT_SOURCE_DIR}/../Config/mytool.cfg
DESTINATION /etc/opt/mytool
)
I've looked at CMake rpm installing a file in /etc/init.d, but my RPM builds just fine (and I'm using CMake 3)
What is the difference between make install and make package (I can infer that the latter is running CPack, and it works just fine)? How can I create a development install tree
The difference between the two build targets is that package creates an RPM file in your case while install copies the resources given to the install() command to the location provided to the DESTINATION parameter:
DESTINATION
Specify the directory on disk to which a file will be
installed. If a full path (with a leading slash or drive letter) is
given it is used directly. If a relative path is given it is
interpreted relative to the value of the CMAKE_INSTALL_PREFIX
variable. The prefix can be relocated at install time using the
DESTDIR mechanism explained in the CMAKE_INSTALL_PREFIX variable
documentation.
You specified to copy files to /etc/opt/mytool for which you obviously have no write permissions and encounter the cited error.
You have two options to resolve this, the second one is clearly preferred, because it allows every developer to provide their own, system-local setting, where to temporarily install dev files:
set a DESTINATION path for which you have write permissions
set a relative path and call cmake with an additional argument to specify where your development install tree is:
cmake -H<source path> -B<build path> -DCMAKE_INSTALL_PREFIX=<install path>

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.

Why won't find_library find libgmp

I'm trying to build a cmake project, and the repo I have been given has the lines
find_library(gmp gmp)
if(NOT gmp)
message(FATAL_ERROR "gmp not found")
endif()
which cause CMake configuration to fail.
I have been told this CMake works on Redhat Enterprise Linux 7.3.
I have also been told this repo should build in any Linux environment with the correct libraries installed, and an Ubuntu environment has been specifically referenced.
I am building in Debian 9.4.0, I have installed gmp, libgmp.so is located at /usr/lib/x86_64-linux-gnu/openssl-1.0.2/engines/libgmp.so
and I also have a libgmp.so.10 at /usr/lib/x86_64-linux-gnu/libgmp.so.10.
So, to recap, I have been handed a repo I have been told builds, but it does not build, it fails at this specific step, and I can't get google to give me any relevant results on how to fix the issue/what I am doing wrong.
libgmp is installed, but the development libraries are not.
Cmake find_libraries looks for the files required for software development, and while the libgmp package is installed, the libgmp-dev package is not.
Install libgmp-dev.
CMake doesn't search "so-version" files:
If find_library is called for "gmp" library name, CMake searches libgmp.so file, but not libgmp.so.10 one.
Normally, the library file without so-version is just a soft link to the newest so-version file. If your Linux distro doesn't create such link, you may create it manually:
ln -s libgmp.so libgmp.so.10
If you want CMake to find /usr/lib/x86_64-linux-gnu/openssl-1.0.2/engines/libgmp.so file, which is not under directory normally searched by CMake, you need to hint CMake about it. E.g. with PATHS option:
find_library(gmp gmp PATHS "/usr/lib/x86_64-linux-gnu/openssl-1.0.2/engines")

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.