Compiling errors on libraries that work on Arduino IDE

Hi there.
A coupke of days ago I transitioned from the Arduino IDE (making long programs in there was a nightmare) to VSCode with platformIO.

The problem now (that has happened to me in many other libraries) is that when I compile code that was copied from and Arduino IDE sketch the code compiles OK but it throws errrors on the libraries (which have not been modified by me).

Let me give you an example. Using TinyGSM library and its MQTT example. The code works fine on Arduino IDE and when I compile in platformIO it throws this errrors:

> Executing task in folder test gsm: platformio.exe run <

Processing megaatmega2560 (platform: atmelavr; board: megaatmega2560; framework: arduino)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/megaatmega2560.html
PLATFORM: Atmel AVR 1.15.0 > Arduino Mega or Mega 2560 ATmega2560 (Mega 2560)
HARDWARE: ATMEGA2560 16MHz, 8KB RAM, 248KB Flash
PACKAGES: toolchain-atmelavr 1.50400.190710 (5.4.0), framework-arduinoavr 4.1.1
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 16 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <PubSubClient> 2.7
|-- <TinyGSM> 0.9.7
Compiling .pio\build\megaatmega2560\src\main.cpp.o
Archiving .pio\build\megaatmega2560\lib314\libPubSubClient_ID89.a
Compiling .pio\build\megaatmega2560\FrameworkArduino\HardwareSerial2.cpp.o
Compiling .pio\build\megaatmega2560\FrameworkArduino\HardwareSerial3.cpp.o
Compiling .pio\build\megaatmega2560\FrameworkArduino\IPAddress.cpp.o
Compiling .pio\build\megaatmega2560\FrameworkArduino\PluggableUSB.cpp.o
Compiling .pio\build\megaatmega2560\FrameworkArduino\Print.cpp.o
Compiling .pio\build\megaatmega2560\FrameworkArduino\Stream.cpp.o
Compiling .pio\build\megaatmega2560\FrameworkArduino\Tone.cpp.o
In file included from C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmCommon.h:31:0,
                 from C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmClientSIM800.h:22,
                 from C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmClientSIM808.h:13,
                 from C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmClient.h:24,
                 from src\main.cpp:95:
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmFifo.h: In function 'void loop()':
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmFifo.h:4:1: error: a template declaration cannot appear at block scope
 template <class T, unsigned N>
 ^
In file included from C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmClientSIM800.h:22:0,
                 from C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmClientSIM808.h:13,
                 from C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmClient.h:24,
                 from src\main.cpp:95:
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmCommon.h:57:11: error: expected identifier before '{' token
 namespace {
           ^
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmCommon.h:58:3: error: a template declaration cannot appear at block scope
   template<typename T>
   ^
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmCommon.h:70:3: error: a template declaration cannot appear at block scope
   template<typename... Args>
   ^
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmCommon.h:83:1: error: a template declaration cannot appear at block scope
 template<class T>
 ^
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmCommon.h:95:1: error: a template declaration cannot appear at block scope
 template<class T>
 ^
C:\Users\marti\appdata\roaming\spb_data\.platformio\lib\TinyGSM_ID1287\src/TinyGsmCommon.h:142:44: error: a function-definition is not allowed here before '{' token
 String TinyGsmDecodeHex7bit(String &instr) {
                                            ^
src\main.cpp:84:12: warning: unused variable 'apn' [-Wunused-variable]
 const char apn[]  = "telefonica.es";
            ^
src\main.cpp:85:12: warning: unused variable 'user' [-Wunused-variable]
 const char user[] = "telefonica";
            ^
src\main.cpp:86:12: warning: unused variable 'pass' [-Wunused-variable]
 const char pass[] = "telefonica";
            ^
src\main.cpp:89:13: warning: unused variable 'broker' [-Wunused-variable]
 const char* broker = "test.mosquitto.org";
             ^
src\main.cpp:91:13: warning: unused variable 'topicLed' [-Wunused-variable]
 const char* topicLed = "GsmClientTest/led";
             ^
src\main.cpp:92:13: warning: unused variable 'topicInit' [-Wunused-variable]
 const char* topicInit = "GsmClientTest/init";
             ^
src\main.cpp:93:13: warning: unused variable 'topicLedStatus' [-Wunused-variable]
 const char* topicLedStatus = "GsmClientTest/ledStatus";
             ^
src\main.cpp:239:1: error: expected '}' at end of input
 }
 ^
*** [.pio\build\megaatmega2560\src\main.cpp.o] Error 1
=============================================================================================== [ERROR] Took 4.24 seconds ===============================================================================================
The terminal process terminated with exit code: 1

Terminal will be reused by tasks, press any key to close it.

As you can see the errors appear on the library files.

Can you show the code of main.cpp (at least a major piece around line 95)?

1 Like

The code around line 95:
// MQTT details

const char* broker = "test.mosquitto.org";

const char* topicLed = "GsmClientTest/led";

const char* topicInit = "GsmClientTest/init";

const char* topicLedStatus = "GsmClientTest/ledStatus";

#include <TinyGsmClient.h> //this is line 95

#include <PubSubClient.h>

#ifdef DUMP_AT_COMMANDS

#include <StreamDebugger.h>

StreamDebugger debugger(SerialAT, SerialMon);

TinyGsm modem(debugger);

#else

The whole code: (in case it’s needed)
#include <Arduino.h>

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
/**************************************************************
 *
 * For this example, you need to install PubSubClient library:
 *   https://github.com/knolleary/pubsubclient
 *   or from http://librarymanager/all#PubSubClient
 *
 * TinyGSM Getting Started guide:
 *   https://tiny.cc/tinygsm-readme
 *
 * For more MQTT examples, see PubSubClient library
 *
 **************************************************************
 * Use Mosquitto client tools to work with MQTT
 *   Ubuntu/Linux: sudo apt-get install mosquitto-clients
 *   Windows:      https://mosquitto.org/download/
 *
 * Subscribe for messages:
 *   mosquitto_sub -h test.mosquitto.org -t GsmClientTest/init -t GsmClientTest/ledStatus -q 1
 * Toggle led:
 *   mosquitto_pub -h test.mosquitto.org -t GsmClientTest/led -q 1 -m "toggle"
 *
 * You can use Node-RED for wiring together MQTT-enabled devices
 *   https://nodered.org/
 * Also, take a look at these additional Node-RED modules:
 *   node-red-contrib-blynk-ws
 *   node-red-dashboard
 *
 **************************************************************/
#include <Arduino.h>
// Select your modem:
//#define TINY_GSM_MODEM_SIM800
 #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_SARAR4
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
// #define TINY_GSM_MODEM_SEQUANS_MONARCH

// See all AT commands, if wanted
 //#define DUMP_AT_COMMANDS

// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon

// Range to attempt to autobaud
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 38400

// Add a reception delay, if needed
#define TINY_GSM_YIELD() { delay(2); }

// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial

// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1

// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
//SoftwareSerial SerialAT(7, 8); // RX, TX


// Your GPRS credentials
// Leave empty, if missing user or pass
const char apn[]  = "telefonica.es";
const char user[] = "telefonica";
const char pass[] = "telefonica";

// MQTT details
const char* broker = "test.mosquitto.org";

const char* topicLed = "GsmClientTest/led";
const char* topicInit = "GsmClientTest/init";
const char* topicLedStatus = "GsmClientTest/ledStatus";

#include <TinyGsmClient.h>
#include <PubSubClient.h>

#ifdef DUMP_AT_COMMANDS
  #include <StreamDebugger.h>
  StreamDebugger debugger(SerialAT, SerialMon);
  TinyGsm modem(debugger);
#else

TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
PubSubClient mqtt(client);

#define LED_PIN 13
int ledStatus = LOW;

long lastReconnectAttempt = 0;

void setup() {

  // Set console baud rate
  SerialMon.begin(115200);
  delay(10);

  // Set your reset, enable, power pins here
  pinMode(LED_PIN, OUTPUT);



  SerialMon.println("Wait...");

  // Set GSM module baud rate
  SerialAT.begin(19200);
  delay(3000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  // modem.init();

  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem: ");
  SerialMon.println(modemInfo);

  // Unlock your SIM card with a PIN
  //modem.simUnlock("1234");

#if TINY_GSM_USE_WIFI
  SerialMon.print(F("Setting SSID/password..."));
  if (!modem.networkConnect(wifiSSID, wifiPass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");
#endif

#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_XBEE
  // The XBee must run the gprsConnect function BEFORE waiting for network!
  modem.gprsConnect(apn, gprsUser, gprsPass);
#endif

  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork(240000L)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

  if (modem.isNetworkConnected()) {
    SerialMon.println("Network connected");
  }

#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS
    SerialMon.print(F("Connecting to "));
  SerialMon.print(apn);
    if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
    SerialMon.println(" fail");
      delay(10000);
      return;
  }
  SerialMon.println(" OK");
#endif

  // MQTT Broker setup
  mqtt.setServer(broker, 1883);
  mqtt.setCallback(mqttCallback);
}

boolean mqttConnect() {
  SerialMon.print("Connecting to ");
  SerialMon.print(broker);

  // Connect to MQTT Broker
  boolean status = mqtt.connect("GsmClientTest");

  // Or, if you want to authenticate MQTT:
  //boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass");

  if (status == false) {
    SerialMon.println(" fail");
    return false;
  }
  SerialMon.println(" OK");
  mqtt.publish(topicInit, "GsmClientTest started");
  mqtt.subscribe(topicLed);
  return mqtt.connected();
}

void loop() {

  if (!mqtt.connected()) {
    SerialMon.println("=== MQTT NOT CONNECTED ===");
    // Reconnect every 10 seconds
    unsigned long t = millis();
    if (t - lastReconnectAttempt > 10000L) {
      lastReconnectAttempt = t;
      if (mqttConnect()) {
        lastReconnectAttempt = 0;
      }
    }
    delay(100);
    return;
  }

  mqtt.loop();
}

void mqttCallback(char* topic, byte* payload, unsigned int len) {
  SerialMon.print("Message arrived [");
  SerialMon.print(topic);
  SerialMon.print("]: ");
  SerialMon.write(payload, len);
  SerialMon.println();

  // Only proceed if incoming message's topic matches
  if (String(topic) == topicLed) {
    ledStatus = !ledStatus;
    digitalWrite(LED_PIN, ledStatus);
    mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
  }
}

When you created the PlatformIO project, something seem to have gone wrong. It looks as if you have copied your Arduino code into the PlatformIO template of main.cpp without emptying it first. Now you have two setup() and two loop() functions.

To fix it delete the first six lines. Possibly there a stray closing brace } somewhere that needs to be deleted as well.

Furthermore I strongly recommend you rearrange your code such that all #include are before any declarations such as const char apn[] ... or TinyGsm modem(SerialAT);.

2 Likes

Wow. I feel so stupid right now.

Thank you so much. After that everything compiled except for one function which was missing the header on the top of the .cpp file

1 Like

If it makes you feel any better, I must confess to have done the exactly same thing… you really stop and wonder just how did you do/miss that when you realise that the culprit is! :laughing: