Separate settings for C and C++ versions

Hi, I’m writing application based on ESP-IDF using mixed codebase of C and C++.
I would like to use C+14 and C11 but i can’t see where i should define this. If I add --std=c++14 and type pio init it compiles with C++14 but i receive some warnings when C files are compiled i.e:

cc1: warning: command line option ‘-std=c++14’ is valid for C++/ObjC++ but not for C

Can someone help?

PlatformIO is an extension of SCons. As documented, CXXFLAGS affect only C++ compiler options and CFLAGS affect only C ones, while CCFLAGS affect both. Can also be seen e.g. here. These variables in env can be changed with advanced scripting. However, ESP-IDF is a bit special since PlatformIO calls into CMake to get the default compiler options, stored e.g. here, where gnu99 for C and gnu++11 for C++ is set. But with build_flags that can also be gotten rid of in a post-process fashion.

So, if you take the blinky example and change the platformio.ini to

[env:esp32dev]
platform = espressif32
framework = espidf
board = esp32dev
monitor_speed = 115200
build_flags =
        ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led
        -D CONFIG_BLINK_GPIO=2
extra_scripts = pre:change_c_cpp_version.py
build_unflags = -std=gnu99 -std=gnu++11

with the change_c_cpp_version.py file in the root of the project being

Import("env")

c = env["CFLAGS"]
c = [x for x in c if not "-std" in x]
c += ["-std=gnu11"]
env.Replace(CFLAGS=c)

cxx = env["CXXFLAGS"]
cxx = [x for x in cxx if not "-std" in x]
cxx += ["-std=c++14"]
env.Replace(CXXFLAGS=cxx)

and also additionally rename blink.c to blink.cpp, adapting src/CMakeLists.txt for the new filename and changing the macro BLINK_GPIO to #define BLINK_GPIO (gpio_num_t)CONFIG_BLINK_GPIO, that changes the compiler invocation for me. (Check with project-task “Advanced → Verbose Build” or pio run -v

xtensa-esp32-elf-g++ -o .pio/build/esp32dev/src/blink.o -c -std=c++14  [..] src/blink.cpp
xtensa-esp32-elf-gcc -o .pio\build\esp32dev\app_trace\app_trace_util.o -c -std=gnu11 [..] app_trace_util.c

Note that if you use c11 instead of gnu11 (aka C11 with GNU extensions), then ESP-IDF becomes uncompilable with errors in asm volatile statements.

C:\Users\Max\.platformio\packages\framework-espidf@3.40200.210118\components\xtensa\include/xt_instr_macros.h:17:30: error: 'asm' undeclared (first use in this function)
 #define RSR(reg, at)         asm volatile ("rsr %0, %1" : "=r" (at) : "i" (reg))
                              ^~~

So you have to use gnu11 there. The C++ version goes up to C++17, btw.

It may be possible to change the C/C++ version directly in the CMakeLists.txt file, so that if the project is compiled with native ESP-IDF tools instead of PlatformIO, it also takes effect.

However, I tried following Request for C++17 support (IDFGH-844) · Issue #2449 · espressif/esp-idf · GitHub and it did not work – using a src/CMakeLists.txt of

idf_component_register(SRCS "blink.cpp"
                    INCLUDE_DIRS ".")

component_compile_options(-std=c++14)

just results in the blink.cpp file being compiled with both options present…

xtensa-esp32-elf-g++ -o .pio/build/esp32dev/src/blink.o -c -std=gnu++11 -std=c++14 -mlongcalls - [..] src/blink.cpp

it does also not have the possibility to change the C and C++ options independently.

You may have luck with idf_component_set_property and these two properties, but I don’t see how one would to a replace instead of append… You can try to ask in the ESP32 forum for further help on that or play with it yourself.

I’ve tried with

set(old_options "")
idf_component_get_property(old_options src C_COMPILE_OPTIONS)
message("c compile options: ${old_options}")   

but even that printed just an empty message.

Thank you! This additional script is working like a charm. I only had to change versions in c_cpp_proprties.json manually to fix some issues with syntax highlighting.