Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP-IDF CMakeLists #800

Merged
merged 13 commits into from
Nov 1, 2024
Merged

ESP-IDF CMakeLists #800

merged 13 commits into from
Nov 1, 2024

Conversation

bakerstu
Copy link
Owner

The goal of this pull request is to no longer require a separate OpenMRNIDF repository.

  • Provides a CMakeLists file such that openmrn can be included as a registered idf component as part of a standard ESP-IDF application build.
  • Provides an esp-idf specific include path with appropriate files linked to it.
  • Makes a few minor code tweaks to support the ESP-IDF build.

# Suppress compilation warnings in OpenMRN
###############################################################################

target_compile_options(${COMPONENT_LIB} PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-volatile>)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be PUBLIC?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted for PUBLIC primarily to suppress a warning from Executor.hxx/cxx showing up if you include the hxx in your project. We might be able to get away with INTERFACE though, I'll check and confirm.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted elsewhere, we can reduce this to PRIVATE

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required because of a warning generated by the usage of Executor::sequence_. We should revisit this at some point.

etc/esp-idf/CMakeLists.txt Outdated Show resolved Hide resolved
Copy link
Collaborator

@atanisoft atanisoft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good.

One other warning that we should review:

[1112/1124] Building CXX object esp-idf/main/CMakeFiles/__idf_main.dir/main.cpp.obj
In file included from .../main/ThermalMonitor.hxx:20,
                 from .../main/main.cpp:55:
..../OpenMRNIDF/src/utils/Fixed16.hxx: In member function 'float Fixed16::to_float() const':
..../OpenMRNIDF/src/utils/Fixed16.hxx:274:17: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  274 |         return *reinterpret_cast<float *>(&f);

I'm not 100% certain how we should handle this one. This is coming up in ESP-IDF v5.3 (tested with v5.3.1 locally).

include/esp-idf/can_ioctl.h Show resolved Hide resolved
###############################################################################
# Suppress compilation warnings in OpenMRN
###############################################################################
target_compile_options(${COMPONENT_LIB} PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-volatile>)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with INTERFACE instead of PUBLIC the following warning is logged:

[880/1084] Building CXX object esp-idf/OpenMRNIDF/CMakeFiles/__idf_OpenMRNIDF.dir/src/executor/Executor.cpp.obj
.../managed_components/OpenMRNIDF/src/executor/Executor.cpp: In member function 'virtual void* ExecutorBase::entry()':
.../managed_components/OpenMRNIDF/src/executor/Executor.cpp:322:15: warning: '++' expression of 'volatile'-qualified type is deprecated [-Wvolatile]
  322 |             ++sequence_;
      |               ^~~~~~~~~

We can reduce this to PRIVATE but we should revisit this specific file and evaluate how we can eliminate the warning entirely (gcc pragma option perhaps?)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that we should revisit this.

