Prototypes placed wrongly for large project

My project has grown over the years. Now there is more than 4kB text between the top of ino and setup(). This makes the compilation fail in some cases. I use a number of tabs in the Arduino IDE. For a failed compilation I found the file “D:\Temp\arduino_build_595143\sketch\mqtt_RullgardinVardagsrum_v004.ino.cpp”, where I could see that the automatically inserted prototypes crashed an enum.

Is this a known bug/limitation?

Arduino 1.8.12
Board: ESP8266
OS: Windows 7

Below is first part of that file:

#line 1 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\mqtt_RullgardinVardagsrum_v004.ino"
// Wemos 4M, 2M LittleFS, DOUT

#define FASTLED_INTERNAL
#define USING_AXTLS
#include <Arduino.h>
#include <dt_esp_common.h>
#include <FastLED.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <MQTTClient.h>
#include <TimeLib.h>
#include <Ticker.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
//#include <EEPROM.h>
#include <ESP_EEPROM.h> // https://github.com/jwrw/ESP_EEPROM (via Libraries)
#include "FS.h"
#include <LittleFS.h>
//#include <ESP8266mDNS.h>
// #include <ArduinoJson.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
//#include <DigiSensor.h>
#include <CRC.h>  // https://github.com/hideakitai/CRC (via Libraries)
//#include <StackThunk.h> // For BSSL space check
#include <ESP8266Ping.h>
#include <PolledTimeout.h> // https://github.com/esp8266/Arduino/blob/master/cores/esp8266/PolledTimeout.h

/************************* WiFi Access Point *********************************/
#define MQTT_SERVER      "aaa.aaaaaa.aaa"
#define MQTT_SERVERPORT  8883 // use 8883 for SSL
#define MQTT_CLIENTID    "vardrull"
#define MQTT_USERNAME    "aaaaaaa"
#define MQTT_KEY         "aaaaaaaaaaaaaaaa"
#define PO_APP_TOKEN     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#define PO_USER_KEY      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#define NTP_SERVER1      "se.pool.ntp.org"
#define OTA_PASSWORD     "aaaaaaaaaaaaaaa"

const char WiFI_AP_SSID[][12] = {
  "aaaa",
  "aaaa",
  "aaaaaa aaa",
  "aaaaaaaa",
};

const char WiFI_AP_PASS[][20] = {
  "aaaaaaaaaaaaaaaa",
  "aaaaaaaaa",
  "aaaaaaaa",
  "aaaaaaaaaaaaaaa",
};

#define USE_SERIAL false
#define USE_CHECKDELAY false
#define DEBUG_ERROR false
#define DEBUG_WARNING false
#define DEBUG_INFO false
#define DEBUG_NOTICE false
#define S if(USE_SERIAL)Serial
#define DEBUG_E if(DEBUG_ERROR)Serial
#define DEBUG_W if(DEBUG_WARNING)Serial
#define DEBUG_I if(DEBUG_INFO)Serial
#define DEBUG_N if(DEBUG_NOTICE)Serial

// Hardware
// Wemos D0=16 D1=5 D2=4 D3=0 D4=2 D5=14 D6=12 D7=13 D8=15 D9/RX=3 D10/TX=1
// SonOff Lilla: Femte hålet=14. Stora: 2.5mm tip-ring-ring-sleeve -> GPIO14, GPIO4(nc), GND, 3V3
#define PIN_Button 15 // Input-pin for the manual switch on the motor assembly 
#define PIN_FastLed_Data 0
#define PIN_IRDIODE -1
#define PIN_LED 2
#define PIN_PIR -1
#define PIN_RADAR -1
#define PIN_Relay -1
#define PIN_Stepper_Enable 13
#define PIN_Stepper_Direction 14
#define PIN_Stepper_Step 12

// FastLed
#define NUM_LEDS 0  // 0=not installed
CRGB leds[NUM_LEDS];
#define RGB_LOW_OK "#000000" // https://github.com/FastLED/FastLED/wiki/Pixel-reference
#define RGB_HIGH_OK "#FF9F6F"
#define RGB_LOW_NOK "#400000"
#define RGB_LOW_NOK2 "#400040"
#define RGB_HIGH_GREEN "#00FF00"
#define RGB_HIGH_RED "#FF0000"
#define RGB_HIGH_ORANGE "#FF8C00"
#define RGB_LOW_ORANGE "#3F2C00"
#define RGB_SIENNA "#A0522D"


// Usersettings
struct usersettings { // Default values
  bool sendPush = false;
  uint8_t selectAP = 0;
  bool WiFienabled = true;
  bool relayAuto = true;
  float WiFiOutputPower = 8.0;
  char fpPushoverNet[60];
  int8_t mqttdebuglevel = 3;
  uint16_t CRC = 0; //Must be the last member of the struct
} us;


// Button
enum Button { NONE, SHORT_PRESS, LONG_PRESS, SUPER_LONG_PRESS, PRESSING, LONG_PRESSING, SUPER_LONG_PRESSING };

// Pushover
enum PO_URGENCY { po_sendN_fileY, po_sendY_fileN, po_sendY_fileY };

// Digisensor
//DigiSensor PIR( PIN_PIR, true );
//DigiSensor RADAR( PIN_RADAR );

// Ticker
//void ledFlasher_int();
//Ticker Ticker_ledFlasher(ledFlasher_int, 500);
Ticker Ticker_OTAtimeOut;

// WiFi
//WiFiClient netClient;
WiFiClientSecure netClient; // or... use WiFiClientSecure for SSL
uint16_t numWiFiReconnects = 0;

// MQTT
MQTTClient mq(256);
unsigned long mqGotConnection = 0; // millis
uint16_t numReconnects = 0;


