CMake构建嵌套子目录失败。

huangapple go评论70阅读模式
英文:

CMake failing to build nested subdirectories

问题

以下是您提供的内容的翻译:

在一个固件项目(一个ESP32项目)中,有以下相对标准的目录结构:

文件夹结构

- myProject/
         - CMakeLists.txt
         - sdkconfig
         - components/ - component1/ - CMakeLists.txt
		 
                                     - component1a/ - CMakeLists.txt
                                                    - src/monkey_test.c
													- include/monkey_test.h
													 
									 - component1b/	- CMakeLists.txt
													- src/src1b.c
													- include/src1b.h
													 
                       - component2/ - CMakeLists.txt
                                     - src/src2.c
                                     - include/ - src2.h
									 
         - main/       - src/app_main.c
                       - src/other_stuff.c

         - build/

现在让我们从可能的最简单的事情开始。如果我创建monkey_test.h和.c文件如下:

源文件

#include <monkey_test.h>

int monkey_test(void) {
    return 1;
}

包含文件

#ifndef MONKEY_WIFI_H__
#define MONKEY_WIFI_H__

int monkey_test(void);

#endif

主文件

#include <monkey_test.h>
main() {
  
    sprintf("test value %s", monkey_test());
	
}

CMake文件

顶级CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/components)
list(APPEND EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/../common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(proj_name)

component1 CMakeLists.txt

list(APPEND EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/component1a)

所有组件的Component CMakeLists.txt

idf_component_register(  
    SRC_DIRS     "src"     
    INCLUDE_DIRS "include" 
)

当我构建这个项目时,它不起作用。

../main/src/app_main.c:54:10: 严重错误: monkey_test.h: 没有那个文件或目录
#include <monkey_test.h>;

我尝试过的事情

我尝试将component1的CMakeLists.txt重写为include(wifi/CMakeLists.txt)idf_build_process(wifi)。都没有起作用,我不太清楚为什么我会这么想。

此外,我尝试删除组件的CMakeLists.txt,并替换component1的CMakeLists.txt以直接将组件引入其中,但即使那样也没有起作用???

idf_component_register(  
     SRC_DIRS  "component1a/src"            
     INCLUDE_DIRS "component1a/include"     
)

我确定问题就在眼前,但我真的很迷茫,有人知道我在这里做错了吗?

英文:

Take the following fairly standard looking directory structure for a firmware project (an ESP32 project):

Folder Struct

- myProject/
         - CMakeLists.txt
         - sdkconfig
         - components/ - component1/ - CMakeLists.txt
		 
                                     - component1a/ - CMakeLists.txt
                                                    - src/monkey_test.c
													- include/monkey_test.h
													 
									 - component1b/	- CMakeLists.txt
													- src/src1b.c
													- include/src1b.h
													 
                       - component2/ - CMakeLists.txt
                                     - src/src2.c
                                     - include/ - src2.h
									 
         - main/       - src/app_main.c
                       - src/other_stuff.c

         - build/

Now let's start with the simplest thing possible. If I create monkey_test.h & .h as:

Source

#include &lt;monkey_test.h&gt;

int monkey_test(void) {
    return 1;
}

Include

#ifndef MONKEY_WIFI_H__
#define MONKEY_WIFI_H__

int monkey_test(void);

#endif

Main

#include &lt;monkey_test.h&gt;
main() {
  
    sprintf(&quot;test value %s&quot;, monkey_test());
	
}

CMake Files

Top Level CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/components)
list(APPEND EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/../common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(proj_name)

component1 CMakeLists.txt

list(APPEND EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/component1a)

Component CMakeLists.txt (for all components)

idf_component_register(  
    SRC_DIRS     &quot;src&quot;     
    INCLUDE_DIRS &quot;include&quot; 
)

When I build this, it doesn't work.

../main/src/app_main.c:54:10: fatal error: monkey_test.h: No such file or directory
#include <monkey_test.h>

Things I've tried

I tried rewriting the component1 CMakeLists.txt as include(wifi/CMakeLists.txt) and idf_build_process(wifi). Neither work, and I don't really know why I thought it might.

Also, I've tried just removing the component CMakLists.txt and replacing the component1 CMakeLists.txt to directly bring in the component there but even that didn't work???

idf_component_register(  
     SRC_DIRS  &quot;component1a/src&quot;            
     INCLUDE_DIRS &quot;component1a/include&quot;     
)

I'm sure it's staring me in the face, and I'm being very blind indeed, but anyone know what I'm doing wring here?

答案1

得分: 1

以下是您要翻译的内容:

您不能真正在此回答的时间之前进行操作。

问题如下:

idf superset的概念是CMake命令的超集(例如,所有以idf*为前缀的命令,例如idf_components_register),其目的是自动解决快速变化的多个组件之间的依赖关系。因此,作者所做的是让脚本遍历所有组件和EXTRA_COMPONENTS_DIR中的文件夹,并拾取任何将自己注册为idf组件的组件并记住其依赖关系。项目将自动创建CMake目标,并将每个依赖组件链接到彼此。

那么,如果您只是使用add_subdirectory将子组件包含到生成树中怎么办?您可以这样做,但只能在脚本模式处理idf_component_register之后进行,如果您在CMake之前放置该命令,CMake会抱怨add_subdirectory不是可脚本化的命令。如果您将其放在之后,子组件将不会被包含在依赖图中,因为脚本在执行idf_components_register之后完成,所以它将不会构建。

您可以手动为每个单独的子组件添加CMakeTargets,并将其链接回根组件,就像esp_mbedls所做的那样。如果您从外部存储库中包含组件,这是一种方法,但仅在您的子组件不依赖于其他esp_idf组件时才有效,因为对于手动组件,链接目标不会自动添加(因为在那时已经执行了上述脚本)。

我希望Espressif将来会为嵌套组件添加支持,但在那之前,我们不幸地只能使用提供给我们的解决方案。

我目前处理的方式是只有一个metacomponent“管理”子组件,即将每个子组件的头文件和源文件添加到其自己的源文件和包含中。

英文:

You can't really as of the time of this answer.

The problem is the following:

The idea of the idf superset of CMake commands (e.g. all commands prefixed with idf*, such as for example idf_components_register) is to automatically resolve dependencies across a multitude of components that change rapidly. So what the authors did was to have a script walk through all folders in components and EXTRA_COMPONENTS_DIR and pick up any component that registers itself as an idf component and remember its dependencies. The project will then automatically create CMake targets and link each dependent component against each other.

So what if you just include the subcomponenent into the generator tree using add_subdirectory? You can do that, but only AFTER script mode has processed idf_component_register, if you put the command before CMake will complain that add_subdirectory is not a scriptable command. And if you put it after, the subcomponents will not be taken up in the dependency graph as the script completes after executing idf_components_register, so it will not build.

You could manually add CMakeTargets for each individual subcomponent, and link it back to the root component such as done by esp_mbedls. If you include components from external repos this is the way to go, but it only works if your subcomponent doesn't depend on other esp_idf components, as the link targets won't be added automatically for manual components (as the aforementioned script has already been executed by that time).

I hope espressif will add support for nested components in the future, until then we're stuck with the solution that are provided to us unfortunately.

The way I handle it right now is to just have one metacomponent that "manages" the subcomponent, i.e. it adds headers and sources of each subcomponent into its own sources and includes.

huangapple
  • 本文由 发表于 2023年4月13日 14:58:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76002500.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定