clang-tidy reporting many error: unknown argument - c

I am running an embedded C project based on a tricore-gcc compiler.
I made a compile_commands.json file that works well.
However, there are some arguments that clang-tidy cannot recognize.
For example I get the following
error: unknown argument: '-fstrict-volatile-bitfields' [clang-diagnostic-error]
when I run clang-tidy.
This is not a surprise of course, since -fstrict-volatile-bitfields is an option for gcc but not for clang-tidy.
However, I would like to suppress output messages due to unknown compiler options.
I tried to append --extra-arg=-Wno-unknown-warning-option as suggested here but the problem persists.

I had the same problem when using clang-tidy for a project compiled with GCC. The two compilers have different set of recognized flags. My compile_commands.json, which was generated by intercept-build, contained a number of options used by GCC that clang-tidy did not understand.
I solved this by a somewhat hackish solution of redacting the compile database before initiating the static analysis pass.
My script contains a number of Sed lines similar to this:
sed -i -E 's#-fconserve-stack##g' compile_commands.json
sed -i -E 's#-maccumulate-outgoing-args##g' compile_commands.json
sed -i -E 's#-mindirect-branch-register##g' compile_commands.json
sed -i -E 's#-mindirect-branch=thunk-extern##g' compile_commands.json
sed -i -E 's#-mpreferred-stack-boundary=3##g' compile_commands.json
sed -i -E 's#-mfunction-return=thunk-extern##g' compile_commands.json
This way, the unsupported flags are made invisible to clang-tidy, which allows to work without errors.

Related

How to include header files with E-ACSL wrapper script?

