ESP-IDF добавляет внешнюю библиотеку/компонент: «команда проекта не поддерживает сценарий»

Я пытаюсь заставить систему сборки esp-idf сделать такую ​​тривиальную вещь, как добавление внешней библиотеки в приложение. Это совершенно просто в простом CMake, но по какой-то причине это не работает в неудобной экосистеме esp-idf.

Структура проекта выглядит следующим образом:

.
├── app
│   ├── CMakeLists.txt
│   ├── components
│   │   ├── DummyLib
│   │   │   ├── CMakeLists.txt
│   │   │   ├── test.cpp
│   │   │   └── test.h
│   │   └── DummyLibComponent
│   │       └── CMakeLists.txt
│   └── main
│       ├── CMakeLists.txt
│       └── mm01.c
└── esp-idf

6 directories, 7 files

приложение/CMakeLists.txt:


cmake_minimum_required(VERSION 3.16)

set(EXTRA_COMPONENT_DIRS "components")

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(app)

приложение/основной/CMakeLists.txt:



idf_component_register(SRCS "mm01.c"
    INCLUDE_DIRS "."
    REQUIRES
        DummyLibComponent
)

приложение/основной/приложение.с:



#include <stdio.h>
#include "test.h"

void app_main(void)
{
    int ret = test_component();
}

приложение/компоненты/DummyLib/CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)                                                                                                          
project(DummyLib)
add_library(${PROJECT_NAME} STATIC
    test.cpp
)
target_include_directories(${PROJECT_NAME} PUBLIC
    .
)

приложение/компоненты/DummyLib/test.cpp:

#include "test.h"

int test_component()
{
    return 2+3;
}

приложение/компоненты/DummyLib/test.h:

int test_component();

приложение/компоненты/DummyLibComponent/CMakeLists.txt:

idf_component_register(
        INCLUDE_DIRS ../DummyLib # Not sure where should it point? To the include referenced by the lib or by relative path?        REQUIRES DummyLib
)

add_subdirectory(../DummyLib DummyLib)

target_link_libraries(${COMPONENT_LIB} INTERFACE DummyLib)

Дерево каталогов:

esp-idf <- здесь находится репозиторий esp-idf, которого здесь нет

app <- вот приложение, созданное с помощью команды create-project. Он строится нормально, когда не определены дополнительные компоненты.

app/components <- этот каталог настроен в «EXTRA_COMPONENT_DIRS»

app/components/DummyLib <- любая статическая библиотека, которая нормально работает в простом CMake

app/components/DummyLibComponent <- компонент, обертывающий DummyLib, чтобы я мог работать с экосистемой esp-idf.

Для этой настройки, когда я пытаюсь создать приложение с помощью idf.py build, оно завершается с ошибкой:

idf.py build                                                      
Executing action: all (aliases: build)
Running ninja in directory <PATH_TO_PROJECT>/app/build
Executing "ninja all"...
[0/1] Re-running CMake...-- Building ESP-IDF components for target esp32s3
CMake Error at <PATH_TO_PROJECT>/esp-idf/tools/cmake/component.cmake:224 (message):
  CMake Warning (dev) at build_properties.temp.cmake:8:

    Syntax Warning in cmake code at column 51

  

    Argument not separated from preceding token by whitespace.

  Call Stack (most recent call first):

    <PATH_TO_PROJECT>/esp-idf/tools/cmake/scripts/component_get_requirements.cmake:3 (include)

  This warning is for project developers.  Use -Wno-dev to suppress it.

  

  CMake Error at
  <PATH_TO_PROJECT>/app/components/DummyLib/CMakeLists.txt:2
  (project):

    project command is not scriptable

  Call Stack (most recent call first):

    <PATH_TO_PROJECT>/esp-idf/tools/cmake/scripts/component_get_requirements.cmake:106 (include)
    <PATH_TO_PROJECT>/esp-idf/tools/cmake/scripts/component_get_requirements.cmake:124 (__component_get_requirements)


