How to get debug postfix in executable name - cmake

I am using cmake 2.8.12.2. I have set CMAKE_DEBUG_POSTFIX, and it is automatically used with the add_library command. But it is not automatically used with add_executable command. I have discovered that I can set the DEBUG_POSTFIX target property to get a debug postfix into the executable name, but this requires using an additional command.
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
Is the second command explicitly setting the DEBUG_POSTFIX target property required or is there an easier way?

The current cmake documentation for set_target_properties states
There is also a <CONFIG>_OUTPUT_NAME that can set the output name on a per-configuration basis. <CONFIG>_POSTFIX sets a postfix for the real name of the target when it is built under the configuration named by (in upper-case, such as “DEBUG_POSTFIX”). The value of this property is initialized when the target is created to the value of the variable CMAKE_<CONFIG>_POSTFIX (except for executable targets because earlier CMake versions which did not use this variable for executables).
So it seems to highlight the fact that cmake does not use the value of CMAKE_DEBUG_POSTFIX in the name of executables. Therefore
add_executable(myexe ${SOURCE_FILES})
set_target_properties(myexe PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
will use the value of the global variable ${CMAKE_DEBUG_POSTFIX} when building the myexe target for the DEBUG configuration.
Note that one of the commenters to this question was confused by the use of the variable ${PROJECT_NAME}. This variable is automatically set to myexe when using project(myexe). Using ${PROJECT_NAME} is equivalent to myexe and it makes it easier to copy/paste to new CMakeLists.txt.

Just to mention that, if you have in your project many sub-executables, it is worth having a look on CMAKE_EXECUTABLE_SUFFIX. The variable in this case would need to be changed when running CMake for a specific build (Release/Debug), but this suffix is auto-attached to every ADD_EXECUTABLE(...)-call executable name. Tested and verified with CMake 2.8.12.2 and 3.0.2

Related

set PKG_CONFIG_PATH in cmake

I have built opencv locally and installed it to a local directory (not the system default ). opencv.pc is present under a folder pkgconfig in this local folder. How can I find this opencv.pc from cmake, because I want to link and include opencv files from my program.
pkg_search_module(<PREFIX> [REQUIRED] [QUIET] <MODULE> [<MODULE>]*)
does not have any parameter in which I can force the command to use a specific path (similar to HINTS with find_package()) and not the system default.
So basically .cmake works:
find_package(OpenCV REQUIRED HINTS "my/path/to/share/OpenCVConfig.cmake")
but I would like to use a opencv.pc located under my/path/to/pkgconfig/opencv.pc.
After doing some research and a hint from the #OlivierM, I found the answer.
Here are the steps:
Method I :
CMAKE_PREFIX_PATH can be set to find the .pc files
set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/libs/opencv-install")
Method II
A second method is to use the PKG_CONFIG_PATH, which is a system environment variable to look for .pc files.
set(ENV{PKG_CONFIG_PATH} "${CMAKE_SOURCE_DIR}/libs/opencv-install/lib/pkgconfig")
Irrespective of which method you use,
For old (traditional) CMake:
find_package(PkgConfig REQUIRED)
pkg_search_module(PKG_OPENCV REQUIRED opencv) # this looks for opencv.pc file
Please note that the PKG_OPENCV variable can be named anything. Whatever it is is named, its used as a prefix. For example if you name ABCD, then include directories will be ABCD_INCLUDE_DIRS
The variable PKG_OPENCV_INCLUDE_DIRS and PKG_OPENCV_LIBRARIES contains the header files (compile stage) and libraries (link stage) respectively.
One very important thing I noticed was that the variable PKG_OPENCV_LIBRARIES just provides the libraries and not the library path during the link stage. In order to use the library path as well in one command, one has to use
PKG_OPENCV_LDFLAGS
This variable contains the library path as well as all the libraries listed in the package config file.
for examaple:
include_directories(${PKG_OPENCV_INCLUDE_DIRS})
target_link_libraries (FINAL_BINARY ${PKG_OPENCV_LDFLAGS})
For modern CMake:
In modern CMake we don't want variables, we want targets.
find_package(PkgConfig REQUIRED)
# this looks for opencv.pc file and creates a new target
# IMPORTED_TARGET requires CMake >= 3.6.3
pkg_search_module(PKG_OPENCV REQUIRED IMPORTED_TARGET opencv)
All variables will still be created for backwards compatibility, but IMPORTED_TARGET will create a target you can use in your project which will automatically propagate all of its build and usage requirements:
target_link_libraries(my_proj PRIVATE PkgConfig::PKG_OPENCV)
You could set PKG_CONFIG_PATH with the CMake line:
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/my/path/to/pkgconfig")
I did this workaround in this file
Interestingly, it seems CMake 3.1 extends PKG_CONFIG_PATH with some CMake variable see: https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3df51470
I would propose you to call cmake with custom PKG_CONFIG_PATH variable, like below:
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:my/path/to/pkgconfig cmake <some args>
Or can make PKG_CONFIG_PATH update to be permanent for whole bash session:
$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:my/path/to/pkgconfig
$ cmake <some args>

Directing cmake to link against shared object with debug postfix (_d)

I've got a cmake project that pretty much looks like this:
cmake_minimum_required(VERSION 3.0)
SET(CMAKE_DEBUG_POSTFIX "_d")
include_directories(../TransfunctionerProject)
include_directories(../TransmogrifierProject)
set(Libraries
ContinuumTransfunctioner
Transmogrifier
)
set(SourceFiles
Wrapper.cpp
Logger.cpp
)
add_library(Frobnigator SHARED ${SourceFiles})
add_library(FrobnigatorStatic STATIC ${SourceFiles})
set_target_properties(FrobnigatorStatic PROPERTIES OUTPUT_NAME Frobnigator)
target_link_libraries(Frobnigator ${Libraries})
Where ContinuumTransfunctioner and Transmogrifier projects include the debug postfix directive SET(CMAKE_DEBUG_POSTFIX "_d") so that libContinuumTransfunctioner_d.so and libTransmogrifier_d.so both exist.
The problem is that the current project appears to be linking against the static library without the _d suffix and complains:
/usr/bin/ld: cannot find -lContinuumTransfunctioner
The Libraries that you pass into the target_link_libraries call are interpreted as filenames, not as target names.
This is the unfortunate fallback for that call in CMake: If you pass a random string to it, that cannot be interpreted in a meaningful way, CMake will always assume it to be plain library name. Sometimes this is just what you want, but the name has to be an exact match for an existing library. The whole debug postfix magic will be lost here.
What you might have wanted to do was to pass a library target name instead. This will trigger a much smarter handling of the dependency and would solve your problem. However, that only works if the library is a known target in the context of the target_link_libraries call. You can easily check this as follows:
if(TARGET ContinuumTransfunctioner)
message("Library target name")
else()
message("Plain library name")
endif()
target_link_libraries(Frobnigator ContinuumTransfunctioner)
So how do you get to the target name case? This depends on how your build is structured. If the library is being built as part of your CMake run, simply make sure that the corresponding add_library call is performed from a subdirectory that is pulled in via add_subdirectory from the file that performs the target_link_libraries call.
If the library in question is an external dependency, you need to build an imported target that carries all the relevant information where to find the library files (including any potential debug postfixes). This can be a bit cumbersome to do manually, so if you can, you might want to use CMake's packaging mechanism to generate this automatically as part of the library's build process.
Here's the solution, courtesy of the good people on the cmake mailing list:
# Note:
# $<$<CONFIG:Debug>:_d> is called a generator expression.
# It outputs _d if the build is debug.
#
set(Libraries
ContinuumTransfunctioner$<$<CONFIG:Debug>:_d>
Transmogrifier$<$<CONFIG:Debug>:_d>
)

CMake generated makefile does not expand all `make` variables

I have a projects that consists of modules that are built separately. Some modules use make only, others use cmake.
The top project has a makefile, which is used to trigger the build of the submodules. The makefile at the top defines make variables for pathes to libs, includes, and binaries. The submodules then use these variables.
My problem is that I cannot pass all these make variables to the projects that use cmake.
For the include directory, this work-around in CMakeLists.txt works:
INCLUDE_DIRECTORIES("/$(INCLUDE_DIR)")
The string is passed as is all the way to the generated makefile, and is then expanded by make upon building. The leading slash is needed. Without it, the content of INCLUDE_DIR gets prefixed by the cmake project root (it is then considered a relative path).
This solution does not work for linking:
LINK_DIRECTORIES("/$(LIB_DIR)")
The link command that I see upon building has the literal string -L/$(LIB_DIR). Removing the leading slash gives a warning about relative paths, and the link command has still the unexpanded $LIB_DIR.
How do I make sure that the expansion works for the make variable LIB_DIR passed though cmake to the generated makefile? Since it is make that runs the linker (I think?) I don't see why it wouldn't expand.
Is there another, less ugly solution, solution for fixing it for INCLUDE_DIR as well?
A backup solution is to let the top makefile define CMAKE variables. It should work fine, and is probably what I'll do if I can't make it work otherwise. But it would be nice to just define these variables once and make everything else take them into account.
One option is to use an environment variable to set a CMake variable. For example:
set (INCLUDE_DIR $ENV{INCLUDE_DIR})
then use the CMake variable like other CMake variables:
INCLUDE_DIRECTORIES(${INCLUDE_DIR})
If you want the variable to show up in cmake-gui or ccmake you can put it in the cache using the following:
set(INCLUDE_DIR $ENV{INCLUDE_DIR} CACHE PATH "An environment variable containing a path" FORCE)
for my projects I have wrapped the concept in a cmake function:
function( define_from_environment VariableName PackageName)
if (NOT DEFINED ${VariableName})
message( STATUS "${VariableName}=$ENV{${VariableName}}" )
if (NOT "$ENV{${VariableName}}" STREQUAL "")
set(${VariableName} $ENV{${VariableName}} CACHE PATH "Set the path variable ${VariableName} for ${PackageName}" FORCE)
endif (NOT "$ENV{${VariableName}}" STREQUAL "")
endif(NOT DEFINED ${VariableName})
endfunction( define_from_environment)
An example usage of this CMake function is
define_from_environment(GDCM_DIR GDCM)
which sets the CMake variable GDCM_DIR to a CMake cache variable if the environment variable GDCM_DIR is set.

Wrap cache variables of a library when configuring my code in CMake

I have to build a library that is using another library, how can I make variables of that another library not showing in the CMake-Gui and use instead values that are configured by my CMake script?
For example when my application is built for Mobile, I already have a flag for OpenGL ES, but the SDL "VIDEO_OPENGLES" variable still shows up in the GUI. The problem is that since my build script already have knowledge of what happens, it can happily pre-configure other scripts instead of polluting the Gui of the users that need to compile my code.
Also I want to know what happens if 2 libraries have by accident 2 variables with same name but used in a different fashion.
The key word is INTERNAL property of the variable. Take a look at this example:
Test/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
Project(Test)
add_subdirectory(Component1)
add_subdirectory(Component2)
Test/Component1/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.11)
project(Component1)
set(SOURCES test1.c)
set(Component1_CONF "SomeValue" CACHE STRING "Component1_CONF description")
message(STATUS "Component1_CONF=${Component1_CONF}")
add_library(Component1 ${SOURCES})
target_include_directories(
Component1 INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
)
Test/Component2/CMakeLists.txt:
project(Component2)
set(SOURCES test1.c)
set(Component2_CONF "/etc/passwd" CACHE FILEPATH "Component2_CONF description")
add_executable(Component2 ${SOURCES})
target_link_libraries(Component2 Component1)
Actually Component2 can be a library static or shared not an executable, it doesn't matter.
Now if you run cmake-gui on the top directory and run Configure you will see both Component1_CONF and Component2_CONF. But if you change the top-level CMakeLists.txt and add the line which forcibly sets Component1_CONF:
cmake_minimum_required(VERSION 2.8)
Project(Test)
set(Component1_CONF "Other value" CACHE INTERNAL "Component1_CONF forced value" FORCE)
add_subdirectory(Component1)
add_subdirectory(Component2)
you will effectively hide Component1_CONF from cmake-gui and even from command-line (-DComponent1_CONF=Boo) configuration.
Also you should note that usually variables are set only in the current scope (unless PARENT keyword is used). Thus variables set in some directory don't affect variables set in peer subirectories and the parent subdirectory. However if variables are set in the very same scope (say, when you run configuration tests from within the parent CMakeLists.txt) then yes, they could interfere one another. To prevent this CMake uses naming convention which explicitly separates variables from different packages. Most of configuration macros receives "prefix" parameter which specifies the name prefix for variables being set in the macros, so macro users (that is applications CMakeLists.txt) can explicitly separate test variables from different dependent packages.

Compile same file with different flags using CMAKE

I want to compile the same .cpp source file into two different target executables and I am using cmake. One will have some instrumentation code and the other won't. That way I can compare the overhead of instrumentation.
I have the instrumentation code separated with #ifdefs so I want to define a value using the -D flag. I see that is possible with
add_definitions(-DINSTRUMENT)
But it looks like this then applies to all the executables created in that directory. I'm wondering if there is a good way to set the definition only for a specific executable target.
You can set the COMPILE_DEFINITIONS property of one of the targets to have target-specific definitions:
set_target_properties (instrumented_target PROPERTIES COMPILE_DEFINITIONS "INSTRUMENT")
Update:
Starting from CMake 2.8.11 you can also use target_compile_definitions for the same purpose.