port a variable form make to Cmake - c++

Our Library uses Cmake while the Overall system uses Make file for build.
I want to port the value of a variable (preprocessor macro) defined in the makefile to Cmakefile and use it as preprocessor marco in source codes of my library.
How to do that?

You can define variable at CMake invocation like so:
cmake -DMY_VAR=ON <path_to_CMakeLists.txt>
Then later in your CMake file:
if (MY_VAR)
add_definitions(-DENABLE_MY_VAR)
endif()
And finally in your code:
#ifdef ENABLE_MY_VAR
// Your code
#endif

Related

Is there a cmake compile feature for c++17's charconv?

I have written some code that make use c++17's charconv, that I can compile just fine with g++ 9. Even though I have set the std to c++17 in my CMakeLists.txt, cmake insists on using c++ 7.5, which does not support charconv.
How do I tell cmake that I need a compiler that supports charconv ?
I see no switch in CMAKE_CXX_KNOWN_FEATURES.
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
file(GLOB CLIENT_SRC "srcs/*.cpp")
include_directories("includes")
add_executable(client ${CLIENT_SRC})
set_target_properties(client PROPERTIES OUTPUT_NAME "distff-client")
target_compile_features(client PUBLIC cxx_std_17 )
Not a cmake guy... and I don't really understand cmake's approach to compile features here. But in C++ in general, we now use feature-test macros to detect the presence of features. You're looking specifically for __cpp_lib_to_chars.
I think you want to require compilation of this program:
#if __has_include(<version>)
# include <version>
#elif __has_include(<charconv>)
# include <charconv>
#else
# error "neither <version> nor <charconv> available to test"
#endif
#ifndef __cpp_lib_to_chars
# error "tochars not implemented"
#endif
Which can probably be generalized to something you can configure_file() for an arbitrary library feature (just pull out the header name and the macro name, and probably also check for the macro having the minimum required value).
Either way, if you try_compile() the resultant source file, you could probably get the behavior you want?
Not a CMAKE expert, but the easiest would be to set the CXX environment variable. Like so:
export CXX="/usr/bin/x86_64-linux-gnu-g++-9"
see more at How to specify a compiler in CMake?

How to handle not finding OpenCV in source code

I have built a C++ library that depends on OpenCV. However, sometimes I don't need to use OpenCV, and I compile the code without it.
The idea is, when the OpenCV_Found variable in CMake is true, there would be a pre-processor variable similar to the OpenCV_Found variable, but in the C++ code. In other words, I want to do something like this:
#ifdef OpenCV_Found
#include <opencv2/core/core.hpp>
#endif
My question is:
Does OpenCV provide a similar variable like that? Or do I have to define it manually, and send it to the target compilation flags?
You can use CMake to forward the OpenCV_Found CMake definition to your C++ source code. You can use a generator expression in target_compile_definitions() like this:
add_executable(MyExe ${MY_SOURCES})
target_compile_definitions(MyExe PUBLIC $<$<BOOL:${OpenCV_Found}>:OpenCV_Found>)
This will add OpenCV_Found as a pre-processor definition to the MyExe target when the ${OpenCV_Found} CMake variable evaluates to True. When the CMake variable ${OpenCV_Found} evaluates to False (case-insensitive equal of 0, FALSE, OFF, N, NO, IGNORE, or NOTFOUND), the OpenCV_Found pre-processor definition is omitted.

CMake: Set different name for #cmakedefine variable

I know you can use CMake's configure_file to make CMake variables available to your program. For example, I can use
#define ${CMAKE_BUILD_TYPE}
resulting in
#define Release
However, to keep my code more readible, I would prefer to define
#define BUILD_TYPE_RELEASE
Is there a simple way to achieve this?
Here is a fairly simple way to solve it:
In CMakesLists.txt:
if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE Release)
endif (NOT CMAKE_BUILD_TYPE)
string (TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE_NAME)
configure_file (config.h.in config.h)
And in config.h.in:
#define BUILD_TYPE_${BUILD_TYPE_NAME}
I am, however, still curious if there is a more elegant solution.
This is more a question of your preferred programming style (configuration files vs. compiler definitions).
In your case I would use add_definitions() or directly modify/append COMPILE_DEFINITIONS directory property (using generator expressions also supports multi-configuration environments):
set_property(
DIRECTORY
APPEND
PROPERTY
COMPILE_DEFINITIONS "BUILD_TYPE_$<UPPER_CASE:$<CONFIG>>"
)
Most simplified Debug/Release Check
You can also check what compiler definitions CMake does pre-define. Without having to modify/add something to your CMakeLists.txt files you could simply check for NDEBUG definition (set for Release builds across platforms) in you C/C++ code:
#ifdef NDEBUG
...
#endif
References
CMake: How to pass preprocessor macros
How to check if a CMake build directory build type is Debug or Release?
What predefined macro can be used to detect debug build with clang?

