#ifdef DEBUG with CMake independent from platform - c++

I am using CMake for building my projects on Windows (Visual Studio) as well as on Linux machines(gcc). I'd like to mark some code as "debugging only", like with
#ifdef DEBUG
//some logging here
#endif
The question is: what compiler definition is available on all platforms in the CMake "Debug" build type? DEBUG seems not to exist. (I want to have the logging or whatever only when the build type is Debug.)

CMake adds -DNDEBUG to the CMAKE_C_FLAGS_{RELEASE, MINSIZEREL} by default. So, you can use #ifndef NDEBUG.

I would suggest that you add your own definition. The CMake symbol CMAKE_C_FLAGS_DEBUG can contain flags only used in debug mode. For example:
C:
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DMY_DEBUG")
C++:
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DMY_DEBUG")
In your code you can then write the following:
#ifdef MY_DEBUG
// ...
#endif
(Maybe, you would have to use "/DMY_DEBUG" for visual studio.)

In CMake >= 2.8, use target_compile_definitions:
target_compile_definitions(MyTarget PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>")
When compiling in Debug mode, this will define the DEBUG symbol for use in your code. It will work even in IDEs like Visual Studio and Xcode for which cmake generates a single file for all compilation modes.
You have to do this for each target [1]. Alternatively you can use add_compile_options (Cmake >= 3.0):
add_compile_options("$<$<CONFIG:DEBUG>:-DDEBUG>")
Note that recent versions of Visual C++ (at least since VS2015) allow either / or - for parameters, so it should work fine across compilers. This command is also useful for other compile options you might like to add ("/O2" in release mode for MSVC or "-O3" for release mode in G++/Clang)
[1] : Note: in CMake >= 3.12 (currently beta) there is also an add_compile_definitions that supports generator expressions, which affects all targets.

I'm using the following in my CMakeLists.txt:
set(IS_DEBUG_BUILD CMAKE_BUILD_TYPE STREQUAL "Debug")
# Indication to the code that this is a debug build
if (${IS_DEBUG_BUILD})
add_compile_definitions(__DEBUG__)
endif ()
Then, in my code, I can write:
#ifdef __DEBUG__
// blablabla
#edif
My minimum CMake version:
cmake_minimum_required(VERSION 3.16.3)

Related

How can cmake_minimum_required required version impact generated files?

I'm experiencing a strange behaviour where changing cmake_minimum_required affects files generated by CMake targetting Visual Studio 2019. According to the doc of cmake_minimum_required:
If the running version of CMake is lower than the required version it will stop processing the project and report an error
So it's just supposed to interrupt project generation.
But, if I create:
main.cpp:
int main()
{
#ifndef _DEBUG
#error "DEBUG flag not set"
#endif
return 0;
}
and CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12)
project(hello_world)
set( CMAKE_CONFIGURATION_TYPES "Debug;Release;MyDebug" CACHE INTERNAL "" FORCE )
set( CMAKE_CXX_FLAGS_MYDEBUG "${CMAKE_CXX_FLAGS_DEBUG}" )
set( CMAKE_C_FLAGS_MYDEBUG "${CMAKE_C_FLAGS_DEBUG}" )
set( CMAKE_EXE_LINKER_FLAGS_MYDEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" )
set( CMAKE_SHARED_LINKER_FLAGS_MYDEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" )
set_property( GLOBAL PROPERTY DEBUG_CONFIGURATIONS "Debug;MyDebug" )
add_executable(app main.cpp)
If I generate this project with CMake 3.24.1 for Visual Studio 2019, then it builds correctly using MyDebug config as _DEBUG compilation flag is correctly set.
However, if I change cmake_minimum_required(VERSION 2.8.12) to cmake_minimum_required(VERSION 3.24.1), then it fails to build, reporting DEBUG flag not set, meaning _DEBUG compilation flag is not set anymore.
When I check vcproj file, I see that for MyDebug, <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> is changed to <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>.
Is this a CMake bug or am I doing something wrong?
So it's just supposed to interrupt project generation.
That's not the case at all!
cmake_minimum_required puts your project into a backwards compatibility mode consistent with the version specified. The "Policy Settings" section of that doc talks about this. There are a set of now over one hundred CMake policies that enable breaking improvements to the system. You can see the full list here: https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html
The relevant policy here is CMP0091 which was introduced in CMake 3.15.
CMake 3.15 and above prefer to leave the MSVC runtime library selection flags out of the default CMAKE_<LANG>_FLAGS_<CONFIG> values and instead offer a first-class abstraction. The CMAKE_MSVC_RUNTIME_LIBRARY variable and MSVC_RUNTIME_LIBRARY target property may be set to select the MSVC runtime library. If they are not set then CMake uses the default value MultiThreaded$<$<CONFIG:Debug>:Debug>DLL which is equivalent to the original flags.
So to upgrade your project to a version of CMake newer than 3.15, you'll just need to override the default CMAKE_MSVC_RUNTIME_LIBRARY close to the top of your CMakeLists.txt file:
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug,MyDebug>:Debug>DLL"
CACHE STRING "Rule for selecting MSVC runtime")
This uses the $<CONFIG> generator expression to enable the debug runtime for your custom MyDebug config.
Of course cmake can change behaviour with its evolution.
As CMake evolves it is sometimes necessary to change existing behavior in order to fix bugs or improve implementations of existing features. *
If it just changes some behaviour in a new version, it introduces a policy, that can explicitly switch cmake to use an old behaviour. The OLD behavior of a policy becomes deprecated by definition and may be removed in a future version of CMake.
See what is changed in the list cmake-policies(7).
Also you can set cmake_minimum_required incrementing the major version number by one at a time, run cmake and see what policies were introduced in cmake dump. One of them is changing the behaviour of RuntimeLibrary and _DEBUG.

How to use "webrtc.lib" static library in VS 2019 or CLion Project?

I have been working with WebRtc Development for the Windows Platform. I want to develop webrtc based desktop application. I am doing it from scratch for learning and better understanding.
The normal process of WebRtc Library Compilation:
I have initially started with (Getting Started with WinRTC). I followed the normal compilation process. After that, I have tried multiple ways to generate project files for webrtc such as;
1.Default
gn gen --ide=vs2019 out/Default
2.Custom Flags
gn gen --ide=vs2019 out/Default --args="use_rtti=true is_clang=false rtc_build_tools=false rtc_include_tests=false rtc_build_examples=false"
3.Custom Flags
gn gen --ide=vs2019 out\Default --filters=//:webrtc "--args=is_debug=true use_lld=false is_clang=false rtc_include_tests=true rtc_build_tools=true rtc_win_video_capture_winrt=true target_cpu=\"x86\" target_os=\"win\" rtc_build_examples=true rtc_win_use_mf_h264=true enable_libaom=true rtc_enable_protobuf=true"
For the building process, I have Followed these methods:
With command line:
Run the following command to build the patched WebRTC from the command line.
ninja -C out\Default\x64
With Visual Studio 2019:
Open the generated Visual Studio solution with the following command:
devenv out\Default\x64\all.sln
I have tried almost all available combinations to generate build files and to build webrtc.lib static library. I have successfully managed to compile the static webrtc library webrtc.lib for both architectures;
x64 (Default Arch) (For Debug as well as release)
x86 (Custom Arch) (For Debug as well as release)
IMPORTANT:
I have successfully managed to run peerconnection_server.exe and
peerconnection_client.exe on windows. These examples are
successfully running on localhost.
Using VS2019:
After that, I created a new Console based project using VS2019 to consume generated binaries and followed these steps;
Add include folders
Configuration Properties → C/C++ → General → Additional Include Directories and add the following paths:
c:\webrtc\src
c:\webrtc\src\out\Default\$(Configuration)\$(PlatformTarget)\gen
c:\webrtc\src\third_party\abseil-cpp
c:\webrtc\src\third_party\libyuv\include
Preprocessor macros:
Click on Preprocessor → Preprocessor Definitions and add the following definitions:
USE_AURA=1;_HAS_EXCEPTIONS=0;__STD_C;_CRT_RAND_S;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_ATL_NO_OPENGL;_WINDOWS;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;PSAPI_VERSION=2;WIN32;_SECURE_ATL;WINUWP;__WRL_NO_DEFAULT_LIB__;WINAPI_FAMILY=WINAPI_FAMILY_PC_APP;WIN10=_WIN32_WINNT_WIN10;WIN32_LEAN_AND_MEAN;NOMINMAX;_UNICODE;UNICODE;NTDDI_VERSION=NTDDI_WIN10_RS2;_WIN32_WINNT=0x0A00;WINVER=0x0A00;NDEBUG;NVALGRIND;DYNAMIC_ANNOTATIONS_ENABLED=0;WEBRTC_ENABLE_PROTOBUF=0;WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE;RTC_ENABLE_VP9;HAVE_SCTP;WEBRTC_LIBRARY_IMPL;WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0;WEBRTC_WIN;ABSL_ALLOCATOR_NOTHROW=1;HAVE_SCTP;WEBRTC_VIDEO_CAPTURE_WINRT
Linker additional library path:
Click on Linker → General → Additional Library Directories and add the following path:
c:\webrtc\src\out\Default\$(Configuration)\$(PlatformTarget)\obj
WebRTC library name:
Click on Input → Additional Dependencies and add the following filename:
webrtc.lib
Now, when I simply use this basic implementation such as;
#include <iostream>
#include "rtc_base/thread.h"
#include "rtc_base/logging.h"
#include "rtc_base/ssl_adapter.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/net_helpers.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/signal_thread.h"
int main(int argc, char** argv) {
rtc::InitializeSSL();
return 0;
}
The program is flooded with two types of errors:
1. LNK2038 mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug'
and another one is
2. LNK2038 mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2'
You can also see as given; Here I have used webrtc.lib with Configuration (Release) & Platform (x64).
Using Clion-2021.2.1 and CMAKE:
Here I have used webrtc.lib with Configuration (Release) & Platform (x86).
CMakeLists.txt is given as;
cmake_minimum_required(VERSION 3.20)
project(NewRtc)
set(CMAKE_CXX_STANDARD 14)
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
include_directories(
"c:/webrtc/src"
"C:/webrtc/src/out/Default/x86/obj"
"c:/webrtc/src/third_party/abseil-cpp"
"c:/webrtc/src/third_party/libyuv/include"
)
# error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.obj
# Solution:
#1. _ITERATOR_DEBUG_LEVEL = 0 // disabled (for release builds)
#2. _ITERATOR_DEBUG_LEVEL = 1 // enabled (if _SECURE_SCL is defined)
#3. _ITERATOR_DEBUG_LEVEL = 2 // enabled (for debug builds)
add_definitions(
-D_ITERATOR_DEBUG_LEVEL=0
-DUSE_AURA=1
-D_HAS_EXCEPTIONS=0
-D__STD_C
-D_CRT_RAND_S
-D_CRT_SECURE_NO_DEPRECATE
-D_SCL_SECURE_NO_DEPRECATE
-D_ATL_NO_OPENGL
-D_WINDOWS
-DCERT_CHAIN_PARA_HAS_EXTRA_FIELDS
-DPSAPI_VERSION=2
-DWIN32
-D_SECURE_ATL
-DWINUWP
-D__WRL_NO_DEFAULT_LIB__
-DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP
-DWIN10=_WIN32_WINNT_WIN10
-DWIN32_LEAN_AND_MEAN
-DNOMINMAX
-D_UNICODE
-DUNICODE
-DNTDDI_VERSION=NTDDI_WIN10_RS2
-D_WIN32_WINNT=0x0A00
-DWINVER=0x0A00
-DNDEBUG
-DNVALGRIND
-DDYNAMIC_ANNOTATIONS_ENABLED=0
-DWEBRTC_ENABLE_PROTOBUF=0
-DWEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE
-DRTC_ENABLE_VP9
-DHAVE_SCTP
-DWEBRTC_LIBRARY_IMPL
-DWEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0
-DWEBRTC_WIN
-DABSL_ALLOCATOR_NOTHROW=1
-DHAVE_SCTP
-DWEBRTC_VIDEO_CAPTURE_WINRT)
#set(CMAKE_CXX_FLAGS_RELEASE "/MT")
#set(CMAKE_CXX_FLAGS_DEBUG "/MTd")
set(-Dwebrtc.lib)
add_executable(NewRtc main.cpp)
set_property(TARGET NewRtc PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_link_libraries(NewRtc
PRIVATE "C:/webrtc/src/out/Default/x86/obj/webrtc.lib"
)
But when I simply build the project, this error comes up for every implementation of WebRtc. Here you can see:
Please assist me that how can I simply use webrtc library in any project on windows suing VS2019 or Clion. I am trying to solve these problems, I have tried multiple solutions over stack overflow and other communities using cmake or adding flags inside project properties such as;
Linker Tool Errors
/MD, /MT, /LD (Use Run-Time Library)
LNK2038 mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2'
Mismatch Detected for 'RuntimeLibrary'
I have tried my best to explain the complete solution and associated problem so that someone might help me accordingly.
Well Guys, After spending almost 12 hours of research, I have made my day. I have exactly figured out what was wrong with my development setup in (VS2019/Clion) of using static webrtc.lib in executable projects.
I must thank Mr.#drescherjm for his support on my question. It's
really appreciated it.
All things were in a positive direction from library compilation to its usage in VS2019/Clion projects. Actually, webrtc development in .netCore projects required some useful libraries for the normal use of webrtc.lib in your projects.
Here is the list of libraries that you must use during development such as;
For Windows:
Required Modules for building WebRtc projects for Windows as follows;
WS2_32 secur32.lib winmm.lib dmoguids.lib wmcodecdspuuid.lib msdmo.lib Strmiids.lib
For Linux:
Required Modules for building WebRtc projects for Linux as follows;
Secur32 Msdmo Winmm Dmoguids wmcodecdspuuid
These are the important libraries as webrtc peer-to-peer communication mostly comes up with the extensive implementation of socket programming in C/C++ for both Linux as well as Windows Operating Systems.
How to use these libraries in projects:
using CmakeLists.txt
using #pragma keyword
For CMakeLists.txt:
You can simply include these modules in target_link_libraries() in which you are also linking webrtc.lib such as;
add_executable(NewRtc main.cpp)
set_property(TARGET NewRtc PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_link_libraries(NewRtc
PRIVATE "{$LIB_PATH}/webrtc.lib"
# Required Modules for building projects
WS2_32 secur32.lib winmm.lib dmoguids.lib wmcodecdspuuid.lib msdmo.lib Strmiids.lib
)
For #Pragma Keyword:
You can directly include all the required libraries using the #pragma keyword inside your executable files (in my case main.cpp) such as;
# pragma comment(lib, "webrtc.lib")
# pragma comment(lib,"WS2_32")
# pragma comment(lib, "secur32.lib")
# pragma comment(lib, "winmm.lib")
# pragma comment(lib, "dmoguids.lib")
# pragma comment(lib, "wmcodecdspuuid.lib")
# pragma comment(lib, "msdmo.lib")
# pragma comment(lib, "Strmiids.lib")
Both procedures will 100% serve the same purpose. I hope it would help someone.

Cannot set __cplusplus to C++17 standard with Visual Studio and CMake

I've a CMake project that's opened with Visual Studio 2019. I need c++17 features for my code, so I've set the corresponding flag in the CMakeLists.txt
cmake_minimum_required (VERSION 3.10.0)
project (datalog)
message (STATUS "Building project ${PROJECT_NAME}")
find_package(stxxl CONFIG REQUIRED)
include_directories (${CMAKE_SOURCE_DIR}/src)
set (PROJECT_SRC
main.cpp
)
add_executable (${PROJECT_NAME} ${PROJECT_SRC})
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
target_link_libraries(${PROJECT_NAME} stxxl)
When I build I obtain a lot of errors, because the library that I'm linking, stxxl, installed with vcpkg, has the following piece of code:
STXXL_BEGIN_NAMESPACE
template <class Type>
struct compat_unique_ptr {
#if __cplusplus >= 201103L && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40400)
typedef std::unique_ptr<Type> result;
#else
// auto_ptr is inherently broken and is deprecated by unique_ptr in c++0x
typedef std::auto_ptr<Type> result;
#endif
};
STXXL_END_NAMESPACE
The problem is that __cplusplus has value 199711L instead of the correct value 201703L, so code tries to use auto_ptr that's removed in C++17 standard.
I've also tried to set the flag manually in Visual Studio, adding this section in the CmakeLists.txt
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /Zc:__cplusplus")
endif()
But nothing changes. I'm also using some C++17 features, so going back at the moment is not an option.
I can manually update the stxxl header file to get rid of the macro, but it's a workaround, and every developer should create the same fix. Instead, I'd like to know why I'm getting the error and how to set the macro to the correct value with Visual Studio and CMake. Do you have any suggestion?
As far as i can tell from this, you need to add /Zc:__cplusplus manually (at least for now).
Your CMakeList snippet worked for me, are you sure, that __cplusplus is actually set incorrectly and it's not just the __GNUC__ Macro, that's missing?
That said, I'd recommend to test if the version of VisualStudio is actually new enough:
# /Zc:__cplusplus is required to make __cplusplus accurate
# /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7
# (according to https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus)
# That version is equivalent to _MSC_VER==1914
# (according to https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019)
# CMake's ${MSVC_VERSION} is equivalent to _MSC_VER
# (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
if ((MSVC) AND (MSVC_VERSION GREATER_EQUAL 1914))
target_compile_options(stxxl INTERFACE "/Zc:__cplusplus")
endif()
Note: I used target_compile_options to add the necessary option to the interface of your library target. This way all targets, that depend on that library (via target_link_libraries) will be compiled with that flag, but targets, that don't need it (and might be incompatible with it) won't get it.
If you want to add the flag to one of your own targets, you can use target_compile_options(stxxl PUBLIC "/Zc:__cplusplus") (PUBLIC instead of INTERFACE). INTERFACE means the option is used when other targets depend on that target, PRIVATE means the option is used for the target itself and PUBLIC means both. (IMHO this artical explains it well.)
Apart from that, you shouldn't set the c++ standard version via compile flags, but instead using target_compile_features if the newer version is required and using
set_target_properties(your_target_name PROPERTIES CXX_STANDARD 17) if you just wish to use the newer version if it is available.
In your case the latter is probably sufficient as your codesnippet has a fallback if the c++ version is older.
If changing the code of stxxl (via pull request, etc.) is an option, the code could test _MSVC_LANG and _MSC_VER. This way it would work without requiring /Zc:__cplusplus.
I think what you need is target_compile_definitions, where you can define arbitrary macros in CMake and pass to compiler.

How to enable a specific c++ warning in Visual Studio

my project warnlevel is /w3.
I want to enable as single warning from warnlevel 4.
Such as "C4296 'operator' : expression is always false"
How can I do this in cxx flags of my CMake file?
Just add to your main CMakeLists.txt (CMake version >= 2.8.12) generally
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/w34296>")
or (thanks #tambre for the hint) just to a specific target
target_add_compile_options(MyTarget "$<$<CXX_COMPILER_ID:MSVC>:/w34296>")
The shwon generator expression will add warning C4296 to warning level 3 for MSVC compilers (for the VC warning options see link provided by #Richard Critten)
Some more possibilities for setting compile option with CMake in Visual Studio projects can be found in my answer given here.
This code works for me.
#enable compiler warning C4296 in warnlevel 3
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /w34296 ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /w34296 ")

Preprocessor Definitions To Identify Debug/Release Mode in VxWorks

Which preprocessor definitions let you identify the build version of a project in VxWorks? I'm looking for something on the lines of _DEBUG (Debug mode)/ _NDEBUG (Release mode) which are used in VC++.
#ifdef _DEBUG
string strBuildMode = "Debug";
#else
string strBuildMode = "Release";
#endif
The standard macro (also supported by VC++) is NDEBUG. It has negative logic: it's defined in release builds. The documented function is to turn assert() (from <cassert>) off.
You can add a switch -DDEBUG in the 'tool flags' options of the build properties for debug mode (along with -g option). The macro can then be used in the program to identify the build mode.