Automatic BLE library detection

I’m working on automatic BLE library detection in ArduinoBleOTA and ArduinoBleChess. Implementation of BleChessDefines.h looks like:

#pragma once

#if __has_include("ArduinoBLE.h")
    #include <ArduinoBLE.h>
    #define BLE_CHESS_BLE_LIB_ARDUINO_BLE
    #define BLE_CHESS_LIB_ARDUINO_BLE
#elif __has_include("NimBLEDevice.h")
    #include <NimBLEDevice.h>
    #define BLE_CHESS_BLE_LIB_NIM_BLE_ARDUINO
    #define BLE_CHESS_LIB_NIM_BLE_ARDUINO
#if !defined(CONFIG_NIMBLE_MAX_CONNECTIONS) && \
    !defined(CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED)
    #define BLE_CHESS_BLE_LIB_NIM_BLE_ARDUINO_V1
#else
    #define BLE_CHESS_BLE_LIB_NIM_BLE_ARDUINO_V2
#endif
#elif defined(ARDUINO_ARCH_ESP32)
    #include <BLEDevice.h>
    #define BLE_CHESS_BLE_LIB_ESP32
    #define BLE_CHESS_LIB_ESP32
#else
    #error "Unsupported BLE library. Consider ArduinoBLE or NimBLE-Arduino."
#endif

Libraries added by:

lib_deps =
	vovagorodok/ArduinoBleOTA@^1.2.0
	vovagorodok/ArduinoBleChess@^0.6.0
	h2zero/NimBLE-Arduino@^1.4.3

At the end, linking error:

undefined reference to `BleChessLib::begin(NimBLEServer*, BleChessPeripheral&, BleChessOfflineCentral&)'
collect2: error: ld returned 1 exit status

Adding at the beginning of .pio/libdeps/ArduinoBleChess/src/BleChessDefines.h

#include <NimBLEDevice.h>

fix an issue

Looks that __has_include("NimBLEDevice.h") doesn’t work if appropriate include isn’t added. It makes impossible to prepare automatic detection.
As I correctly understand PlatformIO somehow check all includes and if NimBLEDevice.h exist than add h2zero/NimBLE-Arduino library to the ArduinoBleChess compilation.
Any idea how to solve this issue?

Please see https://docs.platformio.org/en/latest/projectconf/sections/env/options/library/lib_deps.html. Turn it up to chain+ or deep+. You can control that mode as well in your library.json.

Thanks. I’m using deep+. It is not lib_ldf_mode issue. Perhaps I should describe issue better.

Idea is to have library that haven’t dependencies but can work with different BLE libraries, depending which is added to lib_deps. In library ArduinoBleChess I have section/include where I check which Bluetooth library is used in main project: ArduinoBLE, NimBLE-Arduino or native ESP32. I’m doing it by __has_include macro:

#elif __has_include("NimBLEDevice.h")
    #include <NimBLEDevice.h>
    #define BLE_CHESS_LIB_NIM_BLE_ARDUINO

Expected, if NimBLEDevice.h is available in project than ArduinoBleChess will be compiled with BLE_CHESS_LIB_NIM_BLE_ARDUINO flag in order to work with that BLE library.

But when ArduinoBleChess is compiled __has_include("NimBLEDevice.h") return false and BLE_CHESS_LIB_NIM_BLE_ARDUINO is not defined. ArduinoBleChess library compiles without this flag. But main project that has library ArduinoBleChessand NimBLE-Arduino in lib_deps compiles with __has_include("NimBLEDevice.h") equals true, that cause linking error.

If I add hacked #include <NimBLEDevice.h> like

#include <NimBLEDevice.h>
...
#elif __has_include("NimBLEDevice.h")
    #include <NimBLEDevice.h>
    #define BLE_CHESS_LIB_NIM_BLE_ARDUINO

than __has_include("NimBLEDevice.h") return true on both ArduinoBleChess and main project.

Perhaps it is PlatformIO issue, I think that __has_include("NimBLEDevice.h") should return the same value for main project and for libraries in lib_deps.

Link to library ArduinoBleChess/src/BleChessDefines.h at main · vovagorodok/ArduinoBleChess · GitHub

I can create example of this issue if needed

You was right @maxgerhardt, issue was in lib_ldf_mode. lib_ldf_mode=deep+ in my case.

After checking Library Dependency Finder (LDF) — PlatformIO latest documentation

Looks that + (mean evaluate C/C++ Preprocessor conditional syntax) removes code before compilation. Using deep or chain(default) without + fix an issue and maim project + libraries compile as expected.

Issue exist only when chain+ or deep+. Do You think it is correct behavior or preprocessor should know more about dependent libraries/includes?