Renaming cpack automatic target - cmake

When you INCLUDE(CPack) in a CMakeLists.txt file, it adds a target named package to the generated build files. You can configure a lot of things about that generated target and how it operates, but I can't seem to find a way to change the name of the target itself; i.e., instead of a generated Makefile containing a target named package, I'd like it to contain one named (for example) bundle instead. Is there any way to do this?

CMake only adds the default package target if a package config file named CPackConfig.cmake exists in the outermost binary build directory. By forcing the CPack module to generate the package file under a different name, you can prevent the package target from being created:
set (CPACK_OUTPUT_CONFIG_FILE "${CMAKE_BINARY_DIR}/BundleConfig.cmake")
include(CPack)
You can manually add a bundle target then:
add_custom_target(bundle
COMMAND "${CMAKE_CPACK_COMMAND}"
"-C" "$<CONFIGURATION>" "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake")
This is also true for the default package_source target. Use the variable CPACK_SOURCE_OUTPUT_CONFIG_FILE to override the default package configuration file name CPackSourceConfig.cmake.

Related

How to generate nuget package with specific file organization using cpack/cmake?

I generate two nuget package with cpack and cmake. My problem is to organize files in my package. I would like to put some files in specific folder.
Actually i have in my first package:
/_rels
/package
toto.nuspec
toto.dll
But i want to have toto.dll in /lib folder :
/_rels
/package
/lib/toto.dll
toto.nuspec
I tried to use:
set(CPACK_PACKAGING_INSTALL_PREFIX "/lib")
but i want different file organization for other packages.
Do you have an idea to do this for one specific package ?
Set the desired destination in the install(TARGET...) command instead. E.g.,
install(
TARGET toto DESTINATION lib
# Some other args may follow here, like `COMPONENT`...
)

catkin / ROS: How-to specify include path correctly when using submodules

