How to force CMAKE in building SWIG module in release mode - cmake

Is there a way to forcefully set the release mode of swig modules in cmake to build in release mode no matter what the actual build type is?
I am trying to build a python module using swig autogenerated code, and it complains of a python debug library when I build my application in debug mode.
I am not interested in debugging python module related code, so I am fine with not building the swig autogenerated python modules in debug mode.
Here is what I have in my cmakelists.txt file:
set_source_files_properties(abstract.i PROPERTIES CPLUSPLUS on)
swig_add_module(${PROJECT_NAME} python abstract.i)
swig_link_libraries(${PROJECT_NAME} ${PROJECT_NAME} ${PYTHON_LIBRARIES})

I suppose the real issue is that MSVC produces link error, due to the missing "python_d.lib"
Just insert into the header of SWIG interface (your *.i) files:
%begin %{
#ifdef _MSC_VER
#define SWIG_PYTHON_INTERPRETER_NO_DEBUG
#endif
%}
... and remove
#ifdef _MSC_VER
...
#endif
when the issue is generic, not MSVC related only

Hmm, how about wrapping your code snippet in
set(CMAKE_TMP_BUILD_TYPE ${CMAKE_BUILD_TYPE})
set(CMAKE_BUILD_TYPE "Release")
and
set(CMAKE_BUILD_TYPE ${CMAKE_TMP_BUILD_TYPE})
?

You can tell CMake not to include a project in the default build of a certain configuration. For example, for a Python module (with the underscore added to the target by SWIG):
SET_TARGET_PROPERTIES(_${PROJECT_NAME} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_DEBUG True)

Related

How do I generate PDB files using cmake and gcc?

I want to use the OpenCppCoverage to check the coverage of my source files by my Unit Test. However, it seems that I need to have .pdb files generated for OpenCppCoverage to work.
The problem is that I am not being able to generate such files from my build. Here is my CmakeLists.txt
cmake_minimum_required(VERSION 3.17) # version can be different
project(GUnitTestingVSCode) #name of your project
add_subdirectory(googletest) # add googletest subdirectory
add_compile_definitions(TELEMETRY_DIAGNOSTICS)
add_compile_definitions(GTEST)
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/")
include_directories(googletest/include/) # this is so we can #include <gtest/gtest.h>
include_directories(googletest/googlemock/include/gmock/) # this is so we can #include <gmock/gmock.h>
include_directories("${CMAKE_SOURCE_DIR}/"
"${CMAKE_SOURCE_DIR}/inc/"
"${CMAKE_SOURCE_DIR}/mocks/"
"${CMAKE_SOURCE_DIR}/../submodule/library/inc"
"${CMAKE_SOURCE_DIR}/../submodule/library/inc/Application"
"${CMAKE_SOURCE_DIR}/../submodule/library/inc/Datalink/"
"${CMAKE_SOURCE_DIR}/../submodule/library/inc/Demodulation"
"${CMAKE_SOURCE_DIR}/../submodule/library/inc/Modulation"
"${CMAKE_SOURCE_DIR}/../inc/Peripherals/"
"${CMAKE_SOURCE_DIR}/../inc/Protocol/"
"${CMAKE_SOURCE_DIR}/../inc/Diagnostics/")
file(GLOB_RECURSE SOURCES RELATIVE
${CMAKE_SOURCE_DIR} "../src/Peripherals/DMA.c" "../src/Diagnostics.c"
${CMAKE_SOURCE_DIR} "../src/Protocol/DataLink.c"
"src/*.cpp" "googletest/*.cpp" "mocks/*.c"
"../submodule/library/src/*.c")
add_executable(gUnitTest ${SOURCES}) # add this executable
set(CMAKE_BUILD_TYPE RelWithDebInfo)
set_target_properties(gUnitTest PROPERTIES
COMPILE_PDB_NAME "gUnitTestCompiled"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/"
PDB_NAME "gUnitTestLinker"
PDB_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/")
target_link_libraries(gUnitTest PUBLIC gtest gmock) # link google test to this executable
However, when I build my Test folder in RelWithDebInfo mode (I also tried Debug), I get no .pdb files in the build folder. Can someone help me understand what am I doing wrong?
The compiler used is GCC 9.2.0 (mingw32)
I was able to figure out myself. So here is the answer if someone struggles with the same:
gcc compiler is not able to generate .pdb files. What can be done is the following:
Convert the debug information from gcc to pdb files using the converter called cv2pdb
Use llvm/clange compiler that has support to generate .pdb
Use another code coverage tool, such as gcov from gcc itself
I decided to use option 3, and replace opencppcoverage by gcov (in fact I am using gcovr). I had to include the extra flags for coverage as mentioned above:
-fprofile-arcs -ftest-coverage -fPIC -O0

Compiler option dependency for LLVM pass with CMake

I have a project that needs to be built with an LLVM pass. Here is the project structure:
proj/
instrumentation/
CMakeLists.txt
Instrumentation.cpp
[My project files]
CMakeLists.txt
instrumentation/CMakeLists.txt has a target to build the LLVM pass called MyPass.
I've added the following the CMakeLists.txt:
add_subdirectory(instrumentation)
add_compile_options(
"SHELL:-Xclang -load"
"SHELL:-Xclang $<TARGET_FILE:MyPass>")
Now I just need to add MyPass as a dependency for all the targets in my project. I was wondering if there was a way to force MyPass to build first so that when compiling other files, the LLVM pass would be present. Maybe there a way to add a target compile_options dependencies?
Note: I'd rather not add the dependency manually to every target because there many targets in the project.
My solution to this is to create another project to wrap the compiler executable and automatically build with the LLVM pass. Then rebuild the original project with the wrapped compiler.
AFL does this exact thing when building with a clang compiler.

Cppcheck support in CMake

I am not asking about the various available third-party modules that support Cppcheck in one way or the other.
With CMake 3.10, CMake seems to have gained some official Cppcheck support. See CMAKE_<LANG>_CPPCHECK.
Unfortunately the documentation how to use this variable is a bit sparse. Is there a good example of how Cppcheck is supposed to be used with CMake 3.10 (or later)?
An simple example would be - if you have cppcheck in your PATH and you are not specifying additional parameters - the following by setting global CMAKE_<LANG>_CPPCHECK variable:
cmake_minimum_required(VERSION 3.10)
project(CppCheckTest)
file(
WRITE "main.cpp"
[=[
int main()
{
char a[10];
a[10] = 0;
return 0;
}
]=]
)
set(CMAKE_CXX_CPPCHECK "cppcheck")
add_executable(${PROJECT_NAME} "main.cpp")
The files to scan are added automatically to the cppcheck command line. So the above example gives the following output (gcc and cppcheck on Linux system):
# make
Scanning dependencies of target CppCheckTest
[ 50%] Building CXX object CMakeFiles/CppCheckTest.dir/main.cpp.o
Checking .../CppCheckTest/main.cpp...
Warning: cppcheck reported diagnostics:
[/mnt/c/temp/StackOverflow/CppCheckTest/main.cpp:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.
[100%] Linking CXX executable CppCheckTest
[100%] Built target CppCheckTest
You could give cppcheck a try in an existing project by simply setting the CMAKE_CXX_CPPCHECK variable via the cmake command line:
# cmake -DCMAKE_CXX_CPPCHECK:FILEPATH=cppcheck ..
A more "daily life" example would probably for you to include something like the following code snippet in your CMakeList.txt:
find_program(CMAKE_CXX_CPPCHECK NAMES cppcheck)
if (CMAKE_CXX_CPPCHECK)
list(
APPEND CMAKE_CXX_CPPCHECK
"--enable=warning"
"--inconclusive"
"--force"
"--inline-suppr"
"--suppressions-list=${CMAKE_SOURCE_DIR}/CppCheckSuppressions.txt"
)
endif()
References
CMake Commit: Add properties to run cppcheck along with the compiler
<LANG>_CPPCHECK target property
This property is supported only when <LANG> is C or CXX.
Specify a ;-list containing a command line for the cppcheck static analysis tool. The Makefile Generators and the Ninja generator will run cppcheck along with the compiler and report any problems.
This property is initialized by the value of the CMAKE_<LANG>_CPPCHECK variable if it is set when a target is created.

Force cmake to re-run CHECK_CXX_SOURCE_COMPILES after external libraries have been set up

Using CMake I want to check if a particular function (cv::getGaborKernel) from OpenCV library is available (it is available only in quite recent version of the library). If it is, I will use it in my code, if it is not, I redefine it in my code, in btw #ifdefs.
Here is a snippet of my CMakeLists.txt:
FIND_PACKAGE(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
set(CMAKE_REQUIRED_INCLUDES ${OpenCV_INCLUDE_DIRS})
set(CMAKE_REQUIRED_LIBRARIES ${OpenCV_LIBS})
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES(
"
#include <opencv2/imgproc/imgproc.hpp>
int
main()
{
cv::Mat toto = cv::getGaborKernel(cv::Size(11,11), 1,0,3,1,0, CV_64F);
}
" HAVE_OPENCV_GABOR)
if(HAVE_OPENCV_GABOR)
message("Using OpenCV Gabor implementation")
else(HAVE_OPENCV_GABOR)
message("Using custom Gabor implementation")
endif(HAVE_OPENCV_GABOR)
When deploying on a computer with recent OpenCV version (which does have cv::getGaborKernel), the test fails, forcing the redefinition of the function and some compilation errors.
The problem reside in the fact that OpenCV not beeing installed in standard directory, it first fails to locate the library. So the sample program cannot be built. However, after I properly set up OpenCV dependencies, the test for HAVE_OPENCV_GABOR is not run again as the failure is registered in the cache.
How can I force CMake to rerun the test in that case?
Just wrap your CHECK_CXX_SOURCE_COMPILES() call with
if(NOT OpenCV_INCLUDE_DIRS OR NOT OpenCV_LIBS)
...
endif()
Another solution - add unset(HAVE_OPENCV_GABOR CACHE) before running CHECK_CXX_SOURCE_COMPILES().

Include source files on a per-configuration basis in CMake

In my particular CMake project, I have three CPP files:
a.cpp
b.cpp
c.cpp
I want 'a.cpp' to be compiled in all configurations (release & debug).
I only want 'b.cpp' to be compiled in DEBUG configuration.
I only want 'c.cpp' to be compiled in RELEASE configuration.
How can I do this? I need something similar to the debug and optimized keywords that are accepted by the target_link_libraries() CMake operation.
As far as I know cmake does not provide a way to exclude some files based on configuration. So you need a workaround to achieve this behavior.
For example, you can wrap the whole content of b.cpp and c.cpp with some guard macro:
#ifdef BUILD_ME
//original content of your file
#endif
and next set configuration-specific compiler definitions in cmake:
if (${CMAKE_GENERATOR} MATCHES "Make" AND "${CMAKE_BUILD_TYPE}" STREQUAL "")
# This block might be needed because CMAKE_BUILD_TYPE is usually
# undefined for makefiles.
# And COMPILE_DEFINITIONS_RELEASE are not chosen by default.
set(CMAKE_BUILD_TYPE RELEASE)
endif()
set_source_files_properties(b.cpp PROPERTIES COMPILE_DEFINITIONS_DEBUG BUILD_ME )
set_source_files_properties(c.cpp PROPERTIES COMPILE_DEFINITIONS_RELEASE BUILD_ME )
add_executable(target_name a.cpp b.cpp c.cpp)
This this issue has been fixed as of 3.17:
https://cmake.org/cmake/help/latest/release/3.17.html#generators
"Visual Studio Generators learned to support per-config sources. Previously only Command-Line Build Tool Generators supported them."