I am new to Frama-C and wanted to ask how I could add header files when using the E-ACSL wrapper script. Normally, I've been adding header files the following way with WP and RTE:
frama-c -rte main.c -cpp-extra-args="-I src/include -I ..."
However, I am unsure of how I can include these files when using the wrapper script.
e-acsl-gcc.sh --rte=all -c main.c
Without the header files I run into the following error:
[kernel] Parsing main.c (with preprocessing)/main.c:10:10: fatal error: header.h: No such file or directory #include "header.h"
I am using Frama-C 24.0 (Chromium). Any help would be appreciated. Thanks.
If you run e-acsl-gcc.sh -h, you'll get a help message with the script's options:
Options:
-h show this help page
-c compile instrumented code
(...)
-E pass additional arguments to the Frama-C preprocessor
-F pass additional options to the Frama-C command line
(...)
The two above are relevant for you: -E adds arguments to an implicit -cpp-extra-args used by the script, while -F allows you to add the option itself.
So, you can either run:
e-acsl-gcc.sh -E "-Isrc/include -I..." <other options and source files>
Or:
e-acsl-gcc.sh -F -cpp-extra-args="-Isrc/include,-I..." <other options and source files>
Note that with -F, due to quoting issues (between e-acsl-gcc.sh, Frama-C's command-line, C preprocessor, etc), you may need to replace spaces with commas, as in "-Isrc/include,-I...".
Important: do not add spaces between -I and the directory name. Due to parsing issues, e-acsl-gcc.sh will not parse it correctly if you do. GCC accepts both syntaxes anyway, so I'd recommend getting used to not adding spaces after -I (and -D as well) in general.
Overall, using -E is better here, but -F can be used to pass other options besides -cpp-extra-args.

Error trying to compile C file: mkfifo: cannot create fifo 'stderr': Operation not supported

We are trying to compile this by following instructions in the readme. I must say that we are not specialists with C at all, we are students of a web development bootcamp and trying to do our last project.
It's a command line tool to calculate ephemerides of multiple celestial bodies, and as you can read in the setup in the readme file, it need to download certain data from the internet, and then compile.
All is done through the setup.sh script.
So, we have tried:
In Windows 10 ubuntu WSL terminal
If we type $./setup or $./prettymake, after download the data, gives the error:
$mkfifo: cannot create fifo 'stderr': Operation not supported
$mkdir -p obj obj/argparse obj/coreUtils obj/ephemCalc obj/listTools obj/mathsTools obj/settings
cc -Wall -Wno-format-truncation -Wno-unknown-pragmas -g -c -I /mnt/d/reboot/ephemeris-compute-de430/src -O3 -D DEBUG=0 -D MEMDEBUG1=0 -D MEMDEBUG2=0 -fopenmp -D DCFVERSION=\"2.0\" -D DATE=\"09/06/2019\" -D PATHLINK=\"/\" -D SRCDIR=\"/mnt/d/reboot/ephemeris-compute-de430/src/\" src/ephemCalc/constellations.c -o obj/ephemCalc/constellations.o
If we do it with $sudo ./setup, the error printed is:
$mkfifo: cannot create fifo 'stderr': Operation not supported
$cat: stderr: No such file or directory
$mkdir -p obj obj/argparse obj/coreUtils obj/ephemCalc obj/listTools obj/mathsTools obj/settings
cc -Wall -Wno-format-truncation -Wno-unknown-pragmas -g -c -I /mnt/d/reboot/ephemeris-compute-de430/src -O3 -D DEBUG=0 -D MEMDEBUG1=0 -D MEMDEBUG2=0 -fopenmp -D DCFVERSION=\"2.0\" -D DATE=\"09/06/2019\" -D PATHLINK=\"/\" -D SRCDIR=\"/mnt/d/reboot/ephemeris-compute-de430/src/\" src/ephemCalc/constellations.c -o obj/ephemCalc/constellations.o
In macOS terminal
If we type $./prettymake, gives the error:
$mkdir -p obj obj/argparse obj/coreUtils obj/ephemCalc obj/listTools obj/mathsTools obj/settings
cc -Wall -Wno-format-truncation -Wno-unknown-pragmas -g -c -I /Users/rominaelorrietalopez/Documents/Descargas2/ephemeris-compute-de430-master/src -O3 -D DEBUG=0 -D MEMDEBUG1=0 -D MEMDEBUG2=0 -fopenmp -D DCFVERSION=\"2.0\" -D DATE=\"09/06/2019\" -D PATHLINK=\"/\" -D SRCDIR=\"/Users/rominaelorrietalopez/Documents/Descargas2/ephemeris-compute-de430-master/src/\" src/argparse/argparse.c -o obj/argparse/argparse.o
$clang: error: unsupported option '-fopenmp'
$make: *** [obj/argparse/argparse.o] Error 1
We have tried certain things to no avail, like granting permissions and what not, but have no idea what to do next.
It seems that it have something to do with the prettymake file:
mkfifo stderr
cat stderr | sed 's/\(.*\)/\1/' &
make $# 2>stderr | sed 's/\(.*\)/\1/'
rm stderr
It's like its trying to create a pipe to save the errors of the compilation but somehow it fails.
Also possibly worth of mention, it have a Makefile associated.
Since the github project does not have Issues, we've contacted the creator via email, but well, we thought maybe someone could help us here too.
Any kind of help would be honestly appreciated, thanks.
A comment from the OP invites me to answer; here it is.
The prettymake script creates a named fifo in order to receive the messages produced by make on its standard error.
A background process (cat) consumes the data from this fifo and sends them to a sed command (see right after) in order to transform these data before writing to standard output.
(note that cat is useless here since sed could have directly read from the named fifo thanks to <)
However, the two sed commands as shown in the question don't do anything since they just capture each line of text (\(.*\)) and repeat them unchanged (\1), thus they could have been omitted.
In this case, the script could just contain make $# 2>&1, it would have produced the same effect.
On a system where creating the named fifo is problematic (old version of WSL apparently), this change in the script should produce the same effect as expected.
Looking at the link provided in the question, we can see that the original prettymake script actually contains transformations in the sed commands in order to display standard output and standard error of the make command with different colours.

Getting the compiler default include path into a makefile

I am can run a shell command to grab the default include path from the compiler (and append the -I):
arm-none-eabi-gcc -xc -E -Wp,-v /dev/null 2>&1 | sed -En '/#include <...> search starts here:/,/End of search list./{//!p;};' | sed 's/^ /-I/'
I am trying to add that inside a Makefile:
PROJECT_INC = $(shell arm-none-eabi-gcc -xc -E -Wp,-v /dev/null 2>&1 | sed -En "/#include <...> search starts here:/,/End of search list./{//!p;}" | sed "s/^ /-I/")
Then I get an error:
Makefile:104: *** unterminated call to function `shell': missing `)'. Stop.
I tried to use backticks instead, that does not help. Tried using single-quotes or double-quotes for the sed commands. Most of the similar problems I can find on SO are related to expansion when there is a $ in the command, but it should not be a problem here.
If I cut down the command:
PROJECT_INC = $(shell arm-none-eabi-gcc -xc -E -Wp,-v /dev/null 2>&1 )
Then it seems to be cutting down the output.
The shell would return
ignoring duplicate directory "/Users/mjeanson/miniconda3/envs/project/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/8.3.1/include"
ignoring nonexistent directory "/Users/mjeanson/miniconda3/envs/project/bin/../arm-none-eabi/usr/local/include"
ignoring duplicate directory "/Users/mjeanson/miniconda3/envs/project/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/8.3.1/include-fixed"
ignoring duplicate directory "/Users/mjeanson/miniconda3/envs/project/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/include"
ignoring nonexistent directory "/Users/mjeanson/miniconda3/envs/project/bin/../arm-none-eabi/usr/include"
#include "..." search starts here:
#include <...> search starts here:
/Users/mjeanson/miniconda3/envs/project/bin/../lib/gcc/arm-none-eabi/8.3.1/include
/Users/mjeanson/miniconda3/envs/project/bin/../lib/gcc/arm-none-eabi/8.3.1/include-fixed
/Users/mjeanson/miniconda3/envs/project/bin/../lib/gcc/arm-none-eabi/8.3.1/../../../../arm-none-eabi/include
End of search list.
# 1 "/dev/null"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/dev/null"
Running this inside the Makefile, it would discard from the first line starting with #include, but otherwise it works. Not sure if that's going to be still be a problem after the piping to the sed command works fine(?)
If that's relevant (and not already obvious in the code snippets above), my environment is using a cross compiler (arm-none-eabi-gcc) and in a conda environment and all running on a Mac.
I don't think it should matter, but the reason why I need to do this is so that I can use some static analysis tool. When compiling the code itself, I do not need to add the default include path.
Bonus: I tried combining the sed commands in one but could not figure out how to do that...
Found the problem... the '#' character in the sed command was causing the issue and cause make to consider everything after as a comment.
For posterity, the fixed command is much easier since the include path start with a ' ':
arm-none-eabi-gcc -xc -E -Wp,-v /dev/null 2>&1 | sed -En '/^ /s/^ /-I/p'
The syntax for the macro expansion in GNU Make is very specific (of make, not to the shell), and normally doesn't take into consideration shell metacharacters like ".
You have included several of these, that mean different things to make (e.g. the :, etc) than they do to the shell.
You'd better to write the complete pipeline into a shell script and then just use the shell script name in the Makefile.
Don't build pipelines with arguments protected by shell quoting, as make doesn't attend to quoting at all.

