Remove Catkin artifacts from CPack build - cmake

I am trying to build a Debian package using CPack from a catkin workspace.
This project uses ROS in some part of the implementation.
The package gets build, but the problem I'm having is that ROS adds some files to the .deb.
.catkin
local/.rosinstall
local/env.sh
local/setup.{sh,bash,zsh}
local/_setup_util.py
I'm thinking there's got to be a way to either ignore those files from installing, or simply remove them from the .deb output, but I can't seem to find any option for it.
The CMake configuration looks like this:
INSTALL(TARGETS ${PROJECT_NAME}_node DESTINATION bin)
INSTALL(FILES doc/${PROJECT_NAME}.yaml DESTINATION share)
INSTALL(FILES doc/${PROJECT_NAME}.service DESTINATION lib/systemd/system)
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Maintainer")
SET(CPACK_GENERATOR "DEB")

I asked the question in answer.ros as well. Short answer: add -DCATKIN_BUILD_BINARY_PACKAGE=1 to catkin_make.
or SET(CATKIN_BUILD_BINARY_PACKAGE true) in CMakeLists.txt

Related

Flatpak specific commands in CMake

I try to create a Flatpak package for my application, that is called AppName afterwards. Its uses CMake/make for configuration and compilation.
When I compile normally my application (without using Flatpak), it uses a configuration file that has to be placed in the $HOME/.local/share/AppName/config folder.
I place this file in this folder using this CMake command
install(FILES ${PROJECT_SOURCE_DIR}/config/config.ini DESTINATION $ENV{HOME}/.local/share/AppName)
It works well. Now, when when I create the Flatpak package, it looks for the configuration file in $HOME/.var/app/org.flatpak.AppName/data/AppName/config.ini"
How could I design my CMakeLists.txt so that it uses $ENV{HOME}/.local/share/AppName when I do not use Flatpak and $HOME/.var/app/org.flatpak.AppName/data/AppName when I create a Flatpak package?
In short, I am looking for a CMake snippet like
if(FLATPAK)
install(FILES ${PROJECT_SOURCE_DIR}/config/config.ini DESTINATION $ENV{HOME}/.var/app/org.flatpak.AppName/data/AppName)
else()
install(FILES ${PROJECT_SOURCE_DIR}/config/config.ini DESTINATION $ENV{HOME}/.local/share/AppName)
endif()

Setting CMAKE_INSTALL_PREFIX from CMakeLists.txt file

How do I set CMAKE_INSTALL_PREFIX in my root CMakeLists.txt file?
I have been doing
cmake_minimum_required(VERSION 2.8)
project(MyProject)
# Set default install prefix
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR})
with the hopes that by installations would be destined to folders in the source tree. That is,
install(TARGETS my_exe DESTINATION bin/)
would install to ${CMAKE_SOURCE_DIR}/bin/. Instead, it keeps trying to write to /usr/local/bin (the default for Ubuntu 14.04).
I tried the answers to this question, but I still get the standard usr/local/ as my CMAKE_INSTALL_PREFIX when I check CMakeCache.txt.
The only working solution I have is to do
install(TARGETS my_exe DESTINATION "${CMAKE_SOURCE_DIR}/bin/")
but this then removes the user's ability to specify where the bin directory to install is.
tl;dr I would like make install to automatically install to ${CMAKE_SOURCE_DIR} by default, rather than /usr/local/.
CMake developers suggest to use given pattern for change default value of CMAKE_INSTALL_PREFIX inside CMakeLists.txt:
# Use this snippet *after* PROJECT(xxx):
IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
SET(CMAKE_INSTALL_PREFIX <path> CACHE PATH <comment> FORCE)
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
Using that approach
# Use this snippet *before* PROJECT(xxx):
SET(CMAKE_INSTALL_PREFIX <path> CACHE PATH <comment>)
is not recommended:
.. solution depends on the implementation details of the PROJECT command and is very fragile since it works "accidentally" for some versions of CMake. I don't consider it to be an option at all.

CMake subdirectory install/uninstall targets

