Allow using esp-idf-svc with the CMake build
maelp opened this issue · 31 comments
Hi,
Thanks for this really nice repository! We're a French company using ESP32 for our products, and we are really looking forward to being able to use embedded Rust.
We saw both rust-esp32-example
(this repo, CMake-based build) and https://github.com/ivmarkov/rust-esp32-std-hello (a nice "cargo-first" build from @ivmarkov which also allows to use the nice https://github.com/esp-rs/esp-idf-svc which gives access to nice Rust wrappers for most of ESP-IDF libraries).
For now, because our codebase is C/C++, we'd be happy to use this CMake-based build rather than the "cargo-first" build (as we want to incrementally modify modules of our code by replacing them with Rust code), but it seems we can't use esp-idf-svc
with it out-of-the-box.
Would it be possible to update this code, or add an example of how to do a CMake-based build that also allows to use esp-idf-svc
?
@maelp With the changes to the esp-idf-sys
crate now upstreamed, and with the 4 environment variables defined in this demo-crate, you should in fact be able to use esp-idf-sys
and esp-idf-svc
in CMake-based builds.
To get you a head-start, I've (temporarily) forked this repo here and I've basically enhanced it with all of the demo code that is available in the rust-esp32-std-hello crate.
So just
- Pull my fork above
- Change ssid & pass here
idf.py set-target esp32
idf.py build
Flash as per the build instructions and you should be good to go.
Oh: you need the esp
Rust build of course, as well as the Xtensa clang fork, as usual.
Let me know if you face issues.
Thanks @ivmarkov that's awesome, I'm going to try it right now and let you know if it works as expected!
For now I have a linking error with
= note: ld: library not found for -liconv
collect2: error: ld returned 1 exit status
(although I installed libiconv)
Perhaps I have to add something to the CMake file or add a LD_LIBRARY_PATH ?
Can you provide some extra context:
- Does the build work for you for the plain (un-forked) rust-esp32-example?
- Are you using ESP-IDF master, or V4.3? Honestly, I only tried with master (sorry!)
- Can you provide some extra logs exactly when during the build this happens? When linking the app elf image, or during the bootloader linking?... Or much earlier? Installing "libiconv" would likely NOT help, because I can't imagine how an OS library compiled for X86_64 can be linked into the ESP-IDF Xtensa code...
Hey @ivmarkov, the original rust example used to compile on my machine, but it seems that the most recent commit fails with the same error, I'll try to build a few commits or git bisect to try to find which commit introduced the error,
as a reference, I had built the example successfully on commit ad2066c
@ivmarkov I reinstalled the latest master
branch of esp-idf
locally, and ran again the compilation on the commit that worked before, and still have the same error (although I know for sure that a while ago I managed to build it).
Any idea how I could debug why it requires this library?
I'm not sure whether libiconv is really needed for the compilation though, when I grep the esp-idf
repo for iconv, I find it in one example
examples/peripherals/secure_element/atecc608_ecdsa/components/esp-cryptoauthlib/cryptoauthlib/third_party/hidapi/libusb/hid.c
49:#include <iconv.h>
and then mostly in the Doxyfile for documentation
examples/build_system/cmake/import_lib/main/lib/tinyxml2/dox
22:# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
23:# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
793:# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
794:# documentation (see: http://www.gnu.org/software/libiconv) for the list of
This is the build command that fails
"cc" \
"-m64" \
"-arch" "x86_64" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.0.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.1.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.10.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.11.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.12.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.13.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.14.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.15.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.2.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.3.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.4.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.5.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.6.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.7.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.8.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.build_script_build.ca656uf2-cgu.9.rcgu.o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b.1za4lfu810eqk51f.rcgu.o" \
"-L" "[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/deps" \
"-L" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libstd-5391a9c2677cf581.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-3bbc2df779345b87.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libobject-ba2085ff30a375ca.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libaddr2line-60eb3f1dc0a88ccf.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libgimli-3c8cee53c8082ecf.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libstd_detect-4659320ab27ece1f.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/librustc_demangle-38c209974c1e0383.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libhashbrown-732c4590e3658e3f.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_alloc-fd3e472dbd6e7b52.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libunwind-50f6ed39e54308d3.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libcfg_if-7203489bd3ec4028.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/liblibc-3d6f48823f80dcaa.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/liballoc-fd99f8a81c04f070.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_core-41d8a5c3c9ceb90b.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libcore-f043409408606858.rlib" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-ed99a4cb6d3f51aa.rlib" "-lSystem" "-lresolv" "-lc" "-lm" "-liconv" \
"-L" "/Users/primet/.rustup/toolchains/esp/lib/rustlib/x86_64-apple-darwin/lib" "-o" \
"[redacted_path]/rust-esp32-example-espressif/build/esp-idf/rustlib/target/release/build/proc-macro2-3ec969f85280340b/build_script_build-3ec969f85280340b" "-Wl,-dead_strip" "-nodefaultlibs"
= note: ld: library not found for -liconv
collect2: error: ld returned 1 exit status
As a reference, this is how I install the toolchain
rustup toolchain install nightly
VERSION="1.54.0-dev"
ARCH="x86_64-apple-darwin"
RUST_DIST="rust-${VERSION}-${ARCH}"
RUST_SRC_DIST="rust-src-${VERSION}"
TOOLCHAIN_DESTINATION_DIR="~/.rustup/toolchains/esp"
mkdir -p ${TOOLCHAIN_DESTINATION_DIR}
curl -O "https://dl.espressif.com/dl/idf-rust/dist/${ARCH}/${RUST_DIST}.tar.xz"
tar xvf ${RUST_DIST}.tar.xz
./${RUST_DIST}/install.sh --destdir=${TOOLCHAIN_DESTINATION_DIR} --prefix="" --without=rust-docs
curl -O "https://dl.espressif.com/dl/idf-rust/dist/noarch/${RUST_SRC_DIST}.tar.xz"
tar xvf ${RUST_SRC_DIST}.tar.xz
./${RUST_SRC_DIST}/install.sh --destdir=${TOOLCHAIN_DESTINATION_DIR} --prefix="" --without=rust-docs
rustup default esp
curl -O "https://dl.espressif.com/dl/idf-rust/dist/${ARCH}/xtensa-esp32-elf-llvm11_0_0-x86_64-apple-darwin.tar.xz"
tar xf xtensa-esp32-elf-llvm11_0_0-x86_64-apple-darwin.tar.xz
export PATH="`pwd`/xtensa-esp32-elf-clang/bin/:$PATH"
cd rust-esp32-example && get_idf && idf.py set-target esp32 && idf.py clean
The error seems to happen at that step:
[781/1015] Performing build step for 'rustlib_project'
FAILED: esp-idf/rustlib/stamp/rustlib_project-build esp-idf/rustlib/target/RustApi.h esp-idf/rustlib/target/xtensa-esp32-espidf/release/librustlib.a /Users/primet/work/gouach/embedded-nobackup/rust-esp32-example-espressif/build/esp-idf/rustlib/stamp/rustlib_project-build /Users/primet/work/gouach/embedded-nobackup/rust-esp32-example-espressif/build/esp-idf/rustlib/target/RustApi.h /Users/primet/work/gouach/embedded-nobackup/rust-esp32-example-espressif/build/esp-idf/rustlib/target/xtensa-esp32-espidf/release/librustlib.a
OK got it.
So where it is failing, is at a compilation stage which is NOT really building the esp-idf-*
crates themselves, but is building a Rust script that will itself do a customized build of the esp-idf-*
crates.
Background: since cargo
is a declarative build tool, the way how you do very-special-customized build tasks is by providing - next to the Cargo.toml
file - a build.rs
file which Cargo is compiling and executing on your machine as part of the build itself.
So what I am trying to say is that installing libiconv
- as a x86_64 library - on your own operating system - using the OS means to do this installation (be it apt-get
or brew
) is the way forward.
Now why it did not work for you even though you said you installed libiconv
is the issue to be solved. I guess you tried something like this already? Perhaps you need to reboot your Mac or something?
Ha interesting, indeed if I do a docker run -it espressif/idf-rust-examples
and build your code in it it works, so it might be something with libiconv
I tried with brew and with nix, and in both cases the libiconv is not detected, I tried adding the path to LD_LIBRARY_PATH before building, or to CFLAGS and LDFLAGS, but it does not seem to work
This stackoverflow thread might be relevant. Unfortunately no solution there. Do you happen to run an M1 Mac as well???
I'm on a regular intel mac :) are there some cargo flags that I can use to tell the build about other library paths?
If I copy paste the line of the code which does not compile, and simply remove the -liconv
it compiles correctly, so perhaps that's something I should change somewhere in the script that tries to build build.rs
?
And if I install libiconv
with brew and add
LDFLAGS="-L/usr/local/opt/libiconv/lib" CCFLAGS="-I/usr/local/opt/libiconv/include"
in front of the cc
command it still does not find the lib, although
ls /usr/local/opt/libiconv/lib
libcharset.1.dylib libcharset.dylib libiconv.a
libcharset.a libiconv.2.dylib libiconv.dylib
But if I include the flags "-L/usr/local/opt/libiconv/lib -I/usr/local/opt/libiconv/include" directly in front of the "-liconv" on the build command, it compiles, so I guess the issue is that for some reason the build does not take into account the LDFLAGS and CCFLAGS
For now perhaps I will use the Docker build, do you know if there's an easy way to do a build in docker and retrieve the built binary, so that I can flash it from my laptop on the ESP (since it's complicated to bind the USB ports to Docker containers on a mac)?
The fact that CCFLAGS
is not considered is fine. This is Rust after all, not C, so these includes cannot be used by Rust anyway. (And I think CC is used only as a linker, and most likely only on Mac)
Now, instead of LDFLAGS
, it seems you need RUSTFLAGS
. Check here.
If I copy paste the line of the code which does not compile, and simply remove the
-liconv
it compiles correctly, so perhaps that's something I should change somewhere in the script that tries to buildbuild.rs
?
There is no "script" that tries to build the build.rs
script. This is just cargo
, building build.rs
using the [build-dependencies]
section in Cargo.toml.
Now, the fact, that removing -liconv
does not result in a linkage error problably means that the -liconv
flag is not coming from dependencies of build.rs
(in [build-dependencies]
), but somehow from the combination of the Rust compiler itself + your OS env.
Hence why I pointed you at the stackoverflow thread above where they try to compile a supersimple "Hello, world" app on Mac, and it still does not work.
So, can you actually build even a simple "Hello world" Rust app with the esp
rust toolchain? And ditto for the nightly/stable toolchains?
- Like, cloning this one
- Then
rustup default esp
- Then,
cargo build
? - Then repeat the same but with
rustup default nightly
and thenrustup default stable
?
For now perhaps I will use the Docker build, do you know if there's an easy way to do a build in docker and retrieve the built binary, so that I can flash it from my laptop on the ESP (since it's complicated to bind the USB ports to Docker containers on a mac)?
Not really, @georgik might be able to help.
Compiling the hello-world:
with esp
: fails with the iconv
error
with nightly
: fails with the iconv
error
with stable
: fails with the iconv
error
The error seems to be a Nix thing, I can make the hello-world example compile using nix-shell -p cargo rustc libiconv
I guess the easiest for now is to build using a Docker container :)
OK since the error is really somehow with your Rust installation (basic hello-world fails to build too), please report if after flashing the thing works, and if it does, I think we can close this one. :)
P.S. RUSTFLAGS
should work, but you might have to wrap the -L
argument in something. Maybe -c
; not sure.
Well, when building the code in the docker container it seems to work but it stalls when doing this
[1/15] Performing build step for 'bootloader'
[1/1] cd /opt/rust/rust-esp32-example/build/bootloader/esp-idf/esptool_py && /opt/esp/python_env/idf4.4_py3.8_env/bin/python /opt/esp/idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x1000 /opt/rust/rust-esp32-example/build/bootloader/bootloader.bin
Bootloader binary size 0x6350 bytes. 0xcb0 bytes (11%) free.
[1000/1012] Linking C static library esp-idf/clib/libclib.a
and then nothing is displayed and it seems to hang, does it do the same for you?
It does not stall. It just takes a lot of time (not sure why).
Weird, it seems to be perhaps 1h that I left it like that, do you know how long it takes on your laptop?
The build completed (after perhaps one hour or so), and I could successfully flash and run it :) although I will need to have a way to build faster for this to be useable haha
On my laptop it takes a couple of minutes at most. If not less than a minute.
I suggest you open a separate issue, so that Espressif & myself can look into what is causing the slowness later.
In the meantime, ideally you should somehow fix your native Rust environment, because there the build time would be much more tolerable, as per above.
Perfect :)