Hello!
I used to write C code with -ansi, -pedantic flags. Is it possible to build translation modules (mod.c, mod.h) with these flags with arduino-cli for esp32?
Hello!
I used to write C code with -ansi, -pedantic flags. Is it possible to build translation modules (mod.c, mod.h) with these flags with arduino-cli for esp32?
the ESP32 Arduino core relies on GCC with some extensions and expects C++11 / C++17 or later for most code.
I think the -ansi and -pedantic flags are strict C flags and thus would likely break Arduino/ESP32 code, especially anything using Arduino headers or C++ features.
➜ However you could probably compile individual .c translation modules in strict C mode separately with -ansi -pedantic and then link them into the Arduino build.
(Mixing strict C modules with the ESP32 Arduino C++ core might likely require extern "C" wrappers for headers and careful handling of types).
Hi @evily. Arduino CLI allows the user to set the values of platform properties via the --build-property flag of the arduino-cli compile command:
https://arduino.github.io/arduino-cli/latest/commands/arduino-cli_compile/#options
The esp32:esp32 boards platform follows the standard convention of allowing the user to inject arbitrary arguments into the compilation commands via a set of dedicated platform properties:
The compiler.c.extra_flags property is referenced in the esp32:esp32 platform's recipe.c.o.pattern property, which defines the template from which Arduino CLI generates the compilation command used for C language files:
This means you can add the -ansi and -pedantic flags to the commands used to compile all C files by adding the following flag to your arduino-cli compile command:
--build-property "compiler.c.extra_flags=-ansi -pedantic"
By default, the esp32:esp32 platform adds the -w flag to the compilation commands, which disables warnings, which would render your -pedantic flag useless. You can enable warnings via the --warnings flag of the arduino-cli compile comand. So you will want to also add something like --warnings all to your arduino-cli compile command:
arduino-cli compile --build-property "compiler.c.extra_flags=-ansi -pedantic" --warnings all ...
Alternatively, you can do more granular diagnostics configuration from your source code by using diagnostic pragmas:
You do need to use the -Wpedantic flag instead of its -pedantic synonym.
For example, if you want to enable the "pedantic" set of warnings for a translation unit, you would add the following line to the top of the .c file:
#pragma GCC diagnostic warning "-Wpedantic"
Or if you want to enforce warning-free code by promoting the warnings to errors:
#pragma GCC diagnostic error "-Wpedantic"
I discovered a problem with this. Unfortunately there is a bug in the esp32:esp32 platform;
The platform adds its own flags after the point where the flags the user specifies via the compiler.c.extra_flags are injected. This is a problem because, in cases where two flags conflict, the flag that comes later overrides the prior occurrences of the flag.
This doesn't affect the -pedantic flag (other than the easily worked around problem I mentioned in my previous reply of the -w flag counteracting it). However, it does completely nullify the injected -ansi flag, since the platform's flags include -std=gnu17, which overrides -ansi.
It is possible to work around this, by using the --build-property of arduino-cli compile to also redefine the platform's recipe.c.o.pattern property:
--build-property "recipe.c.o.pattern=\"{compiler.path}{compiler.c.cmd}\" {compiler.c.flags} {compiler.c.extra_flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD=\"{build.board}\" -DARDUINO_VARIANT=\"{build.variant}\" -DARDUINO_PARTITION_{build.partitions} {build.extra_flags} {compiler.cpreprocessor.flags} {includes} \"@{build.opt.path}\" \"@{file_opts.path}\" \"{source_file}\" -o \"{object_file}\""
Note that I swapped the order of the {compiler.c.flags} and {compiler.c.extra_flags} property references in my definition of the recipe.c.o.pattern property. This is the equivalent of fixing the bug in the platform's platform.txt configuration file:
--- a/platform.txt
+++ b/platform.txt
@@ -146,7 +146,7 @@ recipe.hooks.prebuild.8.pattern=/usr/bin/env bash -c "cp -f "{compiler.sdk.path}
recipe.hooks.prebuild.8.pattern.windows=cmd /c COPY /y "{compiler.sdk.path}\sdkconfig" "{build.path}\sdkconfig"
## Compile c files
-recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.extra_flags} {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" -DARDUINO_PARTITION_{build.partitions} {build.extra_flags} {compiler.cpreprocessor.flags} {includes} "@{build.opt.path}" "@{file_opts.path}" "{source_file}" -o "{object_file}"
+recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {compiler.c.extra_flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" -DARDUINO_PARTITION_{build.partitions} {build.extra_flags} {compiler.cpreprocessor.flags} {includes} "@{build.opt.path}" "@{file_opts.path}" "{source_file}" -o "{object_file}"
## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.extra_flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" -DARDUINO_PARTITION_{build.partitions} {build.extra_flags} {compiler.cpreprocessor.flags} {includes} "@{build.opt.path}" "@{file_opts.path}" "{source_file}" -o "{object_file}"
Oh, great! I glad to read it! And thank you for you work! I’ll try later to do it and will let you know.
Okay, I used this patch. Seems it works.
I’ve created the file hello/hello.ino:
void setup()
{}
void loop()
{}
Compiling without -ansi -pedantic:
arduino-cli compile -b esp32:esp32:esp32 hello.ino --warnings all --quiet --build-property build.partitions=min_spiffs
Everything OK.
Compiling with -ansi -pedantic:
arduino-cli compile -b esp32:esp32:esp32 hello.ino --warnings all --quiet --build-property build.partitions=min_spiffs --build-property "compiler.c.extra_flags=-ansi -pedantic"
But got an error and many warnings (I added only a little part of warnings):
/home/evi/.arduino15/packages/esp32/hardware/esp32/3.2.0/cores/esp32/ColorFormat.c:23:1: error: C++ style comments are not allowed in ISO C90
23 | // define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards
| ^
/home/evi/.arduino15/packages/esp32/hardware/esp32/3.2.0/cores/esp32/ColorFormat.c:23:1: note: (this will be reported only once per input file)
/home/evi/.arduino15/packages/esp32/hardware/esp32/3.2.0/cores/esp32/ColorFormat.c: In function 'espHsvToRgbColor':
/home/evi/.arduino15/packages/esp32/hardware/esp32/3.2.0/cores/esp32/ColorFormat.c:52:24: warning: initializer element is not computable at load time [-Wpedantic]
52 | espHsvColor_t hsv = {h, s, v};
| ^
/home/evi/.arduino15/packages/esp32/hardware/esp32/3.2.0/cores/esp32/ColorFormat.c:52:27: warning: initializer element is not computable at load time [-Wpedantic]
52 | espHsvColor_t hsv = {h, s, v};
|
Is it possible to this fix error somehow with saving -ansi -pedantic flags? Maybe somehow compile only my units with these flags.
For -pedantic, you can do that by using the alternative diagnostic pragma approach instead of the approach of injecting flags into the compilation commands:
However, I am not aware of a way to do the same with -ansi, since this is not a diagnostic flag. Maybe you will find -Wpedantic alone to be sufficient?
I've tried to compile without -pedantic:
arduino-cli compile -b esp32:esp32:esp32 hello.ino --warnings all --quiet --build-property build.partitions=min_spiffs --clean --build-property "compiler.c.extra_flags=-ansi"
No warnings, got the same error:
/home/evi/.arduino15/packages/esp32/hardware/esp32/3.2.0/cores/esp32/ColorFormat.c:23:1: error: C++ style comments are not allowed in ISO C90
23 | // define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards
| ^
I deleted all comment lines, but got more errors.
Were you expecting a different result? If so, please provide a detailed description of why you expected that. Understanding this will allow the forum helpers to effectively assist you.
I have an ugly solution to what I want. For example, I have 3 files: prog.ino, my_mod.c, my_mod.h.
-ansi flag.touch my_mod.*-ansi flag.So, I have compiled esp32 parts without standard problems. Then I can compile my units with my favorite standard.
Can I compile separate esp32 part without -ansi and mein part with -ansi and then ld then without touch hack?
Nice one! It should probably be considered a bug that Arduino CLI doesn't invalidate the compilation cache when the platform properties are changed via --build-property, but in this case it actually turned out to be useful!
I don't know how that can be accomplished. Maybe one of the other forum helpers will have an idea.
Are you sure you really need -ansi? I'm all for encouraging/enforcing best practices via -pedantic, but compiling for an ancient C standard via -ansi seems a bit excessive to me.
There are some reasons:
C99 is unacceptable because of VLA (I won't explain why, you can look why it's bad for yourself). So if write units for esp32 in ANSI C I can use it later.