Build an Arduino library for ESP8266 locally

This project GitHub - ThingPulse/esp8266-weather-station: ESP8266 Weather Station library supporting OpenWeatherMap, Aeris and other sources builds fine on Travis CI but fails to link locally in VS Code

platformio.ini

[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
upload_speed = 921600
board_f_cpu = 160000000L
lib_deps =  JsonStreamingParser,
            ESP8266_SSD1306
            simpleDSTadjust
            DHT sensor library
            Adafruit Unified Sensor

Output

Linking .pio/build/d1_mini/firmware.elf
/Users/marcelstoer/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .pio/build/d1_mini/libFrameworkArduino.a(core_esp8266_main.cpp.o):(.text._ZL12loop_wrapperv+0x4): undefined reference to `setup'
/Users/marcelstoer/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .pio/build/d1_mini/libFrameworkArduino.a(core_esp8266_main.cpp.o):(.text._ZL12loop_wrapperv+0x8): undefined reference to `loop'
/Users/marcelstoer/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .pio/build/d1_mini/libFrameworkArduino.a(core_esp8266_main.cpp.o): in function `loop_wrapper()':
core_esp8266_main.cpp:(.text._ZL12loop_wrapperv+0x21): undefined reference to `setup'
/Users/marcelstoer/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: core_esp8266_main.cpp:(.text._ZL12loop_wrapperv+0x2d): undefined reference to `loop'
collect2: error: ld returned 1 exit status
*** [.pio/build/d1_mini/firmware.elf] Error 1

It looks as if it didn’t understand that this is actually Arduino code. Already deleted the .pio, .platformio and ~/.platformio/packages folders but that doesn’t help.

Since you didn’t mention what you’re trying to compile, I’m assume you mean one of the examples. I had a skim of most of them, and there’s no #include <Arduino.h> in a couple… which is most likely why you have the undefined reference to 'setup'/'loop' errors.

https://docs.platformio.org/en/latest/faq.html#convert-arduino-file-to-c-manually

1 Like

I get your point, thanks. As this project is an Arduino library (for ESP8266) that includes examples the Travis file includes all the

env:
    - PLATFORMIO_CI_SRC

definitions for each example. That works - with or without the #include <Arduino.h>.

I guess I was hoping I could build all at once locally with the minimal platformio.ini included in the project. That doesn’t seem to be case even if I add #include <Arduino.h> to all the examples it was missing (thanks for the hint).

Hm… I’ll counter with another question, but for @ivankravets… which could answer this for both of us… as I had tried to get this configuration working before but it wouldn’t play ball, and I am so close now it’s not funny.

Ivan, I managed to get my pet library to compiles examples in different envs using the following, but only if I rename the *.ino files to *.cpp. Is there anything I’m missing there? Is it possible to persuade PIO to accept *.ino files as well? .ino files are accepted if I point the [platformio] src_dir to a folder like $PROJECT_DIR/examples/timeouts, but that doesn’t help as that’s the global setting.

platformio.ini contents
[platformio]
src_dir = $PROJECT_DIR/examples
lib_dir = $PROJECT_DIR

[env]
platform = atmelavr
framework = arduino
board = uno

[env:example-blinkingLeds]
src_filter = +<blinkingLeds/>

[env:example-GettingStarted]
src_filter = +<GettingStarted/>

[env:example-timeouts]
src_filter = +<timeouts/>

[env:example-timingComparison]
src_filter = +<timingComparison/>

Edit: Just linking this topic, as it looks to be another approach to the problem, but if the OP can get it working again, looks to be neater / more automated.

So, using this adjust_src_dir.py extrascript …

Import("env")
env['PROJECT_SRC_DIR'] = env['PROJECT_DIR'] + "\\examples\\" + env["PIOENV"]
print("Setting the project directory to: {}".format(env['PROJECT_SRC_DIR']))

… with this platformio.ini

[platformio]
lib_dir = $PROJECT_DIR

[env]
extra_scripts = pre:adjust_src_dir.py
platform = atmelavr
framework = arduino
board = uno

[env:blinkingLeds]

[env:GettingStarted]

[env:timeouts]

[env:timingComparison]

with the elapsedMillis library (once I move the header file into /src) works just fine… I can compile all of the examples at once, or compile any individual one at will.

However, when I try to do the same for the esp8266-weather-station library, with this platformio.ini it spits the dummy … dependency graph is all wonky (although it is a bit wonky for the elapsedMillis examples also), and it can’t find the libraries, even though they were installed :frowning:

[platformio]
lib_dir = $PROJECT_DIR

[env]
extra_scripts = pre:adjust_src_dir.py
platform = espressif8266
board = d1_mini
framework = arduino
upload_speed = 921600
board_build.f_cpu = 160000000L
lib_deps =
    JsonStreamingParser
    ESP8266_SSD1306
    simpleDSTadjust
    DHT sensor library
    Adafruit Unified Sensor

[env:WeatherStationDemo]

[env:oneDayForecaster]
Processing oneDayForecaster (platform: espressif8266; board: d1_mini; framework: arduino)
-------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
Setting the project directory to: e:\repos\GitHub\esp8266-weather-station\examples\oneDayForecaster
CONFIGURATION: https://docs.platformio.org/page/boards/espressif8266/d1_mini.html
PLATFORM: Espressif 8266 2.2.3 > WeMos D1 R2 and mini
HARDWARE: ESP8266 160MHz, 80KB RAM, 4MB Flash
PACKAGES: toolchain-xtensa 2.40802.190218 (4.8.2), tool-esptool 1.413.0 (4.13), tool-esptoolpy 1.20600.0 (2.6.0), framework-arduinoespressif8266 2.20502.0 (2.5.2)
Converting oneDayForecaster.ino
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Looking for JsonStreamingParser library in registry
Found: https://platformio.org/lib/show/561/JsonStreamingParser
LibraryManager: Installing id=561
Using cache: C:\Users\Peter\.platformio\.cache\88\f8d1709798831a95c4e40862a1906088
JsonStreamingParser @ 1.0.5 has been successfully installed!
Looking for ESP8266_SSD1306 library in registry
Found: https://platformio.org/lib/show/562/ESP8266_SSD1306
LibraryManager: Installing id=562
Using cache: C:\Users\Peter\.platformio\.cache\d0\5934d6d51cda3c4bcc0818eb30dc49d0
Unpacking  [####################################]  100%
ESP8266_SSD1306 @ 4.1.0 has been successfully installed!
Looking for simpleDSTadjust library in registry
Found: https://platformio.org/lib/show/1276/simpleDSTadjust
LibraryManager: Installing id=1276
Using cache: C:\Users\Peter\.platformio\.cache\be\e2ad0113c989ed3d1d3a3d631d6149be
simpleDSTadjust @ 1.2.0 has been successfully installed!
Looking for DHT sensor library library in registry
Found: https://platformio.org/lib/show/19/DHT sensor library
LibraryManager: Installing id=19
Using cache: C:\Users\Peter\.platformio\.cache\c4\c71b8c48a4a013bd3cff76e14fc53bc4
DHT sensor library @ 1.3.8 has been successfully installed!
Looking for Adafruit Unified Sensor library in registry
Found: https://platformio.org/lib/show/31/Adafruit Unified Sensor
LibraryManager: Installing id=31
Using cache: C:\Users\Peter\.platformio\.cache\d3\d18a768c13d410d94032887a7f4d50d3
Adafruit Unified Sensor @ 1.0.3 has been successfully installed!
Found 41 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <.pio>
|-- <SD(esp8266)> 2.0.0
|   |-- <SDFS> 0.1.0
|   |   |-- <SPI> 1.0
|   |   |-- <ESP8266SdFat> 1.0.16
|   |   |   |-- <SPI> 1.0
|-- <ESP8266mDNS> 1.2
|   |-- <ESP8266WiFi> 1.0
|-- <src>
|   |-- <ESP8266WiFi> 1.0
|   |-- <.pio>
|   |-- <ESP8266HTTPClient> 1.2
|   |   |-- <ESP8266WiFi> 1.0
|-- <ArduinoOTA> 1.0
|   |-- <ESP8266mDNS> 1.2
|   |   |-- <ESP8266WiFi> 1.0
|   |-- <ESP8266WiFi> 1.0
Building in release mode
Compiling .pio\build\oneDayForecaster\src\oneDayForecaster.ino.cpp.o
Generating LD script .pio\build\oneDayForecaster\ld\local.eagle.app.v6.common.ld
Archiving .pio\build\oneDayForecaster\lib3f7\lib.pio
Compiling .pio\build\oneDayForecaster\lib3b2\SPI\SPI.cpp.o
Indexing .pio\build\oneDayForecaster\lib3f7\lib.pio
Compiling .pio\build\oneDayForecaster\lib631\ESP8266SdFat\FatLib\FatFile.cpp.o
Compiling .pio\build\oneDayForecaster\lib631\ESP8266SdFat\FatLib\FatFileLFN.cpp.o
E:/repos/GitHub/esp8266-weather-station/examples/oneDayForecaster/oneDayForecaster.ino:42:26: fatal error: Adafruit_GFX.h: No such file or directory

**********************************************************************
* Looking for Adafruit_GFX.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:Adafruit_GFX.h"
* Web  > https://platformio.org/lib/search?query=header:Adafruit_GFX.h
*
**********************************************************************

#include <Adafruit_GFX.h>
                         ^
compilation terminated.
*** [.pio\build\oneDayForecaster\src\oneDayForecaster.ino.cpp.o] Error 1
==================================================== [FAILED] Took 19.48 seconds ====================================================

Environment         Status    Duration
------------------  --------  ------------
WeatherStationDemo  IGNORED
oneDayForecaster    FAILED    00:00:19.476
=============================================== 1 failed, 0 succeeded in 00:00:19.476 ===============================================

What is your goal? How are you going to compile a project with src where there is no main file with loop/setup?

I’m not sure I understand the question.

Don’t worry about issues with MetOfficeDemo and oneDayForecaster. They’re excluded from the Travis build as well for some reason :frowning:

However, I too am seeing the same behavior with other examples e.g. WeatherStationDemo. Platform IO doesn’t find the lib dependencies it had just installed seconds ago.

@ivankravets If you’re replying to me, I’m doing two things out of the ‘ordinary’ … By using the adjust_src_dir.py, PROJECT_SRC_DIR is changed to a directory with a *.ino file, so that condition is satisfied. Also, since the project revolves around the library examples, and the library is located in the \src directory, I set lib_dir = $PROJECT_DIR so that the library is found. It’s just that doing it this way seems to completely mess of the LDF and also means PIO doesn’t find libraries that have been downloaded. It would be nice if this could be made to work, or some variation of it… otherwise reverting to pio ci in a script looks to be the only viable option, just not so user friendly.

@marcelstoer :laughing: Now you tell me I picked one of the ones that didn’t work? :laughing:

@pfeerick great work so far!

I don’t know. Just noticed they’re not included in the CI build. Since I didn’t setup this project initially I wouldn’t know why that is…

P.S. for platform-independency I had to do something about \examples vs /examples in the adjust_src_dir.py script (os.path.join() or os.sep).

1 Like

Yeah, I noticed when compiling them for some reason they use ESPWiFi.h, not ESP8266WiFi.h … so that’s the first clue something ain’t quite right there! More importantly, is it getting anywhere with the other examples? Or falling flat on it’s face still? :frowning: I mainly stuck to the WeatherStationDemo, and it didn’t seem to get past finding the libraries, so more poking around there is needed.

It’s driving me crazy. None of the lib_dir/src_dir combinations I tested yield a successful build.

This rather minimal platformio.ini is very similar to the Travis CI definition. For now I stopped fiddling with the extra script.

[platformio]
lib_dir = "."

[env]
platform = espressif8266
board = d1_mini
framework = arduino
upload_speed = 921600
board_build.board_f_cpu = 160000000L
lib_deps =
    JsonStreamingParser
    ESP8266_SSD1306
    simpleDSTadjust
    DHT sensor library
    Adafruit Unified Sensor

[env:WeatherStationDemo]
src_dir = examples/WeatherStationDemo

; more envs here

Compilation is fine but the linker fails with the errors reported in my first comment (undefined reference tosetup’`). Why would this work with CI but not if run locally.

