Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C esp idf:具有相同功能的组件的条件包含_C_Esp Idf - Fatal编程技术网

C esp idf:具有相同功能的组件的条件包含

C esp idf:具有相同功能的组件的条件包含,c,esp-idf,C,Esp Idf,我正在做一个项目,需要为几个esp32开发固件。所有的微控制器共享一个共同的代码来处理wifi和mqtt,但是它们都有不同的行为,这是在特定的组件中定义的。我的项目结构如下: - CMakeLists.txt - Makefile - sdkconfig - main - CMakeLists.txt - main.c - components - wifi_fsm - wifi_fs

我正在做一个项目,需要为几个esp32开发固件。所有的微控制器共享一个共同的代码来处理wifi和mqtt,但是它们都有不同的行为,这是在特定的组件中定义的。我的项目结构如下:

    - CMakeLists.txt
    - Makefile
    - sdkconfig
    - main
        - CMakeLists.txt
        - main.c
    - components
        - wifi_fsm
            - wifi_fsm.h
            - wifi_fsm.c
            - CMakeLists.txt
        - mqtt_fsm
            - mqtt_fsm.h
            - mqtt_fsm.c
            - CMakeLists.txt
        - entity_1
            - entity_1.h
            - entity_1.c
            - CMakeLists.txt
        - entity2
            - entity2.h
            - entity2.c
            - CMakeLists.txt
        ...
每个实体都定义了一些具有标准名称的函数,这些函数为实体本身实现特定的逻辑,并在共享代码(main、wifi_-fsm、mqtt_-fsm)中调用

我的想法是使用一个条件语句任意包含一个特定的行为,这样编译器就可以根据所包含的实体,将对上述函数的调用链接到特定包含库中的函数。因此,在
main.c
的开头,我刚刚添加了以下几行,目的是必须更改唯一定义的预处理器符号以编译不同的enity行为

#define ENTITY_1

#ifdef ENTITY_1
  #include "entity_1.h"
#elif defined ENTITY_2
  #include "entity_2.h"
#elif ...
#endif

#include "wifi_fsm.h"
#include "mqtt_fsm.h"

void app_main(void)
{
   while(1){
     ...
   }
}
一方面,编译器显然工作正常,在没有错误或警告的情况下成功编译,这意味着include链工作正常,否则将抛出标准函数的重复名称错误。另一方面,它总是按字母顺序与第一个实体链接,例如执行组件实体_1的init_entity()中包含的代码。如果我重命名实体_1中的标准函数,那么它将链接到实体_2

如果上述方法错误,我可能会使用指向标准调用的指针链接到每个实体中的特定函数,但我想首先了解我的方法中的错误

编辑以响应Bodo的请求(CMakeFile.txt的内容)

项目:

cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(proj)
主要内容:

组成部分:

set(COMPONENT_SRCDIRS "src")
set(COMPONENT_ADD_INCLUDEDIRS "include")

set(COMPONENT_REQUIRES log freertos driver nvs_flash esp_http_server mqtt)

register_component()

这个答案是基于猜测,因为我没有足够的信息。出于同样的原因,它在某些部分是不完整的,或者可能与问题的用例不完全匹配

关于如何构建项目的详细信息似乎隐藏在
cmake
include文件中,如
project.cmake
或嵌套的include文件

我的猜测是,构建系统从每个组件的源代码创建库,然后将主对象文件与库链接起来。在这种情况下,链接器将在满足依赖关系的第一个库中找到类似
init_entity
的符号。这意味着将使用链接器命令行中首先列出的库(=组件)

如果链接器命令行将显式列出对象文件
entity_1.o
entity_2.o
,我将看到一条关于重复符号
init_entity
的错误消息

