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: