Building and uploading library examples with env sections

I’ve spent a few hours over the last day and a half scouring the internet and experimenting with different .ini directives to do something that seems like it should be dead-simple, but is in fact (so far) impossible: specify a single example project within an Arduino-compatible library structure to build and upload.

TL;DR SUMMARY:

PlatformIO is properly compiling everything under ./src/* (and subfolders). I’m trying to use build_src_filter to add another folder, or even just another file, to the list of what must be compiled only for a specific environment. It never includes the specified folder/file.

Is there a way to do this?

The library in question (Perilib) is on Github here in essentially the current format, minus a few changes and the platformio.ini file I’m working on right now. I’ve followed the recommended PlatformIO library structure template, except that the header files are in the same src folder as the source files, which I understand is necessary for Arduino compatibility. In any case, that modification doesn’t seem to be related to any problems I’m having, as I’ve actually tried it the other way as well and encounter the same issue.

As a library, I realize it doesn’t strictly need its own platformio.ini file, but my goal is to use it as a way to develop and test examples without jumping through a bunch of hoops every time I want to switch which example I’m working on, or commit the latest code, or use symlinks (which might work but should be unnecessary).

It appears that the build_src_filter directive should accomplish what I want, and various posts online suggest the same, but no matter what I try, it never works. Here’s an example of what I mean; my current work-in-progress .ini content looks like this–very simple:

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

[env:example_Stream_LTV_parse]
build_src_filter = +<*> +<../examples/example_Stream_LTV_parse>

[env:example_Register_TWI_MPU6050_direct]
build_src_filter = +<*> +<../examples/Register_TWI_MPU6050_direct>

I prefixed the additional example folders in each case with ../ because I understand that build_src_filter is relative to src_dir which (unspecified here) defaults to ./src (which is correct for the rest of the library code. When I build either of these two environments, it properly compiles all of the library source code, but then fails because setup() and loop() can’t be found by the linker, because the final example .ino file isn’t being compiled:

C:\Users\Jeff\OneDrive\Documents\Git\perilib\perilib-arduino-core>pio run -v --environment example_Stream_LTV_parse
Processing example_Stream_LTV_parse (build_src_filter: +<*> +<../examples/example_Stream_LTV_parse>; platform: atmelavr; framework: arduino; board: uno)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/uno.html
PLATFORM: Atmel AVR (4.0.0) > Arduino Uno
HARDWARE: ATMEGA328P 16MHz, 2KB RAM, 31.50KB Flash
DEBUG: Current (avr-stub) On-board (avr-stub, simavr)
PACKAGES:
 - framework-arduino-avr @ 5.1.0
 - toolchain-atmelavr @ 1.70300.191015 (7.3.0)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 5 compatible libraries
Scanning dependencies...
Dependency Graph
|-- Wire @ 1.0 (License: Unknown, Path: C:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire)
Building in release mode
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\Device.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections 
-fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\Device.cppavr-g++ -o .pio\build\example_Stream_LTV_parse\src\LTVStreamProtocol.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\LTVStreamProtocol.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\RegisterDevice.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\RegisterDevice.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\RegisterInterface.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\RegisterInterface.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\RegisterMap.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\RegisterMap.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\Stream.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections 
-fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\Stream.cppavr-g++ -o .pio\build\example_Stream_LTV_parse\src\StreamDevice.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\StreamDevice.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\StreamPacket.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\StreamPacket.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\StreamParserGenerator.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\StreamParserGenerator.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\StreamProtocol.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\StreamProtocol.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\TLVStreamProtocol.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\TLVStreamProtocol.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\TextStreamProtocol.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\TextStreamProtocol.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\hal\TwiRegisterInterface_ArduinoWire.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p 
-Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\hal\TwiRegisterInterface_ArduinoWire.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\src\hal\UartStream_ArduinoStream.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -Isrc -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard src\hal\UartStream_ArduinoStream.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\lib24a\Wire\Wire.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src\Wire.cpp
avr-gcc -o .pio\build\example_Stream_LTV_parse\lib24a\Wire\utility\twi.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\libraries\Wire\src\utility\twi.c
avr-gcc-ar rc .pio\build\example_Stream_LTV_parse\libFrameworkArduinoVariant.a
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\CDC.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\CDC.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\HardwareSerial.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial0.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\HardwareSerial0.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial1.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\HardwareSerial1.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial2.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\HardwareSerial2.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial3.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\HardwareSerial3.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\IPAddress.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\IPAddress.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\PluggableUSB.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\PluggableUSB.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\Print.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\Print.cpp      
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\Stream.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\Stream.cpp
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\Tone.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\Tone.cpp
avr-gcc -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\WInterrupts.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\WInterrupts.c
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\WString.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\WString.cpp
avr-gcc -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\hooks.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\hooks.c
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\new.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\new.cpp
avr-gcc -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\wiring.c
avr-gcc -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_digital.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\wiring_digital.c
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\USBCore.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\USBCore.cpp  
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\WMath.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\WMath.cpp      
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\main.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\main.cpp        
avr-gcc-ar rc .pio\build\example_Stream_LTV_parse\lib24a\libWire.a .pio\build\example_Stream_LTV_parse\lib24a\Wire\Wire.cpp.o .pio\build\example_Stream_LTV_parse\lib24a\Wire\utility\twi.c.o
avr-gcc -mmcu=atmega328p -x assembler-with-cpp -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard -c -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_pulse.S.o C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\wiring_pulse.S
avr-gcc -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_shift.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\wiring_shift.c
avr-g++ -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\abi.cpp.o -c -fno-exceptions -fno-threadsafe-statics -fpermissive -std=gnu++11 -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\abi.cpp
avr-gcc-ranlib .pio\build\example_Stream_LTV_parse\libFrameworkArduinoVariant.a
avr-gcc -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_analog.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections 
-flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\wiring_analog.c
avr-gcc -o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_pulse.c.o -c -std=gnu11 -fno-fat-lto-objects -mmcu=atmega328p -Os -Wall -ffunction-sections -fdata-sections -flto -DPLATFORMIO=60105 -DARDUINO_AVR_UNO -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO=10808 -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino -IC:\Users\Jeff\.platformio\packages\framework-arduino-avr\variants\standard C:\Users\Jeff\.platformio\packages\framework-arduino-avr\cores\arduino\wiring_pulse.c
avr-gcc-ranlib .pio\build\example_Stream_LTV_parse\lib24a\libWire.a
avr-gcc-ar rc .pio\build\example_Stream_LTV_parse\libFrameworkArduino.a .pio\build\example_Stream_LTV_parse\FrameworkArduino\CDC.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial0.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial1.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial2.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\HardwareSerial3.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\IPAddress.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\PluggableUSB.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\Print.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\Stream.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\Tone.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\USBCore.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\WInterrupts.c.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\WMath.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\WString.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\abi.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\hooks.c.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\main.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\new.cpp.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring.c.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_analog.c.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_digital.c.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_pulse.S.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_pulse.c.o .pio\build\example_Stream_LTV_parse\FrameworkArduino\wiring_shift.c.o
avr-gcc-ranlib .pio\build\example_Stream_LTV_parse\libFrameworkArduino.a
avr-g++ -o .pio\build\example_Stream_LTV_parse\firmware.elf -mmcu=atmega328p -Os -Wl,--gc-sections -flto -fuse-linker-plugin .pio\build\example_Stream_LTV_parse\src\Device.cpp.o .pio\build\example_Stream_LTV_parse\src\LTVStreamProtocol.cpp.o .pio\build\example_Stream_LTV_parse\src\RegisterDevice.cpp.o .pio\build\example_Stream_LTV_parse\src\RegisterInterface.cpp.o .pio\build\example_Stream_LTV_parse\src\RegisterMap.cpp.o .pio\build\example_Stream_LTV_parse\src\Stream.cpp.o .pio\build\example_Stream_LTV_parse\src\StreamDevice.cpp.o .pio\build\example_Stream_LTV_parse\src\StreamPacket.cpp.o .pio\build\example_Stream_LTV_parse\src\StreamParserGenerator.cpp.o .pio\build\example_Stream_LTV_parse\src\StreamProtocol.cpp.o .pio\build\example_Stream_LTV_parse\src\TLVStreamProtocol.cpp.o .pio\build\example_Stream_LTV_parse\src\TextStreamProtocol.cpp.o .pio\build\example_Stream_LTV_parse\src\hal\TwiRegisterInterface_ArduinoWire.cpp.o .pio\build\example_Stream_LTV_parse\src\hal\UartStream_ArduinoStream.cpp.o -L.pio\build\example_Stream_LTV_parse -Wl,--start-group .pio\build\example_Stream_LTV_parse\lib24a\libWire.a .pio\build\example_Stream_LTV_parse\libFrameworkArduinoVariant.a .pio\build\example_Stream_LTV_parse\libFrameworkArduino.a -lm -Wl,--end-group
C:\Users\Jeff\AppData\Local\Temp\ccKiDW9h.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x86): undefined reference to `setup'
<artificial>:(.text.startup+0x8e): undefined reference to `loop'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\example_Stream_LTV_parse\firmware.elf] Error 1
============================================================================ [FAILED] Took 1.81 seconds ============================================================================

In addition to some blog posts and Github issues, I found the following topics on this very forum discussing the same problem. However, none of them reach the goal.

Most detailed discussion:

(Split extra links into a new post because I’m still a new user)

Same problem, no replies:

Same problem, only a workaround discussed:

That trick works for .c/.cpp files, not for .ino files. Ino files get special handling (source, source).

Reading that it’s also easy to use advanced scripting to trigger the .ino → .cpp conversion and the build src filter additon.

For your project, consider the platformio.ini:

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

[env:example_Stream_LTV_parse]
custom_example = examples/Stream_LTV_parse

[env:example_Register_TWI_MPU6050_direct]
custom_example = examples/Register_TWI_MPU6050_direct

with compile_example.py as

#from platformio.builder.tools.pioino import ConvertInoToCpp
import os
Import("env")

custom_example = env.GetProjectOption("custom_example", None)

print("Custom example is: " + str(custom_example))

if custom_example is not None:
    prev_src_dir = env["PROJECT_SRC_DIR"]
    proj_path = env["PROJECT_DIR"]
    # paths are seen as relative from project root location
    example_path = os.path.join(proj_path, custom_example)
    # ConvertToInoCpp() only looks at .ino files from PROJECT_SRC_DIR
    # we temporarily redirect this variable to the examples folder
    env["PROJECT_SRC_DIR"] = example_path
    print("Converting ino for " + example_path)
    env.ConvertInoToCpp()
    env["PROJECT_SRC_DIR"] = prev_src_dir
    # also automatically add to build_src_filter
    print("CURRENT SOURCE FILTER")
    print(env.get("SRC_FILTER", ""))
    if "SRC_FILTER" in env:
        # is it a list or a simple string?
        if isinstance(env["SRC_FILTER"], list):
            env["SRC_FILTER"][0] += " +<%s>" % example_path
        else:
            env["SRC_FILTER"] += " +<%s>" % example_path
    else:
        # not set previously:
        env["SRC_FILTER"] = "+<*> +<%s>" % example_path
    print("SOURCE FILTER NOW")
    print(env.get("SRC_FILTER", ""))
    # ify ou want to set data/ directory per-example for SPIFFS/LittleFS upload
    #env["PROJECT_DATA_DIR"] = os.path.join(example_path, "data")

Then you will see that both environments will build normally and all you have to do is give the environment the path to the example (relative to the root of the project).

Environment                          Status    Duration
-----------------------------------  --------  ------------
example_Stream_LTV_parse             SUCCESS   00:00:02.548
example_Register_TWI_MPU6050_direct  SUCCESS   00:00:02.793
====================== 2 succeeded in 00:00:05.341 ======================
1 Like

Thank you! That is a an excellent solution. I’m a little surprised it takes a Python script to make it work, but the important part is that it works perfectly.