Linking order problem with virtual/override methods

Hello!

I’m the developer of RFQuack, an RF-hacking library framework and hardware toolkit. The project is based on PlatformIO and I found a linking issue that results in the wrong method being called.

RFQuack depends on (a fork of) RadioLib, which is now 100% aligned with the upstream. RFQuack wraps some classes of RadioLib, adding some more methods and reusing (i.e., using) some existing ones.

Full post with links to code lines (because new users of this community cannot post more than 2 links):


Situation

The desired chain of calls is as follows:

RFQRF69::begin()
RadioLibWrapper:begin()
RF69::begin()
RF69::setFrequency(float)

Background

The last step is because of this part in RFQRFM69.h:

class RFQRF69 : public RadioLibWrapper<RF69> {
public:
    using RF69::setPreambleLength;
    using RF69::setOutputPower;
    using RF69::setPromiscuousMode;
    using RF69::variablePacketLengthMode;
    using RF69::setCrcFiltering;
    using RF69::setRxBandwidth;
    using RF69::fixedPacketLengthMode;

    using RF69::setFrequency;        // <--- this

    using RF69::setFrequencyDeviation;
    using RF69::getFrequencyDeviation;
    using RF69::setBitRate;

RFQRF69 implements RadioLibWrapper but it uses the generic’s implementation of setFrequency(float). The reason for this is that I want RadioLibWrapper to define the interface (minimum methods to be implemented), but leave the developer to either use the generic’s implementation or to override.

Problem

However, the linker confuses RF69::setFrequency(float) with virtual RadioLibWrapper::setFrequency(float). So, the runtime call chain of calls is as follows:

RFQRF69::begin()
RadioLibWrapper:begin()
RF69::begin()
RadioLibWrapper::setFrequency(float)

Possible Explanation

I guess this is due to linking order as per how PlatformIO “decides” to order libraries.

To verify this, I changed RadioLibWrapper.h as follows:

    // virtual int16_t setFrequency(float freq) {
    //   Log.error(F("setFrequency was not implemented."));

