Page 1 of 2

undefined reference to esp_blufi_gap_event_handler

Posted: Thu Jan 20, 2022 5:12 pm
by glrtheil
Working on integrating blufi into our project. For some reason though, even after verifying config options between the example project and our project, I am getting a linker error when compiling. Our project is majority C++.
FAILED: controller-firmware.elf
cmd.exe /C "cd . && C:\Users\Ricky\.espressif\tools\xtensa-esp32-elf\esp-2021r2-8.4.0\xtensa-esp32-elf\bin\xtensa-esp32-elf-g++.exe -mlongcalls -Wno-frame-address @CMakeFiles\controller-firmware.elf.rsp -o controller-firmware.elf && cd ."
c:/users/ricky/.espressif/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: esp-idf/main/libmain.a(BluetoothService.cpp.obj):(.literal._ZN16BluetoothService31esp_blufi_gap_register_callbackEv+0x0): undefined reference to `esp_blufi_gap_event_handler(esp_gap_ble_cb_event_t, esp_ble_gap_cb_param_t*)'

Seems that esp_blufi.c is somehow not being included for the compiler.

Here are the includes I'm using

Code: Select all

#include "esp_err.h"
#include "esp_blufi_api.h"
#include "esp_log.h"
#include "esp_blufi.h"
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
And the method making the call

Code: Select all

esp_err_t BluetoothService::esp_blufi_gap_register_callback(void)
{
   int rc;
   rc = esp_ble_gap_register_callback(esp_blufi_gap_event_handler);
    if(rc){
        return rc;
    }
    return esp_blufi_profile_init();
}

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Fri Jan 21, 2022 10:19 am
by akshaay24

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Fri Jan 21, 2022 3:38 pm
by glrtheil
akshaay24 wrote:
Fri Jan 21, 2022 10:19 am
Refer this explanation and try https://www.youtube.com/watch?v=COB_vBtTdiY&t=23s
Not sure what you're referring to. I'm not using eclipse, nor am I looking to add a new component to a project. If you're referring to the component sources, these are not present in the example application. I've scoured the files in the blufi example and nowhere is esp_blufi.c in any of the cmakelists.txt files.

blufi/CMakeLists.txt

Code: Select all

# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(blufi_demo)
blufi/main/CMakeLists.txt

Code: Select all

idf_component_register(SRCS "blufi_example_main.c"
                            "blufi_security.c"
                            "blufi_init.c"
                    INCLUDE_DIRS ".")
The files in my project are set up similarly, but I've never had to refer to a c file in the idf in any cmakelists.txt file.

esp\esp-idf\components\bt\host\bluedroid\api\esp_gap_ble_api.c is included for the compiler.
esp\esp-idf\components\bt\host\bluedroid\api\esp_bt_main.c is included for the compiler
esp\esp-idf\components\bt\common\btc\profile\esp\blufi\bluedroid_host\esp_blufi.c is not included for the compiler.

The question is, why isn't esp\esp-idf\components\bt\common\btc\profile\esp\blufi\bluedroid_host\esp_blufi.c included in my project, but it is in the blufi example even though not specified anywhere? I'm guessing it's a menuconfig option, but I am not seeing anything when comparing the two projects. My guess would be that "Include blufi function" would include esp_blufi.c, but that doesn't seem to be the case.

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Fri Jan 21, 2022 4:07 pm
by hustenhabas
you probably need to add a require "bt" to your component's CMakeLists.txt

Code: Select all

idf_component_register(SRCS "bluetooth.c"
                    INCLUDE_DIRS "include"
                    PRIV_REQUIRES nvs_flash bt)
in this example i've added PRIV_REQUIRES for nvs_flash and bluetooth

or change the Bluetooth boolean in menuconfig so it compiles the right way

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Fri Jan 21, 2022 6:18 pm
by glrtheil
hustenhabas wrote:
Fri Jan 21, 2022 4:07 pm
you probably need to add a require "bt" to your component's CMakeLists.txt

or change the Bluetooth boolean in menuconfig so it compiles the right way
The Bluetooth boolean is set true, as well as blufi set true. Looking at the bt component CMakeLists.txt file, it's definitely there when CONFIG_BT_BLUEDROID_ENABLED is true.

Code: Select all

list(APPEND srcs "common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c")
I just don't understand why it's all by itself in that APPEND, and not with the items directly above it. It's also tabbed one additional level compared to the preceding and subsequent lines, but I don't think that matters.

I also notice when looking at the build logs, esp_blufi.c is being included. I see it in .ninja_log, build.ninja, compile_commands.json, and the map file for our project.

I'm starting to think this isn't an include issue, but rather something to do with a type mismatch between c and c++. I'm trying to add that callback in a c++ file, but the entire blufi example is in c.

I also notice that calling esp_blufi_disconnect() also throws a linker error, which sort of destroys my theory that it's a c v. c++ issue.

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Fri Jan 21, 2022 9:30 pm
by chegewara

Code: Select all

#if  defined(CONFIG_BT_BLE_BLUFI_ENABLE) || defined(CONFIG_BT_NIMBLE_BLUFI_ENABLE)
https://github.com/espressif/esp-idf/bl ... lufi.c#L36

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Mon Jan 24, 2022 4:38 pm
by glrtheil
chegewara wrote:
Fri Jan 21, 2022 9:30 pm

Code: Select all

#if  defined(CONFIG_BT_BLE_BLUFI_ENABLE) || defined(CONFIG_BT_NIMBLE_BLUFI_ENABLE)
https://github.com/espressif/esp-idf/bl ... lufi.c#L36
CONFIG_BT_BLE_ENABLED=y is what's in my sdkconfig file.

This means that because it's defined, UC_BT_BLUFI_ENABLE should be TRUE, however when I reach the code where it should be true, both UC_BT_BLUFI_ENABLE and BLUFI_INCLUDED are undefined. This means that bt_user_config.h is not being included, which means bt_common.h is also not being included. What I don't see is what includes bt_common.h.

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Mon Jan 24, 2022 5:20 pm
by chegewara
I will try to explain it slower:
- CONFIG_BT_BLE_ENABLED=y is not the same as CONFIG_BT_BLE_BLUFI_ENABLE
- CONFIG_BT_BLE_ENABLED=y wont enable blufi no matter how much you will want it
- blufi is not the same as BLE, even if blufi is protocol on top of BLE
- here is espressif blufi example, with default sdkconfigs
https://github.com/espressif/esp-idf/bl ... esp32#L474

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Mon Jan 24, 2022 8:36 pm
by glrtheil
chegewara wrote:
Mon Jan 24, 2022 5:20 pm
I will try to explain it slower:
- CONFIG_BT_BLE_ENABLED=y is not the same as CONFIG_BT_BLE_BLUFI_ENABLE
- CONFIG_BT_BLE_ENABLED=y wont enable blufi no matter how much you will want it
- blufi is not the same as BLE, even if blufi is protocol on top of BLE
- here is espressif blufi example, with default sdkconfigs
https://github.com/espressif/esp-idf/bl ... esp32#L474
Apologies. I didn't state the correct config variable when writing the post (they are right next to each other in sdkconfig). CONFIG_BT_BLE_BLUFI_ENABLE=y is what's in sdkconfig. The rest of my post is correct.

Image

I have compared the config file of the blufi sample project with my config file, but am not seeing any difference that would cause this issue.

Code: Select all

ESP_LOGE(TAG, "callback init: CONFIG_BT_BLE_BLUFI_ENABLE: %d", CONFIG_BT_BLE_BLUFI_ENABLE);
#ifdef UC_BT_BLUFI_ENABLE
    ESP_LOGE(TAG, "callback init: UC_BT_BLUFI_ENABLE: %d", UC_BT_BLUFI_ENABLE);
#endif

#ifdef BLUFI_INCLUDED
    ESP_LOGE(TAG, "callback init: BLUFI_INCLUDED: %d", BLUFI_INCLUDED);
#endif
Running that chunk of code, it compiles, runs and confirms that CONFIG_BT_BLE_BLUFI_ENABLE is defined. That being defined should result in UC_BT_BLUFI_ENABLE being defined as TRUE, but I do not get the log for that item, and if I uncomment the #ifdef, it will not compile. Same for BLUFI_INCLUDED.

To clarify, if I run this code

Code: Select all

    ESP_LOGE(TAG, "callback init: CONFIG_BT_BLE_BLUFI_ENABLE: %d", CONFIG_BT_BLE_BLUFI_ENABLE);
    ESP_LOGE(TAG, "callback init: UC_BT_BLUFI_ENABLE: %d", UC_BT_BLUFI_ENABLE);
    ESP_LOGE(TAG, "callback init: BLUFI_INCLUDED: %d", BLUFI_INCLUDED);
I get this
../main/Services/BluetoothService.cpp:192:5: note: in expansion of macro 'ESP_LOGE'
ESP_LOGE(TAG, "callback init: UC_BT_BLUFI_ENABLE: %d", UC_BT_BLUFI_ENABLE);
^~~~~~~~
../main/Services/BluetoothService.cpp:192:60: error: 'UC_BT_BLUFI_ENABLE' was not declared in this scope
ESP_LOGE(TAG, "callback init: UC_BT_BLUFI_ENABLE: %d", UC_BT_BLUFI_ENABLE);
^~~~~~~~~~~~~~~~~~
C:/Users/Ricky/esp/esp-idf/components/log/include/esp_log.h:337:137: note: in definition of macro 'ESP_LOG_LEVEL'
else if (level==ESP_LOG_VERBOSE ) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
^~~~~~~~~~~
C:/Users/Ricky/esp/esp-idf/components/log/include/esp_log.h:299:38: note: in expansion of macro 'ESP_LOG_LEVEL_LOCAL'
#define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
^~~~~~~~~~~~~~~~~~~
../main/Services/BluetoothService.cpp:192:5: note: in expansion of macro 'ESP_LOGE'
ESP_LOGE(TAG, "callback init: UC_BT_BLUFI_ENABLE: %d", UC_BT_BLUFI_ENABLE);
^~~~~~~~
../main/Services/BluetoothService.cpp:192:60: error: 'UC_BT_BLUFI_ENABLE' was not declared in this scope
ESP_LOGE(TAG, "callback init: UC_BT_BLUFI_ENABLE: %d", UC_BT_BLUFI_ENABLE);
^~~~~~~~~~~~~~~~~~
C:/Users/Ricky/esp/esp-idf/components/log/include/esp_log.h:338:137: note: in definition of macro 'ESP_LOG_LEVEL'
else { esp_log_write(ESP_LOG_INFO, tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
^~~~~~~~~~~
The problem is that even though CONFIG_BT_BLE_BLUFI_ENABLE is defined, UC_BT_BLUFI_ENABLE and BLUFI_INCLUDED are not defined.

Re: undefined reference to esp_blufi_gap_event_handler

Posted: Mon Jan 24, 2022 11:54 pm
by chegewara
Yes, this is expected. Its because those macros are defined in headers:

Code: Select all

#include "bt_common.h"
#include "bt_user_config.h"
and you dont have access to such headers, because those are private includes in bt component:
https://github.com/espressif/esp-idf/bl ... xt#L22-L24
https://github.com/espressif/esp-idf/bl ... s.txt#L603


After more digging i know what is the problem and it is a bug, which should be reported. The problem is that one of header files is not C++ compatible. You can "fix" it in you code like this:

Code: Select all

extern "C" {
#include "esp_blufi.h"
}