I am building a project using ROS and thus, catkin_make to build my ROS nodes and libraries.
The problem I'm facing is:
I am using a git submodule in one package (package A) (and thus, I have a hierarchical include folder structure) and I have difficulties referencing a header file within that submodule.
In order to build the package B, which is dependent on package A, I have added the INCLUDE_DIRS statement to the catkin_package command in package A:
catkin_package(
INCLUDE_DIRS my-submodule/include
...
)
The content of that directory is:
my-submodule/my-header.h
(I have put the header files under a folder, named after the submodule, as many tutorials stated that within ROS you should use this convention).
The include statement in a file from package-B reads like this:
...
#include <my-submodule/my-header.h>
...
This works fine - package B is being built (as I am using one combined workspace to build this).
But: When I switch to the target system, where I only install package A, and then try to build package B (on that target system), it does not build because the include paths are not setup correctly.
The INSTALL statement for package A looks like this
install(DIRECTORY my-submodule/include
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
This is mainly, because the installed folder structure on the target system looks like this:
.../ros/include/my-package-A/include/my-submodule/my-header.h
So, the install process actually puts that submodule's include-path under the package-A-include path (which is a different path structure compared to when I build the packages directly in one combined workspace).
And the CFLAGS for compilation only set the include directory to the folder:
.../ros/include
And thus, breaking my include statement in my package-B file:
#include <my-submodule/my-header.h>
Do you have any idea how to solve this?
I am sure there are more people than me, trying to reference header files from a submodule within a package.
Assuming you have a file my-submodule/include/my-submodule/my-header.h inside your package A, then two small changes to your install() statement should fix this:
install(DIRECTORY my-submodule/include/
DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
First, add a slash to the path (.../include/ instead of .../include), which causes the contents of the include folder to be installed instead of the include folder itself (Otherwise you'll end up with ../ros/install/include/include/my-submodule/my-header.h)
Secondly, use ${CATKIN_GLOBAL_INCLUDE_DESTINATION} (which points to .../ros/install/include/) instead of ${CATKIN_PACKAGE_INCLUDE_DESTINATION} (which points to .../ros/install/my-package-A/include/) as destination.
The alternative would be to fix catkin, as
catkin_package(
INCLUDE_DIRS my-submodule/include
...
)
should theoretically already export my-submodule/include, so you can pick it up in package B with
find_package(catkin REQUIRED DEPENDS my-package-A)
catkin_package(
CATKIN_DEPENDS my-package-A
)
include_directories(${catkin_INCLUDE_DIRS})
Unfortunately, for some reason this is explicitely not possible when using catkin config --install. See https://answers.ros.org/question/335846/install_dirs-not-working-as-expected-when-using-install/.

CMake generated include directory

How to tell CMake that directory is generated so that it doesn't complain before building process that directory doesn't exist?
My library project is used by many clients and for every client I have client-specific configuration generated by scripts and placed into generated/[client-name]/generated.h header. So for every client there's is folder generated. But parent project source files (*.cpp) include just generated.h. I wanted to add generated/[client-name] interface include directory for my library by using:
set_target_properties(mylib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "generated/myclient" ...)
but CMake complains even before starting compilation - Imported target "xxx" includes non-existent path. So I guess CMake doesn't like that include directory is missing when it starts building process although target depends on other targets which should create correct directory & header file within it.
You can create the directory first with CMake:
file(MAKE_DIRECTORY "generated/myclient")
This will have no effect if the directory exists already.

CMake setting to Ninja rebuild when header change?

Apparently, Ninja has to be configured to treat headers as dependencies: https://ninja-build.org/manual.html#ref_headers.
How do I tell CMake to generate this into my build.ninja?
If I look into my build.ninja files generated with CMake for e.g. GCC I do have the necessary dependency file entries automatically generated (see DEP_FILE):
#=============================================================================
# Object build statements for EXECUTABLE target MyExe
build CMakeFiles/MyExe.dir/foo.cc.obj: CXX_COMPILER ../foo.cc
DEP_FILE = CMakeFiles/MyExe.dir/foo.cc.obj.d
FLAGS = -fdiagnostics-color=always -Wconversion
OBJECT_DIR = CMakeFiles\MyExe.dir
OBJECT_FILE_DIR = CMakeFiles\MyExe.dir
And the dependency checking works as expected. Just touch or change one of the header dependencies and ninja will automatically rebuild the necessary sources.
There is the file property OBJECT_DEPENDS, which can be used to specify the dependency on other files of any objects created from a specific file.
From the docs:
Additional files on which a compiled object file depends.
Specifies a ;-list of full-paths to files on which any object files compiled from this source file depend. On Makefile Generators and the Ninja generator an object file will be recompiled if any of the named files is newer than it. Visual Studio Generators and the Xcode generator cannot implement such compilation dependencies.
This property need not be used to specify the dependency of a source file on a generated header file that it includes. Although the property was originally introduced for this purpose, it is no longer necessary. If the generated header file is created by a custom command in the same target as the source file, the automatic dependency scanning process will recognize the dependency. If the generated header file is created by another target, an inter-target dependency should be created with the add_dependencies() command (if one does not already exist due to linking relationships).
To set this property on a given source file, use:
set_property(SOURCE first.cpp second.cpp
APPEND PROPERTY OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/inc/header1.h;${PROJECT_SOURCE_DIR}/inc/header2;${PROJECT_SOURCE_DIR}/inc/global_deps.h"

Running fixup_bundle for a specific target (PACKAGE)

I would like to incorporate external dlls when running CPACK without enumerating all of them (by explicitly calling INSTALL(FILE ...) )
Employing fixup_bundle it is possible to fixup all the executables in the install folder (CMAKE_INSTALL_PREFIX) by copying the required libraries.
INSTALL(CODE "
include(BundleUtilities)
fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")
" DESTINATION bin COMPONENT Runtime)
This code is executed when building the INSTALL target and will handle only elements present inside the folder CMAKE_INSTALL_PREFIX.
What I would like to do instead is to run fixup_bundle during the building of the PACKAGE target which is added by CPACK. in this way the install script generated will also include externa libraries.
Did anyone managed to do this?
The best solution I found so far do not rely on fixup_bundle but on listing all files that have to be installed for the runtime configuration (e.g. all dlls).
Given a target you can recover the associated runtime file and add it to the INSTALL project:
#get dll location
get_target_property(BIN_F ${target} LOCATION_${Configuration})
#copy to the bin folder
install(FILES ${BIN_F} DESTINATION ${destinationFolder}
CONFIGURATIONS ${Configuration}
COMPONENT Runtime)
You then can recurse over the target dependenices to perform the same two operations using
get_target_property(link_libs ${target} INTERFACE_LINK_LIBRARIES)