Reputation: 731
I'm trying to force the esp-idf build system to make such trivial thing as adding external library to the application. It is completely straightforward in plain CMake but for some reason it is not working in esp-idf awkward ecosystem.
The project structure is like below:
.
├── 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
app/CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS "components")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(app)
app/main/CMakeLists.txt:
idf_component_register(SRCS "mm01.c"
INCLUDE_DIRS "."
REQUIRES
DummyLibComponent
)
app/main/app.c:
#include <stdio.h>
#include "test.h"
void app_main(void)
{
int ret = test_component();
}
app/components/DummyLib/CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(DummyLib)
add_library(${PROJECT_NAME} STATIC
test.cpp
)
target_include_directories(${PROJECT_NAME} PUBLIC
.
)
app/components/DummyLib/test.cpp:
#include "test.h"
int test_component()
{
return 2+3;
}
app/components/DummyLib/test.h:
int test_component();
app/components/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)
Directory tree:
esp-idf <- here goes the esp-idf repo which is not included here
app <- here is the application created using the 'create-project' command. It builds normally when no additional components are defined.
app/components <- this directory is setup in 'EXTRA_COMPONENT_DIRS'
app/components/DummyLib <- any static library that works normally in plain CMake
app/components/DummyLibComponent <- a component that wraps the DummyLib to make i work with the esp-idf ecosystem
For this setup when I try to build the app using idf.py build
it fails with that errors:
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)
What is wrong with this setup? What does 'poject command is not scriptable' mean? What is the proper way to add EXTERNAL library without modifying it?
Upvotes: 1
Views: 2484
Reputation: 65860
The error
project command is not scriptable
means that given command (project
in your case) is from the list of project commands, which shouldn't be used in the scripting mode of CMake (cmake -P </path/to/script>
). While you write the CMakeLists.txt
which is normally processed in project mode (cmake </path/to/source/dir>
), ESP-IDF actually has two passes:
CMakeLists.txt
is processed in the scripting mode, until it calls a specific function. This pass is needed for collect information about components.CMakeLists.txt
in project mode.That is, until a component' CMakeLists.txt
calls a ESP-IDF specific function, it shouldn't use project-only commands.
The usual function which terminates scripting mode in ESP-IDF processing is idf_component_register
. But there are other "terminating" functions.
Your library app/components/DummyLib
is located in the component's directory, so ESP-IDF tries read its CMakeLists.txt
in a scripting mode. This is why you get the error.
You could move the library files into some other directory. E.g., into app/components/DummyLibComponent/src/
. In that case you may adjust app/components/DummyLibComponent/CMakeLists.txt
to use new location of the library:
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)
Alternatively, you may create pure CMake component. Its scripting mode is terminated by add_library
call. So make sure you have no project command before that call:
# app/components/DummyLib/CMakeLists.txt
#
add_library(${PROJECT_NAME} STATIC
test.cpp
)
target_include_directories(${PROJECT_NAME} PUBLIC
.
)
In that case app/components/DummyLibComponent/CMakeLists.txt
is not needed.
Upvotes: 3