Adafruit GPS Library cannot compile because SoftwareSerial is missing

I’m trying to compile my project but it fails because Adafruit GPS cannot find SoftwareSerial.h…
The compilation works using arduino’s IDE but I can’t seem to understand why.

I have tried adding the SoftwareSerial Library by Arduino from the lib manager but it still won’t work…

SoftwareSerial.h is NOT present in C:\Users\username\.platformio\packages\framework-arduino-avr\cores\arduino.

In file included from .pio\libdeps\nano\Adafruit GPS Library\src\Adafruit_GPS.cpp:31:0:
.pio\libdeps\nano\Adafruit GPS Library\src/Adafruit_GPS.h:58:28: fatal error: SoftwareSerial.h: No such file or directory```

Right because it’s in C:\Users\<user>\.platformio\packages\framework-arduino-avr\libraries\SoftwareSerial.

Full platformio.ini? You’ve got lib_deps = SoftwareSerial along with your other library dependencies in there right? Since SoftwareSerial is built-in, it must be referred to with just its name, and not the owner/lib@version syntax from the library manager.

It is present in the directory you mention though… here is my platformio.ini

platform = atmelavr
board = nanoatmega328
framework = arduino
lib_deps = 
	marcoschwartz/LiquidCrystal_I2C@^1.1.4
	seeed-studio/Grove 3Axis Compass V2.0 BMM150@^1.0.0
	arduino-libraries/Servo@^1.1.7
	adafruit/Adafruit GPS Library@^1.5.3
	featherfly/SoftwareSerial@^1.0.0

Do I still need to download it from the library manager or is that jus redundant

I can reproduce your error on SoftwareSerial being found, currently with my platformio.ini of

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
lib_deps = 
	marcoschwartz/LiquidCrystal_I2C@^1.1.4
	seeed-studio/Grove 3Axis Compass V2.0 BMM150@^1.0.0
	arduino-libraries/Servo@^1.1.7
	adafruit/Adafruit GPS Library@^1.5.3
    arduino-libraries/SD @ 1.2.4
	SoftwareSerial
lib_ldf_mode = deep+

and the test code from here.

It really looks like the PlatformIO library dependency finder has a slight problem here. I’ll investigate.

I’ve added SoftwareSerial to platformio.ini

platform = atmelavr
board = nanoatmega328
framework = arduino
lib_deps =
	marcoschwartz/LiquidCrystal_I2C@^1.1.4
	seeed-studio/Grove 3Axis Compass V2.0 BMM150@^1.0.0
	arduino-libraries/Servo@^1.1.7
	adafruit/Adafruit GPS Library@^1.5.3
	SoftwareSerial

But it still won’t compile and gives me the same errors

And I tried the default code, doesn’t work either

@ivankravets the LDF seems to have a problem here. Latest PIO core. Minimal example

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
lib_deps = 
	adafruit/Adafruit GPS Library@^1.5.3
    arduino-libraries/SD @ 1.2.4
	SoftwareSerial
lib_ldf_mode = deep+
#include <Arduino.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

// you can change the pin numbers to match your wiring:
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);

void setup() {}
void loop(){}

The LDF is unable to identify the dependency of the GPS library to the SoftwareSerial, even on deep+ or chain+.

Dependency Graph
|-- <Adafruit GPS Library> 1.5.3
|   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|-- <SD> 1.2.4
|   |-- <SPI> 1.0
|-- <SoftwareSerial> 1.0
|-- <SPI> 1.0
|-- <Wire> 1.0
Building in release mode

As soon as I comment out line 57 and 59 in the library, the dependency is recognized and the build goes through.

//#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
#include <SoftwareSerial.h>
//#endif
Dependency Graph
|-- <Adafruit GPS Library> 1.5.3
|   |-- <SoftwareSerial> 1.0
|   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|-- <SD> 1.2.4
|   |-- <SPI> 1.0
|-- <SoftwareSerial> 1.0
|-- <SPI> 1.0
|-- <Wire> 1.0
Building in release mode

Note the additional SoftwareSerial beneath Adafruit GPS Library, which previously wasn’t there.

@poulette, please do the following:

  1. Close VSCode.
  2. Open a windows explorer to Documents\PlatformIO\Projects<your project>
  3. Modify the platformio.ini of your project to
[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
lib_deps = 
   marcoschwartz/LiquidCrystal_I2C@^1.1.4
   seeed-studio/Grove 3Axis Compass V2.0 BMM150@^1.0.0
   arduino-libraries/Servo@^1.1.7
   arduino-libraries/SD @ 1.2.4
   Adafruit GPS Library
   SoftwareSerial
  1. Remove the .pio folder of the project
  2. Download the file https://github.com/adafruit/Adafruit_GPS/archive/1.5.3.zip
  3. Open the ZIP file and pull the Adafruit_GPS-1.5.3 folder from inside there into the lib folder of the project
  4. Rename the Adafruit_GPS-1.5.3 folder to Adafruit GPS Library
  5. Open the file Adafruit GPS Library\src\Adafruit_GPS.h and search for the code block
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
#include <SoftwareSerial.h>
#endif
  1. Change that codeblock to
//#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
#include <SoftwareSerial.h>
//#endif
  1. Re-Open VSCode and your project and hit the build button.

Building should give you a success now.

This procedure effectively makes PlatformIO use the GPS library that you put in the lib/ folder, which has a patch for removing a conditional include line that PlatformIO currently has problems with. I’m sure the bug will be solved ASAP and that procedure won’t be necessary then, but if you want to compile the firmware now, then you have to do that modification.

1 Like

It works !
Thank you so much for your help and making such a comprehensive answer !

Could you try to move SoftwareSerial in lib_deps on top of all dependencies?

1 Like

Nope, doesn’t change anything. WIth

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
lib_deps = 
	SoftwareSerial
	marcoschwartz/LiquidCrystal_I2C@^1.1.4
	seeed-studio/Grove 3Axis Compass V2.0 BMM150@^1.0.0
	arduino-libraries/Servo@^1.1.7
	arduino-libraries/SD @ 1.2.4
	adafruit/Adafruit GPS Library@^1.5.3

with minimal code

#include <Arduino.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

// you can change the pin numbers to match your wiring:
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);

void setup() {}
void loop(){}

and a deletion of .pio and rebuild, doesn’t make it recognize the dependency.

Library Manager: Installing marcoschwartz/LiquidCrystal_I2C @ ^1.1.4
Library Manager: LiquidCrystal_I2C @ 1.1.4 has been installed!
Library Manager: Installing seeed-studio/Grove 3Axis Compass V2.0 BMM150 @ ^1.0.0
Library Manager: Grove 3Axis Compass V2.0 BMM150 @ 1.0.0 has been installed!
Library Manager: Installing arduino-libraries/Servo @ ^1.1.7
Library Manager: Servo @ 1.1.7 has been installed!
Library Manager: Installing arduino-libraries/SD @ 1.2.4
Library Manager: SD @ 1.2.4 has been installed!
Library Manager: Installing adafruit/Adafruit GPS Library @ ^1.5.3
Library Manager: Adafruit GPS Library @ 1.5.3 has been installed!
Library Manager: Installing dependencies...
Library Manager: SD @ 1.2.4 is already installed
Found 10 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <SoftwareSerial> 1.0
|-- <LiquidCrystal_I2C> 1.1.4
|   |-- <Wire> 1.0
|-- <Grove 3Axis Compass V2.0 BMM150> 1.0.0
|   |-- <Wire> 1.0
|-- <Servo> 1.1.7
|-- <SD> 1.2.4
|   |-- <SPI> 1.0
|-- <Adafruit GPS Library> 1.5.3
|   |-- <SPI> 1.0
|   |-- <Wire> 1.0
..
In file included from .pio\libdeps\nanoatmega328\Adafruit GPS Library\src\NMEA_data.cpp:38:0:
.pio\libdeps\nanoatmega328\Adafruit GPS Library\src\Adafruit_GPS.h:58:28: fatal error: SoftwareSerial.h: No such file or directory

If I change original expression from

#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
#include <SoftwareSerial.h>
#endif

to

#if defined(__AVR__) || defined(ESP8266)
#include <SoftwareSerial.h>
#endif

same error.

Same with

#if defined(__AVR__)
#include <SoftwareSerial.h>
#endif

Same with

#ifdef __AVR__
#include <SoftwareSerial.h>
#endif

But if I just do

#if defined(USE_SW_SERIAL)
#include <SoftwareSerial.h>
#endif

(this macro is defined by the library a few lines above the include), it does work. So from a high-level view I think the LDF doesn’t take into account the internal macros generated / set by avr-g++ in this case, regarding __AVR__.

Other macros work, too

#if (defined(ARDUINO_ARCH_AVR) || defined(ESP8266)) && defined(USE_SW_SERIAL)
#include <SoftwareSerial.h>
#endif

→ builds.

This macro is definitely internal, when I build

#if defined(__AVR__)
#error "__AVR__ MACRO IS DEFINED"
#else
#error "__AVR__ MACRO IS NOT DEFINED"
#endif

int main() {
  return 0;
}

with

C:\Users\Max\atmel_pure>C:\Users\Max\.platformio\packages\toolchain-atmelavr\bin\avr-g++ -c -o test.o test.cpp
test.cpp:2:2: error: #error "__AVR__ MACRO IS DEFINED"
    2 | #error "__AVR__ MACRO IS DEFINED"
      |  ^~~~~

Further when I do

C:\Users\Max\atmel_pure>C:\Users\Max\.platformio\packages\toolchain-atmelavr\bin\avr-g++ -w -dM -E test.cpp >> out.txt  

do look at all defined macros (just like Marlin does), I do see it too