cd <application path>/components
ln -s <openmrn path>/etc/esp-idf/ openmrn
```
This will result in openmrn being compiled as a registered idf component with the name "openmrn".
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also document using idf_component.yml which is the approach recommended by Espressif for dependency management.

A version of this could be:

dependencies:
  OpenMRN:
    version: {branch, hash, tag, etc}
    git: https://github.com/bakerstu/openmrn.git
    path: etc/esp-idf

The path line overrides where idf.py looks for the CMakeLists.txt within the referenced repository (it defaults to root of the repository).

If you include override_path it will skip looking at the repository and use a local copy instead, which can use environment variables, such as: ${OPENMRNPATH}/etc/esp-idf.

The version line is optional, when not present idf.py build will collect the latest git hash and record it in dependencies.lock. If there is a newer version available in git it will present the following during build:

-- Building ESP-IDF components for target esp32s3
NOTICE: 
Following dependencies have new versions available:
Dependency "OpenMRNIDF": "5d7b0b3157e3411b3f71ccfacedaef6cb1202bff" -> "63e2b2e3f6ba34719f50194240113247793ac3ac"
Consider running "idf.py update-dependencies" to update your lock file.

@@ -0,0 +1,162 @@
set(SRCS
$ENV{OPENMRNPATH}/src/dcc/dcc_constants.cxx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of relying on $ENV{OPENMRNPATH} we likely should use ${CMAKE_CURRENT_SOURCE_DIR} to determine where the source files and include paths actually are relative to the CMakeLists.txt file.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the CMakeLists.txt is not on the top level, then we would probably need an variable that denotes toplevel first.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

${COMPONENT_DIR} can also be used for referencing the location of CMakeLists.txt

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not in favor of changing this. We have an established history of a top level "config" file that setups up environment variables for a repository. @balazsracz and I have also decided to use a Makefile for the top level project build that invokes CMake. We find this a bit more intuitive as it allows us to simply use the command "make" and then all the CMake magic happens under the hood.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...also, we have additional non-CMake related targets in our project makefile for doing special tasks such as creating "release" artifacts, etc.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, OpenMRNIDF will continue to live on as it's not feasible to pass in env vars when using idf_component.yml to manage dependencies.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm revisiting this. It looks like ${COMPONENT_DIR} does not follow the symbolic link to the origin path. I'm exploring options.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atanisoft I pushed a possible solution. Can you take a look?

etc/esp-idf/CMakeLists.txt Outdated Show resolved Hide resolved
src/utils/SocketClient.cxx Show resolved Hide resolved
etc/esp-idf/CMakeLists.txt Outdated Show resolved Hide resolved
set(IDF_DEPS
app_update
bootloader_support
driver
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to put this on my update list for ESP-IDF v5.3 support updates (hopefully a relatively small update), this driver component was split up and can be replaced with:

  • esp_driver_gpio
  • esp_driver_i2c

but there is currently a compilation failure in Esp32HardwareI2C.hxx due to a dependency on the older driver format. I'll take care of migrating to the newer driver code and cleanup of this specific line as optional based on ESP-IDF version (pre-5.3 it will include driver and current Esp32HardwareI2C code, 5.3+ it will depend on the newer I2C driver).

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted.

etc/esp-idf/CMakeLists.txt Outdated Show resolved Hide resolved
@@ -0,0 +1,7 @@
# ESP-IDF Build Instructions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please consider adding an idf_component.yml in this directory with the following contents:

dependencies:
  idf: "<5.3"

This will restrict compilation of OpenMRN to ESP-IDF version 5.2.x or earlier by default until I can get a PR setup for the driver updates in ESP-IDF v5.3

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use the IDF component manager for several reasons:

  • it becomes impossible to compile the code when the espressif servers are not reachable over the internet (have you tried compiling code while you are on an airplane?)
  • the compilation becomes not deterministic from the git hash

Both of these are big problems for a professional project. Reproducible compilation results are essential for finding bugs and retroactive maintenance. We are talking about 10y+ of support needs in this product domain, not a 6-month product development cycle like many other domains.

Having said that, it should be possible to use ther component manager if someone wants it. It is just a requirement for the compilation and dependencies to work correctly if someone chooses not to use it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproducible builds is a great call-out and has a rather simple solution. Limit your external dependencies (beyond esp-idf itself) AND embed the github link and hash (which typically can not change) and the build system will only use that specific version for external dependencies.

As for offline (airplane) usage, this is doable with small adjustments to the idf_component.yml and pre-staging the external dependencies locally. In the idf_component.yml file you would leverage the override_path or path element to shortcut the lookup of the component with a local path to where the dependency actually lives. You might need to remove version/git/etc elements though (I forget now on that).

Cloning the dependencies locally into a components tree (as git submodules) would also work for this, optionally adding the following snippet to the top level CMakeLists.txt file:

list(APPEND EXTRA_COMPONENT_DIRS "../common_components/Filesystem/")

This allows simplified dependencies mapping in component / main CMakeLists.txt files.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also note that the above snippet would ONLY check the ESP-IDF version and does not specifically deal with dependencies. If the ESP-IDF version check does not match the declared version it will abort the build with a message for the user to fix their ESP-IDF version selection.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atanisoft I've added an idf_component.yml file. This causes a warning for my non-managed build, but we can choose to ignore it. Can you have a look and provide some feedback?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented on the file above, we should just include the basic snippet listed above to only restrict the idf version check.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bakerstu it looks like no variant of declaration in idf_component.yml will work correctly with the current version of the idf component manager that I can find. The path: etc/esp-idf bit tries to force the git checkout to that path rather than reference that path for where to find the top level directory.

I suspect it only applies to when publishing the component to their registry and not for when consuming it. For now let's drop the file and I'll see if I can find a suitable way to make it work correctly or log an issue for them to fix it

@bakerstu
Copy link
Owner Author

Overall looks good.

One other warning that we should review:

[1112/1124] Building CXX object esp-idf/main/CMakeFiles/__idf_main.dir/main.cpp.obj
In file included from .../main/ThermalMonitor.hxx:20,
                 from .../main/main.cpp:55:
..../OpenMRNIDF/src/utils/Fixed16.hxx: In member function 'float Fixed16::to_float() const':
..../OpenMRNIDF/src/utils/Fixed16.hxx:274:17: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  274 |         return *reinterpret_cast<float *>(&f);

I'm not 100% certain how we should handle this one. This is coming up in ESP-IDF v5.3 (tested with v5.3.1 locally).

Probably this is intentional. If so, we should consider an inline disabling of this warning using the push/pop method.

@@ -0,0 +1,6 @@
## IDF Component Manager Manifest File
dependencies:
OpenMRN:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Close, we can comment out this OpenMRN section as it would create a circular dependency which may trip up the dependency logic in esp-idf.

@@ -35,7 +35,7 @@
#ifndef _DRIVERS_ESP32GPIO_HXX_
#define _DRIVERS_ESP32GPIO_HXX_

#include "freertos_drivers/arduino/GpioWrapper.hxx"
#include "freertos_drivers/common/GpioWrapper.hxx"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we update arduino/libify.sh since it handles copying from common -> arduino? ref

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these files are already handled in arduino/libify.sh.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in libify they are copied to arduino from common.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's track this via an issue to unify the libify bits so we can avoid ifdef etc

@bakerstu bakerstu merged commit 36833d8 into master Nov 1, 2024
4 checks passed
@bakerstu bakerstu deleted the bakerstu-esp-idf-cmake branch November 1, 2024 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants