CPPCheck: Errors in local header files are not caught - cmake

I have a project that uses CMake with a top level CMakeLists which references subdirectories each with their own targets and CMakeLists. Each subdirectory includes src, include dirs.
I'm trying to execute Cppcheck on my code base using the following command:
cppcheck --project=compile_commands.json --suppressions-list=suppressions.txt --output-file=cppcheck-results.log --xml --enable=all
My suppressions.txt file contains a bunch of style errors to skip.
The problem is that it doesn't catch any error/issue in local .h files (inside the include directories).
Unless I specify cppcheck to check a specific directory and give the -I flag, then it would. But for the whole project it does not.

Related

CMake generation requiring generated files

I'm building a project using CMake in multiple subdirectories. There is a parent directory containing a parent CMakeLists file, and each subdirectory contains its own CMakeLists file. As such, I'm using the add_subdirectory command to run the subdirectories.
My issue is that one of the subdirectories generates code that another subdirectory needs in order to build. Specifically, it's Google Protocol Buffers. The CMakeLists file in that subdirectory will generate the pb.cc and pb.h files if run independently, but until I do so, I cannot generate the cache of the parent CMake file as it complains it's missing those source files.
Directory structure is as follows:
/
--CMakeLists.txt
--protobuf/
----CMakeLists.txt
----src/
--main/
----CMakeLists.txt
----src/
Where the main subdirectory requires files generated by the protobuf subdirectory.
Is there a way I can have the parent CMakeLists file build the subdirectory as part of its generation step? Or somehow mark the protobuf files as required, but missing, so the generation does not fail?
You can try running this particular cmake file as execute_process before including the main file. But this goes against the designed cmake usage.
The correct answer would be to make your generation step a part of build process. If you can post a minimal, reproducible example of your problem I could give you concrete ways to solve your problem directly instead of making your workaround work.

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.

'Cannot determine link language for target...' issue in sub directory

In the main folder of my project, I have a CMakeLists.txt file. Inside this file, I include (using add_subdirectory) another CMakeLists.txt file located in my header file directory. The responsibility of this second file is to add all of my header files to the project:
file(GLOB gl_nbody_HEADERS "*.h")
add_executable(gl_nbody ${gl_nbody_HEADERS})
However, this files causes an error:
CMake Error: CMake can not determine linker language for target:gl_nbody
CMake Error: Cannot determine link language for target "gl_nbody".
What is strange is that when I include the two lines causing this error in my main CMakeLists.txt file (modified to work correctly for the change in directory), it works fine.
What is going wrong here?
add_executable causes the creation of an executable target, meaning the compilation of a list of source code files into an executable binary.
In order for this to work, and have CMake select a suitable compiler, the list of source files must contain at least one file with a "compilable" extension, ie. .c, or .cpp, or .cxx....
I don't see why you are trying to compile an executable here, since you only seem to try to list header files for inclusion into a project (which only makes sense for IDE-based generators, such as Visual Studio).
Also, it is not recommended to use globbing of files in CMake, because if you add more files to your project, CMake cannot detect them automatically, and will not regenerate build files. Please list all files explicitely.
The proper solution here is to list the header files in the proper add_executable command call where you list the actual source files that you want to compile.
You might also want to use the source_group() command, that allows you to group files into folders in the generated Visual Studio solution, for example:
source_group(header_files ${gl_nbody_HEADERS})

Avoid repeating the directory name for multiple file inclusions

I have a CMakeLists.txt file for a library. It's pretty basic:
set(LIB_FILES source/first.cpp)
add_library(first ${LIB_FILES})
I put the files in a list because I will eventually be adding more source files to the library. The problem is that all of the files will be in the source directory. And I don't want to constantly have to repeat that.
I also don't want to use the GLOB pattern matching solution, because I want to have to edit the CMakeLists.txt file when I add a new file. That way, my build will re-build the build solution, and new files will correctly appear (as I understand it. I'm still new with CMake).
I tried adding a CMakeLists.txt file into the source directory itself, just to build the LIB_FILES list. That didn't work out very well. Variables in CMake are file scoped. And even when I broke scoping (with PARENT_SCOPE), I still had to prefix each file with the directory. So that gained nothing.
I don't want to put the actual library definition in the source directory, as that will generate all the build files in the source directory. And I don't want that. Also, I will need to include headers that aren't in or under the source directory.
My directory structure looks like this:
libroot (where the project build files should go)
\-source (where the source code is)
\-include (where the headers that the user of the library includes go)
So how do I tell CMake that all of the source files come from the source directory, so that I don't have to constantly spell it out?
You could move the add_library call to your source/CMakeLists.txt also:
set(LIB_FILES first.cpp)
add_library(first ${LIB_FILES})
Then just use add_subdirectory in your top-level CMakeLists.txt:
add_subdirectory(source)
you could use a simple macro for that
macro(AddSrc dst_var basepath_var)
foreach(file ${ARGN})
list(APPEND ${dst_var} ${basepath_var}/${file})
endforeach()
endmacro()
set(MY_SRCFILES "")
AddSrc(MY_SRCFILES path/to/source
foo.cpp
bar.cpp
whatever.cpp
)

CMake with regarding generated files

Good day everyone.
I have the following situation: I have a CMake file, which is supposed to compile my application, which consists of:
one or more cpp files
some template files (ecpp), which on their turn are generated into cpp files, which are compiled into the application (they are listed below in the WEB_COMPONENTS so for each component there is the associated .ecpp file and the .cpp that will be generated from it).
And here is the CMakeLists.txt (simplified)
cmake_minimum_required (VERSION 2.6)
set (PROJECT sinfonifry)
set (ECPPC /usr/local/bin/ecppc)
set (WEB_COMPONENTS
images
menu
css
)
set(${PROJECT}_SOURCES
""
CACHE INTERNAL ${PROJECT}_SOURCES
)
foreach(comp ${WEB_COMPONENTS})
list(APPEND ${PROJECT}_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${comp}.cpp )
execute_process(COMMAND ${ECPPC} -o ${CMAKE_CURRENT_BINARY_DIR}/${comp}.cpp -v
${CMAKE_CURRENT_SOURCE_DIR}/${comp}.ecpp
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_QUIET
)
endforeach()
list(APPEND ${PROJECT}_SOURCES main.cpp )
add_executable(${PROJECT}_exe ${${PROJECT}_SOURCES})
target_link_libraries(${PROJECT}_exe cxxtools dl tntnet tntdb)
Now, what happens: for the very first time (ie: make the build directory, run cmake-gui, select web component, configure, generate, make) the CMake nicely executes the ${ECPPC} command, ie. it generates the required CPP files in the binary directory, and links them together.
After a while, obviously while I work, I modify one of the component files (such as images.ecpp) and run make again in the build directory. But now, CMake does not pick up the changes of the ecpp files. I have to go to cmake-gui, delete cache, restart everything from zero. This is very tiresome and slow.
So, two questions:
Cand I tell CMake to track the changes of the images.ecpp and call the ${ECPPC} compiler on it if it changed?
How can I make clean so that it also removes the generated cpp files.
Thank you for your time, f.
Instead of execute_process() you want to use add_custom_command(). See here: https://stackoverflow.com/a/2362222/4323
Basically you tell CMake the OUTPUT (the generated filename), COMMAND, and DEPENDS (the .ecpp filename). This makes it understand how to turn the source into the necessary C++ generated file. Then, add the generated file to some target, e.g. add_executable(), or to an add_custom_command() dependency (if it didn't need to be compiled you'd more likely need that).