    //   return ERR_COMMAND_NOT_IMPLEMENTED;
    // }

And the correct method RF69::setFrequency(float) is linked and resolved at runtime. Because the virtual simply doesn’t exist, so the linker couldn’t get confused.

The Build Configuration

The build configuration is as follows.

[platformio]
default_envs = featheresp32

[env]
build_unflags = -fno-rtti
framework = arduino

# This installs all requirements from
# RFQuack's `library.json` (RadioLib is not there)
lib_deps =
	file://.

# Add extra libs
lib_extra_dirs =
	lib/RadioLib

custom_nanopb_protos = 
	+<src/rfquack.proto>
custom_nanopb_options = 
	--error-on-unmatched
extra_scripts = 
	pre:scripts/pio/main_cpp_j2.py
monitor_speed = 115200

[env:featheresp32]
platform = platformio/espressif32@^5.2.0
board = featheresp32

Reproduction

I understand it’s quite hard to reproduce this bug without proper hardware. However, it can compile anywhere pretty easily through PlatformIO:

git clone --recursive https://github.com/rfquack/RFQuack
cd RFQuack
pip install -r requirements.pip
vim build.env
make clean build

Read more thorough build instructions.

Quick shot: Is the issue resolved when adding lib_archive = no in the platformio.ini?

@maxgerhardt if I do that, I get errors that kinda make sense, because it seems to be catching multiple declarations of the same symbols.

I’m wondering if I could revise my design to avoid this, instead of hacking around with compiler/linking options.

$ make clean flash
...
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `radioInterrupt(void*)':
/Users/u/dev/RFQuack/src/radio/RadioLibWrapper.h:51: multiple definition of `radioInterrupt(void*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/RadioLibWrapper.h:51: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `printTimestamp(Print*)':
/Users/u/dev/RFQuack/src/radio/../modules/../rfquack_logging.h:29: multiple definition of `printTimestamp(Print*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/../modules/../rfquack_logging.h:29: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `printNewline(Print*)':
/Users/u/dev/RFQuack/src/radio/../modules/../rfquack_logging.h:35: multiple definition of `printNewline(Print*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/../modules/../rfquack_logging.h:35: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/radio/../modules/ModulesDispatcher.h:132: multiple definition of `modulesDispatcher'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/../modules/ModulesDispatcher.h:132: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_logging_setup()':
/Users/u/dev/RFQuack/src/radio/../modules/../rfquack_logging.h:81: multiple definition of `rfquack_logging_setup()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/../modules/../rfquack_logging.h:81: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_log_buffer(char const*, unsigned char const*, unsigned int)':
/Users/u/dev/RFQuack/src/radio/../modules/../rfquack_logging.h:96: multiple definition of `rfquack_log_buffer(char const*, unsigned char const*, unsigned int)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/../modules/../rfquack_logging.h:96: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_log_packet(_rfquack_Packet*)':
/Users/u/dev/RFQuack/src/radio/../modules/../rfquack_logging.h:116: multiple definition of `rfquack_log_packet(_rfquack_Packet*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/../modules/../rfquack_logging.h:116: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_network_loop()':
/Users/u/dev/RFQuack/src/rfquack_network.h:145: multiple definition of `rfquack_network_loop()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_network.h:145: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `binary_to_base64(unsigned char)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:77: multiple definition of `binary_to_base64(unsigned char)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:77: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `base64_to_binary(unsigned char)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:106: multiple definition of `base64_to_binary(unsigned char)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:106: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `encode_base64_length(unsigned int)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:135: multiple definition of `encode_base64_length(unsigned int)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:135: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `decode_base64_length(unsigned char const*, unsigned int)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:143: multiple definition of `decode_base64_length(unsigned char const*, unsigned int)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:143: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `decode_base64_length(unsigned char const*)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:139: multiple definition of `decode_base64_length(unsigned char const*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:139: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `encode_base64(unsigned char const*, unsigned int, unsigned char*)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:154: multiple definition of `encode_base64(unsigned char const*, unsigned int, unsigned char*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:154: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `decode_base64(unsigned char const*, unsigned int, unsigned char*)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:195: multiple definition of `decode_base64(unsigned char const*, unsigned int, unsigned char*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:195: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `decode_base64(unsigned char const*, unsigned char*)':
/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:191: multiple definition of `decode_base64(unsigned char const*, unsigned char*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/base64/src/base64.hpp:191: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_packet_matches(char*, _rfquack_Packet*)':
/Users/u/dev/RFQuack/src/radio/../modules/../rfquack_common.h:69: multiple definition of `rfquack_packet_matches(char*, _rfquack_Packet*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/radio/../modules/../rfquack_common.h:69: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:48: multiple definition of `rfqRadio'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:48: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_transport_recv(char*, unsigned char*, unsigned int)':
/Users/u/dev/RFQuack/src/rfquack_transport.h:38: multiple definition of `rfquack_transport_recv(char*, unsigned char*, unsigned int)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:38: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack_transport.h:209: multiple definition of `rfquack_topic_buf_len'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:209: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack_transport.h:208: multiple definition of `rfquack_topic_buf'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:208: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack_transport.h:213: multiple definition of `rfquack_payload_buf_len'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:213: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack_transport.h:212: multiple definition of `rfquack_payload_buf'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:212: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack_transport.h:216: multiple definition of `rfquack_serial_receiving'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:216: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack_transport.h:217: multiple definition of `rfquack_serial_data_ready'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:217: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_network_setup()':
/Users/u/dev/RFQuack/src/rfquack_network.h:141: multiple definition of `rfquack_network_setup()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_network.h:141: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_transport_connect()':
/Users/u/dev/RFQuack/src/rfquack_transport.h:219: multiple definition of `rfquack_transport_connect()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:219: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_transport_setup()':
/Users/u/dev/RFQuack/src/rfquack_transport.h:227: multiple definition of `rfquack_transport_setup()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:227: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:61: multiple definition of `radioAModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:61: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquackTask(void*)':
/Users/u/dev/RFQuack/src/rfquack.h:73: multiple definition of `rfquackTask(void*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:73: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:58: multiple definition of `guessingModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:58: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:55: multiple definition of `frequencyScannerModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:55: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:56: multiple definition of `mouseJackModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:56: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:52: multiple definition of `packetFilterModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:52: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:51: multiple definition of `packetModificationModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:51: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:54: multiple definition of `packetRepeaterModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:54: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:53: multiple definition of `rollJamModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:53: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:59: multiple definition of `pingModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:59: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_setup(RFQRF69*, decltype(nullptr)*, decltype(nullptr)*, decltype(nullptr)*, decltype(nullptr)*)':
/Users/u/dev/RFQuack/src/rfquack.h:90: multiple definition of `rfquack_setup(RFQRF69*, decltype(nullptr)*, decltype(nullptr)*, decltype(nullptr)*, decltype(nullptr)*)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:90: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/main.cpp:30: multiple definition of `radioA'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/main.cpp:30: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `setup()':
/Users/u/dev/RFQuack/src/main.cpp:42: multiple definition of `setup()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/main.cpp:42: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:57: multiple definition of `helloWorldModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:57: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_transport_send(char const*, unsigned char const*, unsigned int)':
/Users/u/dev/RFQuack/src/rfquack_transport.h:245: multiple definition of `rfquack_transport_send(char const*, unsigned char const*, unsigned int)'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:245: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_transport_loop()':
/Users/u/dev/RFQuack/src/rfquack_transport.h:301: multiple definition of `rfquack_transport_loop()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack_transport.h:301: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `rfquack_loop()':
/Users/u/dev/RFQuack/src/rfquack.h:172: multiple definition of `rfquack_loop()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:172: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o: in function `loop()':
/Users/u/dev/RFQuack/src/main.cpp:52: multiple definition of `loop()'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/main.cpp:52: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:65: multiple definition of `radioEModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:65: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:64: multiple definition of `radioDModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:64: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:63: multiple definition of `radioCModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:63: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/main.cpp.o:/Users/u/dev/RFQuack/src/rfquack.h:62: multiple definition of `radioBModule'; .pio/build/featheresp32/libbbb/RFQuack/main.cpp.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/rfquack.h:62: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/utils/regex/re.c.o: in function `re_matchp':
/Users/u/dev/RFQuack/src/utils/regex/re.c:106: multiple definition of `re_matchp'; .pio/build/featheresp32/libbbb/RFQuack/utils/regex/re.c.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/utils/regex/re.c:106: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/utils/regex/re.c.o: in function `re_compile':
/Users/u/dev/RFQuack/src/utils/regex/re.c:128: multiple definition of `re_compile'; .pio/build/featheresp32/libbbb/RFQuack/utils/regex/re.c.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/utils/regex/re.c:128: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/utils/regex/re.c.o: in function `re_match':
/Users/u/dev/RFQuack/src/utils/regex/re.c:102: multiple definition of `re_match'; .pio/build/featheresp32/libbbb/RFQuack/utils/regex/re.c.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/utils/regex/re.c:102: first defined here
/Users/u/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/featheresp32/src/utils/regex/re.c.o: in function `re_print':
/Users/u/dev/RFQuack/src/utils/regex/re.c:264: multiple definition of `re_print'; .pio/build/featheresp32/libbbb/RFQuack/utils/regex/re.c.o:/Users/u/dev/RFQuack/.pio/libdeps/featheresp32/RFQuack/src/utils/regex/re.c:264: first defined here
collect2: error: ld returned 1 exit status
*** [.pio/build/featheresp32/firmware.elf] Error 1
================================================== [FAILED] Took 100.79 seconds ==================================================
make: *** [flash] Error 1