Library structure with examples

I’d like to create a library with some examples for use in PIO. My wish is to make it as simple and straightforward as possible:

  1. the library consists of one C++ header and one C++ source file
  2. there are several examples, which I’m also using as quick test
  3. I want to make it trivially easy to run these examples with PIO

The structure for this, as suggested in the docs, is:

mylib/
├── examples/
│   ├── foo/main.cpp
│   └── bar/main.cpp
├── include/mylib.h
├── src/mylib.cpp
└── library.json

I have two problems with this approach:

  • this doesn’t make it easy to actually build and run the examples
  • there is too much nesting, folders with a single file are tedious

The first problem is actually the bigger issue. How do you get these examples to compile? Do I need to include a platformio.ini file with each? And then add lib_extra_dirs = ../../.. to find the library? That will cause PIO to scan all sibling directories as well, which would be confusing (and slow).

The second issue appears to be solvable with the following alternative:

mylib/
├── examples/
│   ├── foo/main.cpp
│   ├── bar/main.cpp
│   └── platformio.ini
├── mylib.h
├── mylib.cpp
└── library.json

With [env:foo] and [env:bar] in the ini file, and a suitable src_filter in each section.

But even then, the problem remains that I can’t reach the library source files in examples/../.

The standard Arduino library structure works too: pull out the files from include/ and src/ into the mylib folder.

Have you tried the pio ci commands? They’re meant for continuous integration, e.g. compiling a library example and seeing if compilation goes through. Documentation is available (this page among lots of others). So something in the style of

pio ci path/to/example/file.cpp --lib="path/to/library/folder" --board=uno

(or whatever board.) Then you don’t need the examples to be full PlatformIO project folders.

2 Likes

Ah, that never occurred to me!

I just did a small test, using this setup:

.
├── examples
│   └── simple.cpp
├── mylib.cpp
└── mylib.h

And indeed, it compiles and builds perfectly, using:

pio ci examples/simple.cpp --lib=. --board=disco_f407vg

The only surprise was that it assumes Arduino’s setup/loop as main. I’m normally targeting stm32cube - but it turns out this can easily be addressed by adding -O 'framework=stm32cube'.

And I see that even uploads are supported - splendid!

Many thanks,
-jcw

Just FYI.

I solved this by using a single platformio.ini and add new environments for every example I use. See the example below.
This works a bit more like Cargo from the Rust language operates. Also you know that the whole project keeps on working.

[platformio]
default_envs = house2

[env]
platform = espressif32
board = nodemcu-32s
framework = arduino
upload_port = /dev/ttyUSB0
monitor_speed = 115200    
monitor_port = /dev/ttyUSB0
lib_deps = 
    playingwithfusion/PWFusion_VL53L3C@^1.0.0
    budryerson/TFLI2C@^0.2.0
    adafruit/Adafruit PWM Servo Driver Library@^2.4.0
    robtillaart/MCP23017@^0.2.6


[env:house2]
src_filter = +<house2.cpp>

[env:luna_config]
src_filter = +<../tools/luna_config.cpp>

You can then run it using:

pio run -e luna_config -t upload

Works like a charm.

2 Likes

Thanks - as it so happens, the src_filter = …` approach is exactly what I’ve settled on. And as you point out, being able to compile all of them as a quick check is a nice convenience.