我可以提出两种解决问题的方法:

  • 确保仅使用所选实体构建程序

  • 使标识符名称在所有实体中唯一,并根据所选实体使用预处理器宏选择正确的标识符名称


  • 对于第一种方法,您可以在
    CMakeLists.txt
    中使用条件。有关示例,请参见。可能是
    register\u component()
    负责将组件添加到构建中。在这种情况下,您可以将其包装在一个条件中

    但是,如果文件是自动生成的,那么修改
    CMakeLists.txt
    可能是错误的


    对于第二种方法,您应该重命名实体中的标识符以使其唯一。相应的头文件可以定义一个宏,用选定实体的特定标识符替换标识符的通用名称

    在使用选定实体的代码中,您将始终使用通用名称,而不是单个名称

    例如:

    实体_1.c

    #include "entity_1.h"
    
    void init_entity_1(void)
    {
    }
    
    #include "entity_2.h"
    
    void init_entity_2(void)
    {
    }
    
    实体_2.c

    #include "entity_1.h"
    
    void init_entity_1(void)
    {
    }
    
    #include "entity_2.h"
    
    void init_entity_2(void)
    {
    }
    
    实体_1.h

    void init_entity_1(void);
    // This replaces the token/identifier "init_entity" with "init_entity_1" in subsequent source lines
    #define init_entity init_entity_1
    // or depending on the parameter list something like
    // #define init_entity() init_entity_1()
    // #define init_entity(x,y,z) init_entity_1(y,x,z)
    
    void init_entity_2(void);
    #define init_entity init_entity_2
    
    实体_2.h

    void init_entity_1(void);
    // This replaces the token/identifier "init_entity" with "init_entity_1" in subsequent source lines
    #define init_entity init_entity_1
    // or depending on the parameter list something like
    // #define init_entity() init_entity_1()
    // #define init_entity(x,y,z) init_entity_1(y,x,z)
    
    void init_entity_2(void);
    #define init_entity init_entity_2
    
    main.c

    #define ENTITY_1
    
    #ifdef ENTITY_1
      #include "entity_1.h"
    #elif defined ENTITY_2
      #include "entity_2.h"
    #elif ...
    #endif
    
    
    void some_function(void)
    {
        init_entity();
    }
    
    在本例中,使用
    #define ENTITY_1
    ,预处理器将
    某些功能更改为

    void some_function(void)
    {
        init_entity_1();
    }
    

    在编译步骤之前,链接器将使用
    entity_1.c
    中的
    init_entity_1
    。然后,优化链接器可能会忽略对象文件
    实体_2.o
    或相应的库,因为它未使用。

    请回答您的问题,并添加有关如何定义预处理器符号
    实体_1
    实体_2
    的详细信息,等。您可以修改
    CMakeLists.txt
    以有条件地仅使用
    组件/实体_1
    组件/实体_2
    等中的一个。显示相关的
    CMakeLists.txt
    文件。@Bodo CMakeList.txt设置为默认值。在组件之间相互依赖的情况下,我只需在集合(组件_需要…)列表中添加条目,“CMakeList.txt设置为默认值”不会告诉任何事情。当我使用编辑器创建
    CMakeLists.txt
    时,我的“默认值”是一个空文件。如果您的IDE创建了
    CMakeLists.txt
    文件,请在问题中说明您使用的IDE以及您如何创建项目/组件(如果与文件内容相关)。显示代码,而不是含糊其辞地描述您的工作。如果您的文件太大,无法在问题中显示,请使用较小的文件创建一个。如果没有看到您的
    CMakeLists.txt
    文件,我无法提出解决方案。(可能是其他人拥有一个水晶球…@Bodo我不知道CMakeFile的内容会添加哪些附加信息,但我将其添加到了问题中。现在,如果您的答案是修改CMakeFile以有条件地包含一个特定的组件,那么这可能会起作用,我希望您能提供一些建议。但是,它仍然没有回答我的问题,这就是我的方法的错误所在,以及为什么一个组件中的方法是链接的,即使该组件未包含在内。事实上,
    CMakeLists.txt
    文件中没有包含足够的信息