Using cxx crate with xtensa-esp32 target

Hello,

I've been trying to compile a rust project for the xtensa-esp32s3-espidf target. I set up the project as documented here: Understanding esp-idf-template - The Rust on ESP Book

As part of this project, I'm also trying to compile a library written in c++, so I included the cxx crate.

However, simply including cxx as a dependency broke the build of my project, which was otherwise working fine.

The error is:

$ cargo build
   Compiling esp-idf-sys v0.36.1
   Compiling link-cplusplus v1.0.10
warning: link-cplusplus@1.0.10: error: unknown target triple 'xtensa-unknown-none-elf'
error: failed to run custom build command for `link-cplusplus v1.0.10`

Caused by:
  process didn't exit successfully: `/Users/mattsains/dev/esp-idf-test/target/debug/build/link-cplusplus-2037f0428263751b/build-script-build` (exit status: 1)
  --- stdout
  cargo:rerun-if-changed=build.rs
  OUT_DIR = Some(/Users/mattsains/dev/esp-idf-test/target/xtensa-esp32s3-espidf/debug/build/link-cplusplus-1cda7d002a87c738/out)
  OPT_LEVEL = Some(s)
  TARGET = Some(xtensa-esp32s3-espidf)
  HOST = Some(aarch64-apple-darwin)
  cargo:rerun-if-env-changed=CXX_xtensa-esp32s3-espidf
  CXX_xtensa-esp32s3-espidf = None
  cargo:rerun-if-env-changed=CXX_xtensa_esp32s3_espidf
  CXX_xtensa_esp32s3_espidf = None
  cargo:rerun-if-env-changed=TARGET_CXX
  TARGET_CXX = None
  cargo:rerun-if-env-changed=CXX
  CXX = None
  cargo:rerun-if-env-changed=CROSS_COMPILE
  CROSS_COMPILE = None
  RUSTC_LINKER = Some(ldproxy)
  cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT
  RUSTC_WRAPPER = None
  cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some(true)
  cargo:rerun-if-env-changed=CXXFLAGS
  CXXFLAGS = None
  cargo:rerun-if-env-changed=TARGET_CXXFLAGS
  TARGET_CXXFLAGS = None
  cargo:rerun-if-env-changed=CXXFLAGS_xtensa_esp32s3_espidf
  CXXFLAGS_xtensa_esp32s3_espidf = None
  cargo:rerun-if-env-changed=CXXFLAGS_xtensa-esp32s3-espidf
  CXXFLAGS_xtensa-esp32s3-espidf = None
  CARGO_ENCODED_RUSTFLAGS = Some(--cfgespidf_time64)
  cargo:warning=error: unknown target triple 'xtensa-unknown-none-elf'

  --- stderr


  error occurred in cc-rs: command did not execute successfully (status code exit status: 1): LC_ALL="C" "c++" "-Os" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "--target=xtensa-none-elf" "-Wall" "-Wextra" "-o" "/Users/mattsains/dev/esp-idf-test/target/xtensa-esp32s3-espidf/debug/build/link-cplusplus-1cda7d002a87c738/out/a44812d996fcf38b-dummy.o" "-c" "/Users/mattsains/dev/esp-idf-test/target/xtensa-esp32s3-espidf/debug/build/link-cplusplus-1cda7d002a87c738/out/dummy.cc"

I thought it a bit suspicious that it says the unknown target triple is xtensa-unknown-none-elf because I was expecting something like xtensa-esp32s3-espidf-elf but I can't figure out whether I need to set this somewhere and how to set it.

I'm not familiar with esp32 toolchain, but I think this error indicates there's no C++ compiler detected.

if your C++ toolchain is setup properly, set the CXX environment variable to the path of the C++ compiler then try again.

1 Like

@nerditation thanks! That helped. I set:

export CXX=/Users/mattsains/dev/esp-idf-test/.embuild/espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin/xtensa-esp-elf-c++

and then deleted the target directory and retried the build, and it worked!

It's quite annoying that I had to do that because the .embuild directory is coming from a build dependency that is supposed to be setting that up: embuild - Rust

I guess more work needs to be done to make cxx and embuild play well together

Now I'm getting wild linker errors like:

/Users/mattsains/dev/esp-idf-test/.embuild/espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/13.2.0/../../../../xtensa-esp-elf/bin/ld: 
  /Users/mattsains/dev/esp-idf-test/target/xtensa-esp32s3-espidf/debug/deps/libcxx-522b47e1d14595bc.rlib(c16f17691ff6f04b-cxx.o): 
    compiled for a big endian system and target is little endian

I did notice that there were some warnings for multiple definitions, for example for __cxa_guard_acquire:

/Users/mattsains/dev/esp-idf-test/.embuild/espressif/esp-idf/v5.3.2/components/cxx/cxx_guards.cpp:114: 
/Users/mattsains/dev/esp-idf-test/.embuild/espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/xtensa-esp-elf/lib/esp32s3/no-rtti/libstdc++.a(guard.o)

A bit lost again

libcxx-522b47e1d14595bc.rlib

is it expected that an esp library has rlib as an extension? Kind of seems like it's accidentally trying to link against a library compiled for mac?

something is very strange here: where does the big endian object come from? to my knowledge, the xtensa processor is little endian, right?

is your host system big endian? if so, then maybe the cross compiler is not setup correctly I guess. but shouldn't it complain link different architecture instead? so confused.

.rlib is the standard suffix for (static) rust library crates, i.e. it is the compilation output for crate-type = "rlib" (and the default for crate-type = "lib"). see:

both of the sources appear to be in the .embuild/espressif directory. My machine is actually little-endian since it's an M2 macbook. So is the esp32s3