Closed nsk126 closed 2 years ago
When I try to run a simple Eigen program below(found it on their website), I'm getting many errors.
What makes you think that this is a problem with pico-sdk
, rather than a problem with eigen
(whatever that is?)
I would be shocked if this was an Eigen issue--Eigen is an industry standard library for linear algebra. I would be more likely to think your build environment is somehow broken. What C++ standard are you using? Do you have libstdc++-arm-none-eabi-newlib
installed (assuming you are on Debian/Ubuntu)? Could you share your CMakeLists.txt?
My initial thought is that Eigen is made to work with C++98, but it uses newer features when possible. In particular, std::invoke_result
is a C++17 feature. If you try building with C++11, does it work?
Interestingly, Eigen's Meta.h does not contain any reference to std::invoke_result
on my machine (Eigen 3.3.9). What version of Eigen are you using? Looks like this feature was added after 3.3.9. The C++ STL being used in the pico-sdk likely does not fully support C++17.
Eigen 3.4.0 I think. from https://gitlab.com/libeigen/eigen
I cloned the repo into my project folder.
Try putting set(CMAKE_CXX_STANDARD 11)
in your CMakeLists.txt.
I think I found it and I'd say it's actually Eigen that is broken (I only tried latest master branch). If you use (ancient) arm gcc 6.3.1 with '-std=gnu++1z' Eigen incorrectly assumes the compiler and/or libstdc++ is fully c++17 capable, while gcc 6.3.1 is definitely not.
cmake will set -std=gnu++1z with set(CMAKE_CXX_STANDARD 17)
, so instead do set(CMAKE_CXX_STANDARD 14)
and the example will compile (Eigen now says c++11 is too old) ... or use a newer compiler, up to gcc 11.2 is available for download.
I doubt this is an Eigen issue. The compiler will set __cplusplus
to 201703L
if C++17 is enabled. However, the compiler or its STL may not have full support for C++17. Eigen has no way of knowing this, since the compiler has told it "I support C++17," and then you run into issues like this. For C++17 compiler support, see here: https://en.cppreference.com/w/cpp/compiler_support/17
As an example, if you tell GCC to use experimental C++23 features, the __cplusplus
macro will be set to a suitable value for C++23, despite the compiler not fully supporting the standard. Otherwise the STL's code wouldn't know which of the features it does support to enable.
(Eigen now says c++11 is too old)
According to the release notes for 3.4.0, 3.4.0 is the last one that still supports C++03, so I'd imagine 11 would work just fine. 11 is generally considered the minimum for "modern" C++ and is probably still the most widely used by a large margin.
Not quite, gcc 6 never tells Eigen it's c++17. With -std=gnu++1z gcc 6 sets __cplusplus
to 201500L
(gcc 7 and later use 201703L
). Next Eigen sets EIGEN_COMP_CXXVER
to 17 when __cplusplus > 201402L
. So whether it's standard or not I don't know, but Eigen can know it's not c++17 simply because 201500 < 201703
.
Concerning c++11, I simply cloned the gitlab repo as I assumed nsk126 did too. I think it has its version set to 3.4.90, so it's not the 3.4.0 release. When you then set(CMAKE_CXX_STANDARD 11)
you'll get: #error This compiler appears to be too old to be supported by Eigen
. c++14 is the minimum for this one.
I've had no success fixing this. Building from the source in my project didn't help.
So I tried installing eigen3 directly into root with sudo apt install libeigen3-dev
and it still pops out errors like
/usr/include/eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h:396:1: error: template with C linkage
template<typename MatrixType>
And a lot more like these.
My CMakeLists.txt :
# Set minimum required version of CMake
cmake_minimum_required(VERSION 3.12)
# Include build functions from Pico SDK
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
# Set name of project (as PROJECT_NAME) and C/C++ standards
project(PicoEKF C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
# Creates a pico-sdk subdirectory in our project for the libraries
pico_sdk_init()
# Tell CMake where to find the executable source file
add_executable(${PROJECT_NAME}
src/eigen_test.cpp
)
FILE(GLOB FreeRTOS_src FreeRTOS-Kernel/*.c)
add_library( FreeRTOS STATIC
${FreeRTOS_src}
FreeRTOS-Kernel/portable/GCC/ARM_CM0/port.c
FreeRTOS-Kernel/portable/MemMang/heap_4.c
)
# Create map/bin/hex/uf2 files
pico_add_extra_outputs(${PROJECT_NAME})
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
#add include directiories
target_include_directories( FreeRTOS PUBLIC
FreeRTOS-Kernel/include
include/
FreeRTOS-Kernel/portable/GCC/ARM_CM0
)
# Link to pico_stdlib (gpio, time, etc. functions)
target_link_libraries(${PROJECT_NAME}
pico_stdlib
hardware_i2c
pico_multicore
hardware_dma
FreeRTOS
Eigen3::Eigen
)
# Enable usb output, disable uart output
pico_enable_stdio_usb(${PROJECT_NAME} 1)
pico_enable_stdio_uart(${PROJECT_NAME} 0)
Edit:
I also put set(CMAKE_CXX_STANDARD 11)
into my CMakeLists.txt
. But found no success.
Not following closely, but did you try with a newer compiler? GCC 6 is very old.
Side note: https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/main/portable/ThirdParty/GCC/RP2040 is the port of FreeRTOS you should be using for RP2040.
I had no problem doing basically what your original approach was. I dropped Eigen 3.4.0's source into the eigen-3.4.0
directory in the project, then did target_include_directories(..... PRIVATE eigen-3.4.0/)
and all went swimmingly. I am using C++11, which should be supported even on GCC 6.
Not following closely, but did you try with a newer compiler? GCC 6 is very old.
@kilograham I don't think OP has ever mentioned using GCC 6. I believe that was another person. GCC 6 is certainly not going to help anyone out here, but they should still be able to build this project just fine.
Thanks for the suggestion. @willeccles
I had no problem doing basically what your original approach was. I dropped Eigen 3.4.0's source into the
eigen-3.4.0
directory in the project, then didtarget_include_directories(..... PRIVATE eigen-3.4.0/)
and all went swimmingly. I am using C++11, which should be supported even on GCC 6.
target_include_directories(${PROJECT_NAME} PRIVATE
eigen-3.4.0/
)
I suppose the core of the problem was CXX 17
. After I re-downloaded eigen-3.4.0
from tuxfamilys' website and changed my CMakeLists.txt
file to set(CMAKE_CXX_STANDARD 11)
I don't see any errors during make.
I have to test this with my Pico. Will do in a bit.
Edit: Does this mean Eigen was never meant to be used with C++ 17? What happen?
Does this mean Eigen was never meant to be used with C++ 17? What happen?
This actually means your C++ STL or compiler is too old to fully support C++17. Eigen will use C++17 features only if the compiler reports that they are available. If the compiler partially supported C++17, it may have reported that it was available, but Eigen ran into issues when some of it was not supported by the compiler. With a sufficiently modern compiler + STL, C++17 will work just fine with Eigen--in your case, however, C++17 support appears to be incomplete in your compiler/STL.
Eigen 3.4.0 does use C++17 features, but since you're compiling with C++11 it will harmlessly avoid compiling that code.
(I think we can close this issue, as it's been proven that this is not only doable, but unrelated to both Eigen and the Pico SDK)
Does this mean Eigen was never meant to be used with C++ 17? What happen?
This actually means your C++ STL or compiler is too old to fully support C++17. Eigen will use C++17 features only if the compiler reports that they are available. If the compiler partially supported C++17, it may have reported that it was available, but Eigen ran into issues when some of it was not supported by the compiler. With a sufficiently modern compiler + STL, C++17 will work just fine with Eigen--in your case, however, C++17 support appears to be incomplete in your compiler/STL.
Eigen 3.4.0 does use C++17 features, but since you're compiling with C++11 it will harmlessly avoid compiling that code.
Could this be because of my OS or my g++ running on version g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
?
What is the output of arm-none-eabi-g++ --version
? This is the compiler used for the Pico.
arm-none-eabi-g++ (15:6.3.1+svn253039-1build1) 6.3.1 20170620
Wow, you really are using GCC 6. That explains that for sure. GCC 6 won't properly support C++17, and Eigen is slightly busted on GCC 6 as someone pointed out above. However, it does support C++11, so using that ought to make everything go smoothly.
Thanks for the help! I'll close this issue.
I put Eigen into the same directory as my project and added the below line into
CMakeLists.txt
.When I try to run a simple Eigen program below(found it on their website), I'm getting many errors.
Output:
Edit: Added the Eigen program I used for better understanding.