Because you’re ignoring the warning at the top of the build log :stuck_out_tongue:

Warning! Ignore unknown configuration option src_dir in section [env:WeatherStationDemo]

src_dir is only valid for the global [platformio] block, as it’s meant to specify the src_dir for the entire project.

The ci command works completely differently to a normal run… where you pass the directory path to the source files, specify a board and optionally directory with library files or install the library if needed… and it goes out and runs completely independent.

The nearest I can get to that locally so far is to… reprodice the ci run locally… ie.

pio ci -b d1_mini -l . --project-option="lib_deps=JsonStreamingParser, ESP8266_SSD1306, simpleDSTadjust, DHT sensor library, Adafruit Unified Sensor" examples/WeatherStationDemo

It has the downside of installing the libraries every time, (the alternative of installing the libraries globally has too many other project breaking implications that it’s not worth doing), although at the same time, the upside being it’s a 100% clean build every time, since it’s in a temp folder.

Thank you for the great feedback, much appreciated.

I could certainly put this into a script; loop over all examples and run the CI build locally. However, it’s hard to accept that this is really the best solution. I thought that building an Arduino library with examples must be a pretty standard use case.

@ivankravets can you confirm that we are not missing something obvious?

You can’t use src_dir here. Do you see warnings in CLI? See Redirecting...

I just created an account just to say thank you, you really saved my day! :slight_smile: