The Arduino IDE bug (or a feature) which took whole night debugging… Until I looked into generated .ino.cpp
Original code (.ino file):
extern "C" __attribute__((used)) int cmd_misc_user(int argc, char **argv) {
return 0;
}
Arduino IDE generates:
#line 1 "D:\\Arduino\\espshell\\espshell.ino"
#include <Arduino.h>
#line 22 "D:\\Arduino\\espshell\\espshell.ino"
int cmd_misc_user(int argc, char **argv);
#line 32 "D:\\Arduino\\espshell\\espshell.ino"
void setup();
#line 47 "D:\\Arduino\\espshell\\espshell.ino"
void loop();
#line 22 "D:\\Arduino\\espshell\\espshell.ino"
extern "C" __attribute__((used)) int cmd_misc_user(int argc, char **argv) {
..
..
As a result of such “smart processing“ there are two different definitions of cmd_misc_user() : one with C linkage (as it intended, because it is a weak library symbol which I want to override) and another - with C++ linkage. Compilation fails.
Please, please, please.. Can we make prototypes generation to be optional? Like, to have a checkbox in the Preferences: “[x] I am too lazy, please generate prototypes for me“, so we can switch it off when Arduino IDE fails to generate correct and compilable code.
This problem is just one case of a bigger problem of Arduino IDE’s preprocessor: it is often (I had posted examples here before) generates wrong output when function have various __attribute_(()) in its definition. I’d suggest to modify the preprocessor to keep everything it does not understand untouched. Like, if it sees __attribute_ (()) it just copies it to the resulting prototype.
Or I am asking too much ? :). Unfortunately I am not a Java programmer so I can not help by writing code
BTW there is a workaround:
If you have functions with extern “C“ linkage in your .ino file, just make a forward declaration by yourself. This prevents Arduino IDE from generation it for you
e.g. instead of
extern "C" int some_function_in_ino_file() {
....
}
one have to
extern "C" int some_function_in_ino_file(); // forward
extern "C" int some_function_in_ino_file() { // body
....
}
Hi @vvb333007. The first thing you should always do when you are struggling to solve a difficult problem is to reduce your code down to the absolute minimum that will still produce the problem. Often I find that when I have done that, the solution becomes clear to me. Even if not, that minimal, reproducible, verifiable example (MCVE) will be very useful to those on the other end of a support request or bug report.
The code you shared has significant irrelevant complexity. It can be minimized down to something like this:
extern "C" void foo() {}
void setup() {}
void loop() {}
It turns out there is a subtle required condition for the fault to occur: a mismatch between the code in the sketch file on disk and the code staged in memory when Arduino IDE's editor is in an unsaved (AKA "dirty") state:
- Select File > Preferences... (or Arduino > Settings... for macOS users) from the Arduino IDE menus.
The "Preferences" dialog will open.
- Uncheck the "Auto save" checkbox.
- Click the "OK" button in the "Preferences" dialog.
The "Preferences" dialog will close.
- Select File > New Sketch from the Arduino IDE menus.
- Select File > Save from the Arduino IDE menus.
The "Save sketch folder as..." dialog will open.
- Save the sketch to any convenient name and location.
ⓘ Saving the sketch is not required, but I think it makes the demonstration easier to understand by eliminating the complexity introduced by using a staged new sketch.
- Change the sketch code to the following:
extern "C" void foo() {}
void setup() {}
void loop() {}
Do not save the sketch after making this change.
- Select any board from the Tools > Board menu.
- Select Sketch > Verify/Compile from the Arduino IDE menus.
Compilation fails spuriously:C:\Users\per\Documents\Arduino\sketch_jan24f\sketch_jan24f.ino: In function 'void foo()':
C:\Users\per\Documents\Arduino\sketch_jan24f\sketch_jan24f.ino:1:17: error: conflicting declaration of 'void foo()' with 'C' linkage
void setup() {
^
C:\Users\per\Documents\Arduino\sketch_jan24f\sketch_jan24f.ino:1:6: note: previous declaration with 'C++' linkage
void setup() {
^~~
- Select File > Save from the Arduino IDE menus.
The editor will change from a "dirty" state (as indicated by the presence of a ⬤ on the editor tab) to a saved state.
- Select Sketch > Verify/Compile from the Arduino IDE menus.
Compilation is successful.
It seems similar to No generated prototype for function with multi-line parameters in unsaved sketch · Issue #1800 · arduino/arduino-cli · GitHub. Note that, although the dependence on the editor being in a dirty state might lead us to conclude that this is caused by a bug in the Arduino IDE codebase, when the developer performed an investigation of arduino/arduino-cli#1800, they determined that it could indeed be reproduced using Arduino CLI alone, and thus that it was not an Arduino IDE bug (but rather either a bug in the Arduino CLI codebase or in a dependency of Arduino CLI).
Java hasn't been involved for the last decade. Function prototype generation is performed for Arduino IDE 2.x by the Arduino CLI tool. Arduino CLI is written in the Go programming language). Arduino CLI uses a separate tool named Ctags to parse the sketch code in order to gain the understanding of the code needed to determine which prototypes need to be generated, and where to inject them in the C++ code produced by sketch preprocessing. Ctags is written in C.
Even with an version of Arduino IDE 1.x newer than 1.0.6, the situation is similar. Function prototype generation is performed for Arduino IDE 1.x by the arduino-builder tool. Like Arduino CLI , arduino-builder is written in Go (Arduino CLI is actually originally based on the arduino-builder codebase). And arduino-builder also uses Ctags to parse the sketch code.
I have my files saved every time. Is it still possible to have such mismatch? The bug is 100% reproducible so I doubt it is about “dirty“ state. As I mentioned in a previous post: adding an explicit prototype resolves the bug.
I.e. when I add “extern “C“ in cmd_misc_user(int argc, char **argv);“ which is immediately followed by the function body - it compiles.
So I suspect something else but not “dirty“ state. I do save my code often, because I use some other tools along with Arduino IDE so I have to be sure that files are in sync for everyone
However, I am not a developer, you know your code better.
so it is ctags who generates wrong output? At whitch stage this happens? I am C developer, and it is C/C++ tool I can have a look and try to help in finding / fixing this bug
I was not able to reproduce the fault until I happened to try it with the editor in a "dirty" state, even when I was using the more complex code you provided. However, it might well be that I did not effectively reproduce the conditions you are producing because you did not provide sufficient information to allow me to do so.
Please provide the complete code of a sketch that will produce the fault when the sketch is in a saved state.
Please also tell us which version of Arduino IDE you are using so that we can be sure of that factor.
No. But if I uncomment the SHELL_USER_HANDLER() macro on line 23 (which is
# define SHELL_USER_HANDLER() extern "C" __attribute__((used)) int cmd_misc_user(int argc, char **argv)
then it compiles.
Note that there is no “dirty“ flag
I have moved your orphan post from Arduino IDE 2.3.7 is now available so it can stay with the topic.