RISCV dissassembly options numeric and no-aliases

I cloned the riscv-tools repository (master branch) and followed the build procedure. Everything went fine.
Then I tried compiling the hello world program for a RV32IM instruction set, doing this:
riscv64-unknown-elf-gcc -m32 -march=RV32IM -o hello hello.c -save-temps
I used options save-temps to keep the intermediate files. (hello.s, hello.i, hello.o)
Everything is OK so far, I can run the hello world program with:
spike pk hello
Hello world!
Now I wanted to take a look at the assembly code for this program. I did the following and I do get the assembly code into hello.dump
riscv64-unknown-elf-objdump -D -S -l -F hello.o > hello.o.dump
Now what I would be interested to see is the assembly code without pseudo instructions and with the non ABI-register names.
It appears to be possible to get that, when I do:
riscv64-unknown-elf-objdump --target-help
I get this:
The following RISC-V-specific disassembler options are supported for use
with the -M switch (multiple options should be separated by commas):
numeric Print numeric reigster names, rather than ABI names.
no-aliases Disassemble only into canonical instructions, rather
than into pseudoinstructions.
However when I try adding these options, it does not work.
riscv64-unknown-elf-objdump -D -S -l -F -Mno-aliases hello.o > hello.o.dump
Unrecognized disassembler option: no-aliases
riscv64-unknown-elf-objdump -D -S -l -F -Mnumeric hello.o > hello.o.dump
Unrecognized disassembler option: numeric
riscv64-unknown-elf-objdump -D -S -l -F -Mnumeric,no-aliases hello.o > hello.o.dump
Unrecognized disassembler option: numeric
Unrecognized disassembler option: no-aliases
Is it a command syntax error or is it just not supported yet by the disassembler?
I can reproduce this and get the same error message. However, riscv64-unknown-elf-objdump returns 0 and the output file does contain an assembler dump without pseudoinstructions and/or with numeric register names, as requested by the option. So it seems like this is working as expected, it just also outputs an irritating error message.
The riscv-tools repo has not been updated since Feb. I also tried this with a build of a more recent version of riscv-gnu-toolchain and here I don't get the error message. So I'd say this is a non-critical bug that already has been fixed in riscv-gnu-toolchain and thus it will be fixed in riscv-tools as soon as riscv-gnu-toolchain is updated there.
You are right, I do get the error message, but when I look at the assembler dump, the numeric register names and the non-pseudo instructions are visible in the file.
Thanks for pointing out that this is just an misleading error message beeing printed...