// Other
bool OTAupdating = false; // OTA update ongoing, inhibit work
bool timeToUploadLogfile = false;
String notepad;

// Rullgardin
enum MotorState {
  SLEEPING, RUNNING_UP, RUNNING_DOWN,
  RUNNING_TO_POS, STOPPING
};
enum MotorDirection {
  DOWN, UP
#line 170 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\mqtt_RullgardinVardagsrum_v004.ino"
void setup();
#line 192 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\mqtt_RullgardinVardagsrum_v004.ino"
void loop();
#line 16 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\buttonledrelay.ino"
int led(int state);
#line 53 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\buttonledrelay.ino"
int8_t relay(int8_t state);
#line 57 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\buttonledrelay.ino"
int8_t relay(int8_t cmd, int16_t parameter);
#line 165 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\buttonledrelay.ino"
void manageButton();
#line 182 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\buttonledrelay.ino"
Button buttonHandler();
#line 230 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\buttonledrelay.ino"

<-- Here I cut away some 140 lines -->

void ManualSwitchControl();
#line 354 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\rullgardin.ino"
void RFRemoteSwitchControl( uint32_t rfCode);
#line 378 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\rullgardin.ino"
void rullgardin_update_1s();
#line 15 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\time.ino"
time_t local();
#line 29 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\time.ino"
bool isDST( uint32_t unixTime );
#line 56 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\time.ino"
void setup_time();
#line 65 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\time.ino"
void periodic_time_update();
#line 126 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\time.ino"
void sendNTPpacket(IPAddress &address);
#line 6 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\uploadlog.ino"
int8_t uploadInternalLog();
#line 10 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\uploadlog.ino"
int8_t uploadFile( const char * filePathAndName, const char * uploadFileName);
#line 5 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\wifi.ino"
void wifiManager(int8_t cmd );
#line 189 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\wifi.ino"
void manageWiFiConnecton();
#line 220 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\wifi.ino"
void wifiConnect();
#line 145 "D:\\Mina Dokument\\Arduino\\MQTT\\mqtt_RullgardinVardagsrum_v004\\mqtt_RullgardinVardagsrum_v004.ino"
};
enum MotorCommand {
  STOP, RUN_UP, RUN_DOWN,
  RUN_HOME, RUN_BOTTOM,
  RUN_TO_POS, SET_HOME,
  SET_BOTTOM, MAIN_LOOP,
  MAX_TIME
};
/* Step motor control */
#include <AccelStepper.h>
#define MAX_RUNNING_TIME 60
#define DEFAULT_STEPS_TO_BOTTOM 103000L /* Default walue of how far down the down-position is */

AccelStepper stepper(1, PIN_Stepper_Step, PIN_Stepper_Direction); // type, step-pin, direction-pin
bool automatic = true;
uint8_t lightLevel = 255;


// Debug
uint16_t debugMessageNumber = 0;
/*
    mq.publish( plog( "node/debug/" MQTT_CLIENTID "/%04d", debugMessageNumber++), p("%s xxx", now_char()), true, 0); // ... retained, QoS
*/


void setup() {
  eeCommit(); // Early in setup
  rgbLED("#404040");
  setup_mq();
  other_setup();
  led(4); //If to update LED status to MQTT. 4=not 5=update
  led (1);
  relay(5, 0); // If On/Off/Toggle shall disable Auto
  rgbLED("#202020");
  
<-- Here I cut away everything below, some 2700 lines -->

Don’t have time to look at the code closely, but with enums you often need to put in your own function prototypes, because the auto prototype gets placed before the enum is declared.

You can usually work around the problem of using a struct as a function argument by adding the 'struct' keyword in the argument declaration. Those get copied to the prototype and the compiler doesn't care if the type is declared as long as it knows that it is a struct.

This sketch reports "error: 'bar' was not declared in this scope":

void setup() {}

struct bar {int X; int Y; int Z;};

void DoBar(bar barArg) {DoBar(barArg);}

void loop() {}

This sketch has no errors or warnings:

void setup() {}



struct bar {int X; int Y; int Z;};


void DoBar(struct bar barArg) {DoBar(barArg);}

void loop() {}

Thanks for you replies!

When compliling the sketch, I get the error:

mqtt_RullgardinVardagsrum_v004:170:1: error: expected '}' before 'void'

 void setup() {

 ^

This is because the automatic prototypes(*) are placed in the middle of my global enum 'MotorDirection'.

I think the intention is that Arduino shall put them immediately before setup(), and it most often do so, but not now.

If I add/removesome code-lines above, it will put the prototypes somewhere else, crashing something else. And even if it does not crash anything, all my code between the automatic prototypes and setup() will be after the prototypes, so the code will not compile anyway, complaining on things like "rullgardin:29:19: error: 'MotorCommand' was not declared in this scope".

(*) From line starting with "#line 170" to line starting with "#line 145". I do not understand why last line starts with '#line...' and not with a prototype.

The solution is very simple --- ALWAYS supply your own prototypes as if you were working in a regular C++ development environment.

You may also want to check out Eclipse / Sloeber. After switching to it, I can't see ever doing serious development in the standard Arduino IDE. But, I will check out the "Pro" version once it cooks awhile.

gfvalvo:
The solution is very simple --- ALWAYS supply your own prototypes as if you were working in a regular C++ development environment.

I am not very skilled in the world of .h and .cpp and their relationship. I have 13 tabs, .ino-files, for my sensors. Would it be enough if I put prototypes uppermost in each of them?

Would it also be possible to move the global enums to those .ino-files? If I do they are not found from the other tabs.

I don't use the multiple .ino file technique. So, I can't comment on where prototypes should be placed to be effective once the Arduino IDE smashes all the .ino files together. My recommendation is to use proper .h and .cpp files as described in My Reply #3 Here.