How to check each header file includes required include files? - c++

I'm developing my application using C++ and cmake.
I'd like to check each C++ header file includes required include files correctly.
Here is an example:
a.hpp
inline void func_a() {
}
b.hpp
// #include "a.hpp" is missing
inline void func_b() {
func_a();
}
main.cpp
#include "a.hpp"
#include "b.hpp"
int main() {}
Demo: https://wandbox.org/permlink/kZqoNHMYARIB3bc1
b.hpp should include a.hpp. Let's say b.hpp missing include a.hpp. If main.cpp include a.hpp before b.hpp, no compile error is occurred. If include order is opposite, compile error is occurred.
I'd like to check this kind of problem.
I'm using fly-check on emacs. It checks this problem well. I'd like to some checking mechanism into my cmake build system.
For example, if I execute make depcheck, then compile error is detected.
I think that if I setup a cmake target that compiles all header files individually but not link, the expected compile error would be reported.
I couldn't find how to setup that, so far.
Is there any way to do that? Or other ways to achieve the goal ?
my header file inclusion policy
Each header file should include header files that contain required element. In other words, each header file should compile individually.
What I want to achieve
I want to know the way to automatically detect b.hpp is missing `#include "a.hpp" by tool assist. The tool means not editor. I guess that cmake could do that. I'm trying to find the way.

Conventional wisdom is to add source files to every header. Even if b.cpp includes only this line:
include "b.hpp" // Note, this should be the first include
That way, you can compile every cpp file in isolation, and a successful compilation means the corresponding header is self-contained.
Of course, if you have an implementation file already, then moving the corresponding header to be included first goes towards ensuring that.

#StoryTeller 's answer
Conventional wisdom is to add source files to every header.
is appropriate way to achieve the goal. It requires adding many source files. It is annoying work especially I develop a header only library.
How to automate that process?
I found a way to check missing include file on cmake. The strategy is compile each header files individually and directly.
Here is CMakeLists.txt
cmake_minimum_required(VERSION 3.8.2)
project(test_checker)
add_custom_target(chkdeps)
file(GLOB HDR_ROOT "*.hpp")
FOREACH (HDR ${HDR_ROOT})
message(STATUS "${HDR}")
get_filename_component(HDR_WE ${HDR} NAME_WE)
SET(CHK_TARGET "${HDR_WE}.chk")
add_custom_target(
${CHK_TARGET}
COMMAND ${CMAKE_CXX_COMPILER} -c ${HDR}
VERBATIM
)
add_dependencies(chkdeps ${CHK_TARGET})
ENDFOREACH ()
To check missing include files, execute make chkdeps.
In order to do only compile, I use add_custom_target. The custom target name is chkdeps (check dependencies). This is the target for all header files dependency checking.
I get the list of *.hpp using file(GLOB HDR_ROOT "*.hpp"). For each got files, I add custom target for only compile using add_custom_target.
I add the extension .chk to avoid conflict. For example if the file name is a.hpp then the target name is a.chk.
I execute the COMMAND ${CMAKE_CXX_COMPILER} with -c option. The -c option is for only compile. I only tested the cmake on Linux. I know setting compile option directly is not good for cross platform development. cmake might provides compile only cross platform mechanism. But I couldn't find it, so far.
Then I add dependency to chkdeps using add_dependencies. Due to this dependency, when I execute make chkdeps, all custom targets (a.chk and b.chk) run.
When I run make chkdeps, then I got the expected error "'func_a' was not declared in this scope" as follows.
make chkdeps
Built target a.chk
/home/kondo/work/tmp/fly_check/b.hpp: In function 'void func_b()':
/home/kondo/work/tmp/fly_check/b.hpp:3:5: error: 'func_a' was not declared in this scope; did you mean 'func_b'?
3 | func_a();
| ^~~~~~
| func_b
make[3]: *** [CMakeFiles/b.chk.dir/build.make:57: CMakeFiles/b.chk] Error 1
make[2]: *** [CMakeFiles/Makefile2:78: CMakeFiles/b.chk.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:113: CMakeFiles/chkdeps.dir/rule] Error 2
make: *** [Makefile:131: chkdeps] Error 2

Related

Issue with Boost.Json library

Could somebody help me with error I am getting when including:
#include <boost/json/src.hpp>
Error is:
In file included from /usr/local/include/boost/json/src.hpp:27:
In file included from /usr/local/include/boost/json.hpp:15:
In file included from /usr/local/include/boost/json/array.hpp:16:
In file included from /usr/local/include/boost/json/storage_ptr.hpp:14:
In file included from /usr/local/include/boost/json/memory_resource.hpp:16:
/usr/local/include/boost/container/pmr/polymorphic_allocator.hpp:132:23: error: expected a class name after '~' to name a destructor
{ (void)p; p->~U(); }
My CMake config has:
find_package(Boost 1.80.0 REQUIRED COMPONENTS timer json)
and
target_link_libraries(device_monitor
Boost::timer
Boost::json
)
Apparently somewhere you have defined U as something else. Preprocessor macros are unsanitary like that, so avoid it.
My guesses are that you are on some kind of Windows platform and U() is a macro that "smart" wraps a string literal of some kind (e.g. to do some UNICODE-depedent stuff or translation).
You could easily show us that in a minimal self-contained example, or go ahead and figure it out by using CMake to precompile the translation unit for you, e.g. something like cmake --build build test.cpp.i. You will find out what the compiler sees instead of the intended code.
You can also demonstrate this effect by
moving the boost include to the top
disabling precompiled headers if you are using them

CLion not working for any file in another directory

I have a directory structure as follows:
libs/
sdw/
glm-0.9.7.2/
glm/
...
src/
ProjectName.cpp
The sdw directory is full of classes with .cpp and corresponding .h files. Inside any of these files, if I type #include " then it auto-suggests header files within this directory. Syntax highlighting also works for any included classes, as does suggestions for methods etc.,
However, inside ProjectName.cpp, I get no such suggestions for header files, and syntax highlighting plus method suggestions are not present. The only things that work are from the std lib like vector etc.
No files get any highlighting etc., for anything inside the glm directory.
Here is a relevant part of the CMakeLists.txt that was provided to me:
set(GLM_INCLUDE_DIRS libs/glm-0.9.7.2)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS} ${GLM_INCLUDE_DIRS})
include_directories(libs/sdw)
add_executable(ProjectName
libs/sdw/Utils.cpp
libs/sdw/Triangle.cpp
src/ProjectName.cpp)
Inside files like libs/sdw/Utils.cpp I am doing: #include "Triangle.h". This works.
Inside src/ProjectName.cpp I am doing: #include <Utils.h>. This
runs but does not work in the way I want, as described above.
And in everything I am doing #include <glm/glm.hpp> which does not
work in the way I want.
EDIT:
I noticed when opening CLion it promps me to clean the project when loading it. If I click OK then it gives me these errors:
No rule to make target 'all'.
Make execution failed with exit code = 2
No compilation commands found
Deleted .idea and selected CMake project this time (chose Makefile last time)

How do I add cpp file to an arduino project?

I am trying to add a cpp file to arduino project that has the following setup...
project
--folder
--foo.h
--foo.cpp
--project.ino
I have a #include "folder/foo.h at the top of project.ino. However while the header provides the prototype of the function, the function definition is in the cpp file. When I try to compile the code using the Arduino IDE, it fails with error
Undefined reference to 'bar()'
and bar() is located in foo.cpp
I looked at this but I do not have a setting for sketch/import library (however I do have sketch/include library, however I did not see anything close to using a custom folder location)
I looked at this too. But same as above, that setting does not exist in my ide. (Which I downloaded recently)
Code
//project.ino
#include "folder/foo.h"
void setup() {
Serial.begin(9600);
}
void loop() {
bar();
}
//folder/foo.h
#include "Arduino.h"
void bar();
//folder/foo.cpp
#include "foo.h"
void bar() {
Serial.println("bar");
}
Error
/tmp/ccNTRFfU.ltrans0.ltrans.o: In function `loop':
/home/temporary/project/project.ino:9: undefined reference to `bar()'
collect2: error: ld returned 1 exit status
exit status 1
What I would expect to happened is a way to link the cpp folder without having to put all the files in the same root folder of the project.
--Edit 1:
added code
--Edit 2:
added #include "Arduino.h"
--Edit 3:
added Serial.begin(9600);
How to properly include C/C++ headers and source files in your Arduino Project.
This answer has been tested and compiled to ensure it works. (Completed in Linux Ubuntu with the Arduino 1.8.7 IDE).
You have 2 problems.
1st: Arduino's unusual build process (described here) doesn't allow including from sub-folders in your project directory where your .ino file for this project is located.
[UPDATE: THIS ONE MAY HAVE BEEN MY MISTAKE ONLY, NOT YOURS, when I was duplicating your code on my PC: I accidentally used foo.c instead of foo.cpp]
2nd: C++ can only be used inside C++ source files, so you must change foo.c to foo.cpp, since Serial.println() is a C++ call to a C++ class's (Serial's) println() method.
To fix 1, simply change your folder structure to have everything in a single folder:
project
├── foo.cpp
├── foo.hh
└── project.ino
I present an alternate fix for #1 below too.
To fix 2, (this is mandatory!) make foo.c --> foo.cpp and (optionally, but recommended, to show it is a C++ header file) foo.h --> foo.hh. Update your includes in the .ino and .cpp file now too to #include "foo.hh".
That's it! Now close the Arduino IDE, then reopen it and reopen your project, and you'll see the following new tabs show up:
It now compiles just fine!
Learning: how did I figure this out?
First, turn on verbose compilation in the Arduino IDE: File --> Preferences --> check the box for "Show verbose output during 'compilation'".
Now, when you compile, all errors will show up in the bottom of the IDE window, as well as the exact compilation or linking commands which throw the error.
Once I fixed the folder structure, but your files were still C instead of C++ files, I saw this error:
Compiling sketch...
/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/tools/avr/bin/avr-gcc -c -g -Os -w -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/arduino/avr/cores/arduino -I/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/arduino/avr/variants/eightanaloginputs /tmp/arduino_build_233569/sketch/foo.c -o /tmp/arduino_build_233569/sketch/foo.c.o
/tmp/arduino_build_233569/sketch/foo.c: In function 'bar':
foo.c:9:5: error: 'Serial' undeclared (first use in this function)
Serial.println("bar");
^
/tmp/arduino_build_233569/sketch/foo.c:9:5: note: each undeclared identifier is reported only once for each function it appears in
exit status 1
'Serial' undeclared (first use in this function)
Notice the file it failed to compile was /tmp/arduino_build_233569/sketch/foo.c, and that the avr-gcc C compiler (rather than the avr-g++ C++ compiler) was in use at the time.
I then opened the /tmp/arduino_build_233569/sketch/foo.c file to examine it and look for anything unusual about it.
Next, I used Eclipse to start tracking down includes, to see where Serial gets pulled in (it should have been obvious to me already what the problem was, but I didn't see it yet). I found the following:
Arduino.h is found in "Arduino/Source/Arduino/hardware/arduino/avr/cores/arduino/Arduino.h". It includes "HardwareSerial.h". This header externs the Serial object:
#if defined(UBRRH) || defined(UBRR0H)
extern HardwareSerial Serial;
#define HAVE_HWSERIAL0
#endif
HOWEVER, looking back at Arduino.h you'll see that HardwareSerial.h is ONLY included if you are compiling with C++:
#ifdef __cplusplus <========= This means that the following headers are ONLY included if you are compiling with C++! BOOM! That's when it hit me! You're compiling a C file with the C compiler to access a C++ object. That's not ok. Use the C++ compiler!
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
#include "USBAPI.h"
#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL)
#error "Targets with both UART0 and CDC serial not supported"
#endif
#ifdef __cplusplus means that the headers above are ONLY included if you are compiling with C++! That's when it hit me! You're compiling a C file with the C compiler to access a C++ object. That's not ok. You must use the C++ compiler instead. Do this simply by changing foo.c to foo.cpp. Done.
Alternate fix for your problem #1 (the folder structure):
Find your "Sketchbook location" from Arduino IDE: File --> Preferences. Mine, for example, is /home/gabriel/dev/Arduino/Sketches.
Now, go there and create a "libraries" folder. For me that would now be /home/gabriel/dev/Arduino/Sketches/libraries. Everything inside this folder is now considered an Arduino "library", and can be included. Move foo.h [do NOT use foo.hh in this case] and foo.cpp there, like this:
/home/gabriel/dev/Arduino/Sketches/libraries/foo
├── foo.cpp
└── foo.h <==== NOT foo.hh in this case!
Now close and reopen the Arduino IDE, then go to Sketch --> Include Library --> foo, and it will automatically add the following line for you:
#include <foo.h>
The reason you can't use foo.hh in this case is simply because Arduino is looking for .h files only when you add your library include using the menus in this way. That's a bug as far as I'm concerned, and should probably be reported to the Arduino developers. Feel free to take that on.
Addendum:
16 Apr. 2019:
A google search for "arduino add include path" led me to this: https://forum.arduino.cc/index.php?topic=445230.0, where user #pert says:
In recent versions of the Arduino IDE(including 1.6.10) if you want to include libraries from the sketch folder you need to put them in a src subfolder. For example:
Blink
|_Blink.ino
|_src
|_BlinkLib
|_BlinkLib.h
He then says you can include like this:
#include "src/BlinkLib/BlinkLib.h"
I haven't tried this, but that'd be super useful if it works. Give it a shot and let me know if it works. Be sure to tell us which OS and Arduino IDE version you are using.
See Also:
Additional discussion on Github here: https://github.com/arduino/Arduino/issues/5186.
The official Arduino Library specification here: https://arduino.github.io/arduino-cli/latest/library-specification/.
Open a tab in your project for each file.
You can create a new file or import an existing file into your project.
This way you can use multiple *.ino, *.c, *.cpp and *.h files. I didn't find a way to import a local directory or to configure your project structure.
Place your folder inside libraries folder that is a subdirectory of your sketchbook directory.
Open Arduino IDE (if it is already open, quit it and reopen).
Go to Sketch->Include Library. You will find folder under Contributed Libraries section.
Choose folder and you are good to go.
According to "Sketch specification":
In Arduino IDE 1.6.5-r5 and older, no recursive compilation was done.
In Arduino IDE 1.6.6 - 1.6.9, recursive compilation was done of all subfolders of the sketch folder.
In Arduino IDE 1.6.10 and newer, recursive compilation is limited to the src subfolder of the sketch folder.
So, putting your source code files into 'src' subfolder should solve the problem. Tested in "Arduino IDE" v2.0.3.

C++ Include Relative Paths Broken

I am currently working on a large-scale financial application.
There are multiple modules that are compiled separately and then combined in a higher-level makefile.
Due to poor design, a lot of the header files include lots of local includes.
My problem is, when I include /src/equity/pdeModels/EqUtil.H inside my current source file /src/rwBatch/calcVol.C, all the includes at the start of EqUtil.H start to break, giving an error: ../../equity/pdeModels/EqUtil.H:15:30: fatal error: ulbase/SpotPrice.H: No such file or directory compilation terminated.
rwBatch and the equity folder are separately compiled and linked together later. Is this a problem with the makefile? Or how should I go about resolving this?
Indepth example:
/src/Module1/file1.C
/src/Module2/folderA/file2.H
/src/Module2/folderB/file3.H
When I write #include "../folderA/file2.H" in file1.C there are errors because of file2.H. At the start of file2.H there are several includes, for example #include "/folderB/file3.H" which, when compiled in file1.C leads to fatal error: /folderB/file3.H: No such file or directory compilation terminated.
Is this a problem with the makefile? Or how should I go about resolving this?
Specifying a path in an #include statement is almost always a bad idea. It takes information needed by the builder but not by the code, and locks it into the code.
As long as there are no name collisions (e.g. folderA/file3.h and folderB/file3.h) you can simply remove those paths. Change these:
// file1.c:
#include "../folderA/file2.H"
// file2.H:
#include "/folderB/file3.H"
to these:
// file1.c:
#include "file2.H"
// file2.H:
#include "file3.H"
And in your makefile (or other build system):
gcc -I/src/Module2/folderA -I/src/Module2/folderB -c /src/Module1/file1.C -o /wherever/file1.o
If there are name collisions, and you have a module that depends on two headers with the same name, you have some options. The simplest -- and probably best -- is to rename one or both of the headers. If you really must, you can put paths into the #include statements, but the paths should reflect the directory structure you use, not the other way around.

Cant compile rocksdb, dependencies not found

I am trying to compile a program that uses rocksdb.
According to the example in the official webpage, the only header i should add to my code is db.h.
Now, the file i am compiling is in folder A.
db.h however is in A/rocksdb-master/include/rocksdb/.
So, i add this line to my file:
#include "rocksdb-master/include/rocksdb"
It finds the file, but the problem is that inside db.h, i have this line:
#include "rocksdb/metadata.h"
And when i compile i get this error:
fatal error: rocksdb/metadata.h: No such file or directory
#include "rocksdb/metadata.h"
I mean, it's obvious. db.h is in the same folder as metadata.h, so it's fine that the compiler cant find any rocksdb folder. But i doubt that people who wrote this library don't know that.
Is there any other way to add the path's to compile it?
Why is it that the path from db.h are not relative to where it is located?
You should normally use just the following header in your project:
#include "rocksdb/db.h"
When compiling your own project, you should then add the RocksDB include path to the list of include directories. For example, if the RocksDB source code is in directory ../rocksdb-master, the include path will be ../rocksdb-master/include.
How to add the include path to the compiler flags is indeed compiler-specific. With g++ or clang, it's done by passing -I../rocksdb-master/include to the compiler when compiling your own program. Note that you many need to link against the RocksDB library as well.
And finally, you may need to include some more RocksDB headers if you use some of its advanced concepts, e.g. transactions.