Can I use Preprocessor Directives in .ld file

Can I use Preprocessor Directives in .ld file?
I need to to use one of two sets of .ld file and wants to let Build engine deside that using macro, Can I do that?
Yes, you can. You need to run preprocessor manually for your linker script, like this:
in="your_linker_script.ld"
out="generated_script.ld"
cflags=-Iinclude/
gcc -E -P -x c $cflags $in >$out
Flags:
-E specifies GCC to only run preprocessor
-P prevents preprocessor from generating linemarkers (#line directives)
-x c tells GCC to treat your linker script as C source file (it's needed to run GCC with your LD script)
Or you can simply use cpp tool, which is actually C preprocessor.
After this you will be able to use generated linker script to build your program (e.g. in Makefile).
Example
Here is how I solved this problem in my project:
Here is my linker script uses preprocessor (#include directive and CONFIG_TEXT_BASE constant). Excerpt:
#include <config.h>
. = CONFIG_TEXT_BASE;
Here is script to generate preprocessed linker script. Excerpt:
gcc -E -P -x c -Iinclude $cflags $in >>$out
Here is my Makefile, it's generating preprocessed linker script at $(LDS_GEN) target (line 53) and the this generated script is being used to build result binary (line 42). Excerpt:
$(LDS_GEN): $(LDS)
build/gen-lds.sh $(LDS) $(LDS_GEN) $(CFLAGS)
$(APP).bin: $(OBJS) $(LDS_GEN)
$(LD) $(OBJS) -T $(LDS_GEN) -o $(APP).elf
Small update after long time. This way of pre-processing works until the memory file does not contain lines that are fooling the pre-processor. E.g.:
"KEEP(*path/*.o(.rodata .rodata*))"
The "/*" after path is considered comment start (the line contains what is considered a C multi-line comment start and not a match pattern).
This line is valid for the linker but it is considered comment and the output from C pre-processor will remove everything till a supposed closing comment is found:
"KEEP(*path"
The resulting file is clearly invalid for the linker. I have no solution at the moment.
As a simplification of Sam's answer, I added the below to my makefile and away we go :)
PRE_LD_FILE = $(PROG_NAME).ld
LD_FILE = $(PROG_NAME)_generated.ld
$(LD_FILE) : $(PRE_LD_FILE)
cpp $(PRE_LD_FILE) | grep -v '^#' >>$(LD_FILE)

Resources