After opening the espurna project in platformio IDE code completion doesn't work like with regular Platformio projects (mutiple .cpp files). I believe the problem stems from espurna being built using multiple .ino files. Is there any way to enable full code completion in VS Code editor? I tried setting "C_Cpp.intelliSenseEngineFallback": "Disabled" flag in settings.json, but it shows multiple errors with the code.
Your assessment is correct, see https://github.com/platformio/platformio-vscode-ide/issues/378
I found workaround solution: place #include preprocessor directives for every .ino file you use when editing the code, then when compiling simply comment out these includes.
I don't think that's an option. Maybe we should move all .ino files to .cpp?
Only might-be downside is lto, as every file will be different .o
I did test this briefly in ArduinoIDE with ezTime example, renaming .ino to .cpp + Arduino.h include and having barebones src.ino (naming rules elude me, basing on default pio dir name):
extern void setup();
extern void loop();
It would be awesome to move to .cpp. I'm also using PlatformIO and Visual Studio Code.
Next release of cpp-tools will include support for comments and has goto definition support.
I'm aware this will be a lot of work, but I think that with those changes navigation will be better. Besides that, it will be easier to continue developing ESPurna.
C/C++ for Visual Studio Code version 0.21.0 was just released (https://github.com/Microsoft/vscode-cpptools/releases/tag/0.21.0)
It supports documentation comments on hover and includes many fixes - Go to definition finally works.
I think this is another argument for moving from .ino to .cpp.
I still wonder if definitions can show up by using
"forcedInclude": [".../code/espurna/config/all.h"]
idk if platformio plugin is actively preventing indexing (notification nagging about the ino->cpp switch), or it just does not work like that.
Regarding the switch, bare minimum to do is to move forward declarations from prototypes.h to somewhere in the include search-path and name them like relay.h, button.h etc.
I second that. It would make the project more cpp-friendly.
@mcspr can I help in any way?
I mostly use ESPurna as a knowledge base and best practices guide, but having intellisense and comments would help a lot of people like me.
I'm still very new to microcontroller programming (mostly doing C#) but with proper guidance everything is possible :)
By having prototypes I mean that every public module method should have a declaration before implementation, so other things can refer to it during compilation:
# foo.h
#include <iostream>
void foo(int);
```
void foo(int bar) {
std::cout << bar << std::endl;
}
```cpp
# some_other_module.cpp
#include "foo.h"
void foobar() {
foo(100)
}
Let's start with this maybe.
Plus moving sensors into .cpp proper
Espurna is a huge project, its not feasible to develop such projects in Arduino IDE, so why the ino files, is this a legacy issue?
This is a much needed feature for new developers on the project.
for now I included all the ino files in espurna.ino as mentioned by @azeth , intellisese seems to be working partially, so how do @mcspr or @xoseperez develop without intellisense, is there any workaround?
@ali80 There is a workaround, albeit it might seem convoluted at first. Just check out what pio init -b d1_mini example project will generate at .vscode/c_cpp_properties.json - you will see SDK + Core + Core libraries paths. I tried my best to keep-up with our file-local includes, but there are still some issues there (obvious and easily fixable, though), so we should be able to edit files based on the default environment settings (see platformio.ini top)
One tricky thing is to specify every used library manually, as PIO won't do it on it's own for some reason:
${workspaceFolder}/.pio/libdeps/default_env/library_name${workspaceFolder}/libraries/library_name which will be used by setting ESPURNA_PIO_SHARED_LIBRARIES environment variable<global-PIO-installation>/lib/library_name (it it was installed manually via pio lib -g install)As mentioned above, we also need to add:
"forcedInclude": ["${workspaceFolder}/espurna/config/all.h"],
We can hit an issue with conflicting directories that reference git and non-git versions of libraries, which is not easily discoverable outside of PIO runtime e.g. pio project config --json-output won't specify library paths. Likely fix for this issue is to vendor libraries beforehand, although idk how PIO can keep them up-to-date in the .json
I do try to use vscode from time to time, but I mostly end up using it for host-built code examples that are later c/p here. vim + ctags over code+libraries otherwise help out to remember how APIs work. Which is a questionable practice to expect from newcomers, that is true.
@mcspr I deveoped faily big projects with PIO in VScode and and it's automatic dependency detection is pretty good(with cpp files), I think the main issue is the ino files which are different from standard cpp files and PIO would merge all of them before starting the compiler, this this a non standard step specific to arduino platform and ino files, vscode intellisense wont work without this merge. also this might be the reason why pio dependency detection doesnt work on this project.
So to make the it work I would manually include all the ino files in the espurna.ino but only for intellisense and not for the actual compilation since they would be readded again and cause error.
What I did was search for all the ino files in the project, included all of them after all the includes in the espurna.ino file. and used preprocessor to limit them only for intellisense, defined the preprocessor in the c_cpp_properties.json
list of the included ino files:
// THIS SECTION IS ONLY INCLUDED IN INTELLISENSE
#ifdef __ESPURNA_INT_FIX
#include "utils.ino"
#include "web.ino"
#include "uartmqtt.ino"
#include "tuya.ino"
#include "thinkspeak.ino"
#include "thermostat.ino"
#include "terminal.ino"
#include "system.ino"
#include "telnet.ino"
#include "storage_eeprom.ino"
#include "ssdp.ino"
#include "settings.ino"
#include "scheduler.ino"
#include "sensor.ino"
#include "rpnrules.ino"
#include "rtcmem.ino"
#include "rfm69.ino"
#include "rpc.ino"
#include "rfbridge.ino"
#include "relay.ino"
#include "ota_web.ino"
#include "ota_arduinoota.ino"
#include "ota_asynctcp.ino"
#include "ota_httpupdate.ino"
#include "ota.ino"
#include "ntp.ino"
#include "ntp_legacy.ino"
#include "mqtt.ino"
#include "netbios.ino"
#include "nofuss.ino"
#include "mdns.ino"
#include "migrate.ino"
#include "light.ino"
#include "lightfox.ino"
#include "llmnr.ino"
#include "led.ino"
#include "ir.ino"
#include "i2c.ino"
#include "influxdb.ino"
#include "homeassistant.ino"
#include "gpio.ino"
#include "domoticz.ino"
#include "encoder.ino"
#include "debug.ino"
#include "crash.ino"
#include "button.ino"
#include "board.ino"
#include "api.ino"
#include "alexa.ino"
#include "ws.ino"
#include "wifi.ino"
#endif // end of INTELLISENSE ONLY SECTION
So why the ino files? I think using the cpp instead would fix all of this
True, effectively you can see everything that PIO generates inside of code/espurna/espurna.ino.cpp file. It is build-time temporary, removed with atexit() callback inside of PIO Core. Either C-z pio run -e ... running in CLI or just hijack Platformio Core python code where it happens. Also note that .ino should probably be alphabetically sorted
In general .ino has over .cpp:
Nonetheless, I will try out conversion, but I already stumbled upon recursive include problem :)
@mcspr
note that .ino should probably be alphabetically sorted
thanks for mentioning it, but it would be dangerous if it actually makes a difference
I think ino files should actually be slower to compile since a single change anywhere in the code (ino file) would result in the recompile of the large merged file espurna.ino.cpp but maybe there is a threshold where checking a lot of small files and then compiling a single one of them still be slower than compiling a large merged file,specially since this detection of changed files is done but PIO itself which is slow.
most modern languages dont need forward declares for functions (I think compilers of c era where simple and lean and moved this to programmer side to make compiler job easier) but it is so little to pay to write standard c instead non standard ino
at this point your ino files are essensially glorified .h files(?) so maybe the right order would be
espurna.inoespurna.ino to espurna.cppnow if this works this is a standard cpp project and then you can think of which implementaions to move out of .h files to their respective .cpp file
well this doesn't work, too many forward declarations needed :)
Most helpful comment
I don't think that's an option. Maybe we should move all .ino files to .cpp?