Что не так с этой настройкой? Что означает «команда проекта не поддерживает сценарий»? Как правильно добавить ВНЕШНЮЮ библиотеку без ее изменения?

ESP-IDF рассматривает каждый подкаталог components/ как компонент, таким образом ожидая найти вызов idf_component_register в их CMakeLists.txt. Но ваш components/DummyLib/CMakeLists.txt не содержит этого вызова. Если вы хотите создать некомпонентный CMakeLists.txt, то не помещайте его в подкаталог components/. Вы можете создать свою библиотеку, например. под app/components/DummyLibComponent/src/, поэтому скрипт app/components/DummyLibComponent/CMakeLists.txt может включить его через add_subdirectory(src).

Tsyvarev 17.04.2023 16:54

@Tsyvarev ваше предложение решает проблему. На данный момент Ив получил DummyLib вне каталога component. Он компилируется, но не будет ссылаться из-за неопределенной ссылки на test_component(). Библиотека построена. Объект содержит функцию. Библиотека отсутствует в командной строке компоновщика. Не уверен, почему. Попытался создать базовый компонент без внешней зависимости, как описано в документах, но не удалось по той же причине.

killdaclick 17.04.2023 21:56

если у вас возникла новая проблема, напишите новый вопрос с минимально воспроизводимым примером этой проблемы

starball 17.04.2023 21:57
target_link_libraries(${COMPONENT_LIB} INTERFACE DummyLib) — связывает с DummyLib всех пользователей компонента, но не сам компонент. Вместо этого используйте связь PUBLIC или PRIVATE.
Tsyvarev 17.04.2023 22:12

undefined reference появился, потому что библиотека CPP, а основное приложение, в котором была вызвана функция, — простой C. facepalm

killdaclick 17.04.2023 23:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
209
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ошибка

команда проекта не поддерживает сценарий

означает, что данная команда (project в вашем случае) входит в список команд проекта , которые не следует использовать в режиме сценариев CMake (cmake -P </path/to/script>). Пока вы пишете CMakeLists.txt, который обычно обрабатывается в режиме проекта (cmake </path/to/source/dir>), ESP-IDF фактически имеет два прохода:

  1. Во-первых, ESP-IDF выполняет итерацию по всем каталогам компонентов, каждый компонент CMakeLists.txt обрабатывается в режиме сценария, пока не вызовет определенную функцию. Этот проход необходим для сбора информации о компонентах.
  2. Затем ESP-IDF обрабатывает CMakeLists.txt каждого компонента в режиме проекта.

То есть, пока компонент не вызовет специфическую функцию ESP-IDF, он не должен использовать команды только для проекта.

Обычная функция, которая завершает режим сценариев при обработке ESP-IDF, — это CMakeLists.txt. Но есть и другие «завершающие» функции.

Ваша библиотека idf_component_register находится в каталоге компонента, поэтому ESP-IDF пытается прочитать ее app/components/DummyLib в режиме скрипта. Вот почему вы получаете ошибку.

Вы можете переместить файлы библиотеки в другой каталог. Например, в CMakeLists.txt. В этом случае вы можете настроить app/components/DummyLibComponent/src/ для использования нового местоположения библиотеки:

idf_component_register(
        INCLUDE_DIRS ../DummyLib # Not sure where should it point? To the include referenced by the lib or by relative path?
)

add_subdirectory(src)

target_link_libraries(${COMPONENT_LIB} PUBLIC DummyLib)

Кроме того, вы можете создать чистый компонент CMake. Его режим сценария завершается вызовом app/components/DummyLibComponent/CMakeLists.txt. Поэтому убедитесь, что перед этим вызовом у вас нет команды проекта:

# app/components/DummyLib/CMakeLists.txt
# 
add_library(${PROJECT_NAME} STATIC
    test.cpp
)
target_include_directories(${PROJECT_NAME} PUBLIC
    .
)

В этом случае add_library не нужен.

Другие вопросы по теме