Is it possible to replace certain symbol to different symbol with CMake?

I'm trying to make an executable with CMake.
This executable requires full path to file which is located in the project.
int main()
{
std::ifstream("fullpath_to_file");
//....
}
I think if CMake can replace certain symbols in source code with user specified string, there will be no need of hard-coding fullpath.
For example, if CMake can replace ${CMAKE_PROJECT_DIR} in source code(cpp) into a cmake's variable like ${PROJECT_SOURCE_DIR}, then I would be able to write source like this.
int main()
{
std::ifstream("${CMAKE_PROJECT_DIR}/input/my_input.txt");
//....
}
Is there any way to do this?
Thanks.
A good way to expose as many CMake variables to you source files as you want is creating a configuration header to your project. First, create a template to the header, call it say config.h.in and define the symbols you want CMake to set at build time, for exemple the contents of config.h.in your case can be
#ifndef __CONFIG_H__
#define __CONFIG_H__
#define PROJECT_DIR #CMAKE_PROJECT_DIR#
#endif
then add to your CMakeLists.txt an instruction to change this configuration header and replace the value between the #'s with the value of the corresponding cmake variable. For instance, put the following in CMakeLists.txt:
include_directories(${CMAKE_BINARY_DIR})
config_file(
${CMAKE_SOURCE_DIR}/config.h.in
${CMAKE_BINARY_DIR}/config.h
)
Then CMake will create config.h with the definitions for the values you want to acces from your sources. Now all you have to do is: include config.h in your c++ sources and use the PROJECT_DIR macro as you expect.
No, CMake cannot do this directly. And you shouldn't do it, because you would have to place your source code within your build directory instead of your source directory.
The usual way - with respect to C++ and CMake - is to use a macro FOO_PATH in your C++ code and
pass -DFOO_PATH=<path_to_foo> via CMake.
add a define #cmakedefine FOO_PATH FOO_PATH to your configure file config.h, define FOO_PATH within your CMake code, and regenerate your config.
How do you do this when using ctest. In this instance there is no .h file to include, but needs to modify .cc files that are compiled? Such that it does not modify the original ${CMAKE_SOURCE_DIR} files
add_compile_definitions(TEST_DATA_DIR="${CMAKE_SOURCE_DIR}/data")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test_file.cc
${CMAKE_CURRENT_BINARY_DIR}/test_file.cc)
and in C++:
std::string filename = "TEST_DATA_DIR/data.txt";
std::cout << filename << std::endl;
...
outputs "TEST_DATA_DIR/data.txt"

C++ Macro defined from outside .cpp or .hpp

I want to do something like an application that is build in debug or release mode.
Is it possible to define a macro outside the .cpp or .hpp?
I am using CMake. I have seen that add_definitions(...) is doing something like this. Shall I create two executables proj and proj_debug and for debug define a macro with add_definitions(...)? Is this a good approach? If not, how would you suggest me to do?
Use something like this:
target_compile_definitions(myproj PRIVATE $<$<CONFIG:Debug>:MY_DEBUG_MACRO>)
http://www.cmake.org/cmake/help/v3.0/manual/cmake-generator-expressions.7.html
http://www.cmake.org/cmake/help/v3.0/command/target_compile_definitions.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
This works with all generators and is the documented, right, supported way of doing it (and implemented by me :) ).
Man g++ http://linux.die.net/man/1/g++
Look for the -D option for defining macros
and you can configure your makefiles to set that option http://www.cmake.org/Wiki/CMake_Useful_Variables
set(CMAKE_CXX_FLAGS "-g -Wall -Dxxxx")
To define Macro in the different file can be done by following ways:
1) You can define Macro in any other .h file.
and include the file in .cpp file.
This can help you to define Macro in different file
To check the Macro for Debug and Release version use _Debug or _Release Macro.
2) Another way to do this is By using the way told by #Soren.
using set(CMAKE_CXX_FLAGS "-g -Wall -Dxxxx")
like this. Shall I create two executables proj and proj_debug and for debug
No need.
With cmake you can change the CMAKE_BUILD_TYPE variable when configuring your project. Then in your CMakeLists.txt you can do something like:
if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
add_definitions(-DMY_DEBUG_MACRO)
endif()
Then you can easily configure your project twice (in two directories): once with CMAKE_BUILD_TYPE set to Debug and once CMAKE_BUILD_TYPE set to Release.