I've got a project with two subdirectory projects (added with add_subdirectory), each with their own libraries, binaries and install/uninstall targets. So:
main_project
|
|--CMakeLists.txt
|--src/
|--CMakeLists.txt (with binary target, install()
|
|--project_a
|--CMakeLists.txt
|--src/
|--CMakeLists.txt (with library, install())
|
|--project_b
|--CMakeLists.txt
|--src/
|--CMakeLists.txt (with library, install())
I'd like for the top-level project (main_project) to automatically install the libraries a and b (included in main_project from target_link_libraries()). So, I'd like to be able to go:
cd main_project/build
cmake ..
make
sudo make install
and have the main_project binary and project_a/b libraries installed automatically. I've tried this:
main_project/src/CMakeLists.txt
...
install(FILES main project_a project_b DESTINATION bin
LIBRARY DESTINATION lib)
but a cmake .. results in
install TARGETS given target "project_a" which does not exist in this directory.
as expected.
I've also tried specifying a path:
main_project/src/CMakeLists.txt
...
install(FILES main ${CMAKE_SOURCE_DIR}/project_a/ ${CMAKE_SOURCE_DIR}/project_b DESTINATION bin
LIBRARY DESTINATION lib)
which also complains that project_a/b are not in this directory (also expected, I guess?)
I've also tried installing the libraries "manually" with the FILES option in install(), and that works just fine, but that seems very kludgy considering there are perfectly good install()s in the subprojects.
One additional issue: since project_a and project_b also have uninstall() custom targets, I can't add an uninstall target to the main_project without CMake complaining about the custom target already existing. When I try adding an uninstall directive to the top dir CMakeLists:
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
But, since my project_a has an uninstall directive, I get:
CMake Error at CMakeLists.txt:37 (add_custom_target):
add_custom_target cannot create target "uninstall" because another
target with the same name already exists. The existing target is a
custom target created in source directory "/main_project/project_a".
See documentation for policy CMP0002 for more details.
So, how do I install and uninstall the necessary library files from my subproject alongside my main_project?
I found the problem. I am adding the subdirectory I want to install with EXCLUDE_FROM_ALL such that it doesn't build everything in the subdirectory, only the library I need. That flag seems to prevent the subdirectory install() from happening. Perhaps ExternalProject_Add is indeed the best way to go here...
Also, RE overriding custom targets, this worked for me: http://public.kitware.com/pipermail/cmake/2011-July/045269.html

Create CMake/CPack <Library>Config.cmake for shared library

I have the simplest possible c-library which builds and is packed using the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project (libfoo C)
add_library(foo SHARED impl.c)
target_link_libraries(foo)
install(TARGETS foo LIBRARY DESTINATION lib/)
install(FILES public_header.h DESTINATION include/libfoo)
set(CPACK_GENERATOR "TGZ")
include(CPack)
Working example is located here: https://github.com/bjarkef/cmake-simple/tree/master/libfoo
I execute mkdir -p build; (cd build/; cmake ../; make all package;) to build a .tar.gz package with the compiled shared library along with its public header file. This is all working fine.
Now I wish to modify the CMakeLists.txt to create the FooConfig.cmake and FooConfigVersion.cmake files needed for CMake find_package in a different project to find the foo library. How do I do this?
I have discovered I should used the CMakePackageConfigHelpers: configure_package_config_file and write_basic_package_version_file, and I should create a FooLibraryConfig.cmake.in file. However I cannot figure out how to put it all together.
Note that it is important the the resulting .cmake files only contains relative paths.
I have cmake module included in the top level CmakeList.txt:
# Generate and install package config files
include(PackageConfigInstall)
Within the generic PackageConfigInstall.cmake file, the config files are created from the cmake.in files, and installed. This module can be reused for other packages.
include(CMakePackageConfigHelpers)
# Generate package config cmake files
set(${PACKAGE_NAME}_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}${PACKAGE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX})
configure_package_config_file(${PACKAGE_NAME}-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_DIR}/${PACKAGE_NAME}
PATH_VARS LIB_INSTALL_DIR INCLUDE_INSTALL_DIR APP_INCLUDE_INSTALL_DIR )
configure_file(${PACKAGE_NAME}-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake #ONLY)
# Install package config cmake files
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake
DESTINATION
${CMAKE_INSTALL_DIR}/${PACKAGE_NAME}
COMPONENT
devel
)
You'll need a package file for your library, such as your_lib-config.cmake.in, which will become your_lib-config.cmake. This will contain the include and library variables that can be used.
get_filename_component(YOUR_LIB_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
# flag required by CMakePackageConfigHelpers
#PACKAGE_INIT#
set_and_check(YOUR_LIB_INCLUDE_DIR #PACKAGE_YOUR_LIB_INCLUDE_INSTALL_DIR#/hal)
set_and_check(YOUR_LIB_LIBRARY #PACKAGE_LIB_INSTALL_DIR#/#CMAKE_STATIC_LIBRARY_PREFIX##PROJECT_NAME_LIB##CMAKE_STATIC_LIBRARY_SUFFIX#)
set_and_check(YOUR_LIB_LIBRARIES #PACKAGE_LIB_INSTALL_DIR#/#CMAKE_STATIC_LIBRARY_PREFIX##PROJECT_NAME_LIB##CMAKE_STATIC_LIBRARY_SUFFIX#)
You'll also want a config-version.cmake.in file like this:
set(PACKAGE_VERSION #PACKAGE_VERSION#)
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
There's quite a bit to the packaging scripts to get it all to work just right. I went through a lot of trial and error to finally get something that works on different targets (both linux server and embedded target). I might have left something out, so please just comment and I'll update answer.

cpack component level install

For the example CMakeLists.txt attached to CMake wiki. I also added below what is the actual make command to create just the component based TGZ. I am confused and not seeing any help in the documents.
CMakeLists.txt
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
project(MyLib)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Install path prefix prepended on to install directories." FORCE)
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CPACK_PACKAGE_NAME "MyLib")
set(CPACK_PACKAGE_VENDOR "CMake.org")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyLib - CPack Component Installation Example")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_VERSION_MAJOR "1")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example")
add_library(mylib mylib.cpp)
add_executable(mylibapp mylibapp.cpp)
target_link_libraries(mylibapp mylib)
install(TARGETS mylib
ARCHIVE
DESTINATION lib
COMPONENT libraries)
install(TARGETS mylibapp
RUNTIME
DESTINATION bin
COMPONENT applications)
install(FILES mylib.h
DESTINATION include
COMPONENT headers)
set(CPACK_COMPONENTS_ALL applications libraries headers)
set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "MyLib Application")
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
"An extremely useful application that makes use of MyLib")
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
"Static libraries used to build programs with MyLib")
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with MyLib")
set(CPACK_GENERATOR "TGZ")
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_SET_DESTDIR ON)
set(CPACK_PACKAGE_CONTACT "jhf")
# This must always be last!
include(CPack)
I have a similar CMakeLists.txt and when I do make package, I end up getting all my binaries and libraries in the TGZ. What should the make package command be if I need just a TGZ with application component from the above CMakeLists.txt?
It is simple.
Just set the CMAKE variable CPACK_COMPONENTS_ALL to the list of components you want to appear in the installation:
SET(CPACK_COMPONENTS_ALL applications) #only pack "applications" component
Take a look at CPackComponent.
I have exactly the same question with you.
I'm a beginner to cmake, and today I've try a whole day on this, just now I noticed a cmake module named CPackComponent which begins appeared in cmake 2.8.5 standard modules.
For now, I haven't made sure whether it is the reason yet. But the variables in the documents listed by you can be found in this module.
cmake 2.8.5 is the earliest version contained CPackComponent in its standard modules.
Have a check at http://www.cmake.org/cmake/help/v2.8.5/cmake.html#module:CPackComponent
And cmake 2.8.8 is the earliest version listed the variables you want. e.g. CPACK_COMPONENTS_ALL
Over here http://www.cmake.org/cmake/help/v2.8.8/cmake.html#module:CPackComponent
I'm sorry I'm a newbie too, could not help you any more.