My project (.ino file) started to become really big so i decided to split it in many files..
I followed this guide but my code started giving compiler errors. Although i fixed them i am not sure i know how this really works.
My code goes like this:
I supposed that included FS.h from mySPIFFS.cpp will "work" for mySPIFFS.h and dont want to be again.
So, do i have to include all these libraries in both cpp and h files?
Let's say i have 10 myFile.cpp, myFile.h files, and i include libraries like FS.h, Wire.h etc..
where is better to place them? in my main .ino file or in every cpp and h file?
I have to place #include "Arduino.h" in every cpp file. Will be included for every cpp multiple times or one time? (so, compiler knows that its already included), or i have to use #ifndef.. etc?
uzer123:
I supposed that included FS.h from mySPIFFS.cpp will “work” for mySPIFFS.h
It won’t. The .cpp file is a separate translation unit.
uzer123:
So, do i have to include all these libraries in both cpp and h files?
No. This line:
#include "mySPIFFS.h"
essentially just copy/pastes the contents of mySPIFFS.h into mySPIFFS.cpp. So if you move this line:
#include "FS.h"
to mySPIFFS.h then the declarations in FS.h will be seen by both mySPIFFS.h and mySPIFFS.cpp.
uzer123:
2) Let’s say i have 10 myFile.cpp, myFile.h files, and i include libraries like FS.h, Wire.h etc…
where is better to place them? in my main .ino file or in every cpp and h file?
Put them in each translation unit that needs the declarations from those header files. Note that the .ino file is also a separate translation unit (at the start of the compilation process it undergoes some minimal preprocessing to make it valid C++ and is then renamed with the .cpp file extension and compiled as C++). If you have multiple .ino files, they are concatenated together during compilation and compiled as a single translation unit.
uzer123:
3) I have to place #include “Arduino.h” in every cpp file.
You only need to do that if the file uses the Arduino core library’s API (e.g., digitalWrite(), digitalRead(), byte).
uzer123:
Will be included for every cpp multiple times or one time? (so, compiler knows that its already included), or i have to use #ifndef… etc?
No. The file has an include guard that prevents multiple inclusions in a single translation unit:
The first reference to fs ( fs:: ) is a namespace in which the class FS is defined. '::' is a scope qualifier.
&fs indicates that the argument required is a pointer. Confusingly, they have also used fs as the name of the argument but that name is not used anywhere.
So, if you call listDir(), the first argument has to be a pointer to an object of type fs::FS .
The first reference to fs ( fs:: ) is a namespace in which the class FS is defined. '::' is a scope qualifier.
&fs indicates that the argument required is a pointerreference. Confusingly, they have also used fs as the name of the argument but that name is not used anywhere.
So, if you call listDir(), the first argument has to be a pointer to an object of type fs::FS .
uzer123:
I supposed that included FS.h from mySPIFFS.cpp will "work" for mySPIFFS.h and dont want to be again.
Yes, the '#include "FS.h"' in mySPIFFS.cpp worked fine for the mySPIFFS.h that is included after it but it does nothing for the mySPIFFS.h included in main.ino. Putting the '#include "FS.h"' at the top of mySPIFFS.h works for both.
I've spent a day reading about good practices etc about splitting c++ code.
And i found my final adjustments to go along with your comments.
So, for future users, i would like to point the basic principles i followed:
to make the cpp and ino relatively independent #include necessary libraries to each cpp file and not put everything in the ino file.
In my example i put #include "FS.h" in both mySPIFFS.cpp and mySPIFFS.h and #include "mySPIFFS.h" in the "main" ino file.
So, if you make another ino project, you just include the mySPIFFS.h and your ready to go.
include only the absolutely necessary libraries in each .h file. So i use #include "FS.h" in mySPIFFS.h, but #include "FS.h", #include "SPIFFS.h" in mySPIFFS.cpp
i put global variables in the cpp file that was more relevant
put #include "Arduino.h" in h files (maybe your dont need it in every cpp but keep that in mind)
I didn't know the Arduino IDE supported #pragma once. The old MetroWerks compilers did. I loved that. Solved a LOT of bizarre issues. There was another #something that would put the defined text on a menu for navigating your source file. #somethingIForgetWhat - would give a menu break. #somethingIForgetWhat someText Would give a menu choice text.
Then, when editing, you could click your popup menu and go the the different sections of your code. I miss that.
It's not a matter of the Arduino IDE supporting it. It's a matter of the compiler supporting it. Most platforms use GCC, which does support #pragma once, but it's not guaranteed that every platform's compiler will support it.
I really don't see the benefit of #pragma once. The working of standard include guards are obvious at a glance and only take two extra lines of code. The include guard macro can be useful for other purposes too.