Pre-processing C code with GCC - gcc

I have some C source files that need to be pre-processed so that I can use another application to add Code Coverage instrumentation code in my file.
To do so, I use GCC (I'm using this on a LEON2 processor so it's a bit modified but it's essentially GCC 3.4.4) with the following command line:
sparc-elf-gcc -DUNIT_TEST -I. ../Tested_Code/0_BSW/PKG_CMD/MEMORY.c -E > MEMORY.i
With a standard file this works perfectly, but this one the programmer used a #ifndef UNIT_TEST close and no matter what I do the code won't be pre-processed. I don't understand why since I'm passing -DUNIT_TEST to GCC explicitly defining it.
Does anyone have any clue what could cause this? I checked the resulting .i file and as expected my UNIT_TEST code is not present in it so I get an error when instrumenting it.

Anything wrapped in an #ifndef will only be parsed if it's NOT defined so you need to remove that definition to get all the code that is inside that block. GCC can't spit out preprocessed info for all the #ifdef and #ifndef if at preprocessing times symbols are/aren't defined.

Related

gfortran does not process #define in include [duplicate]

I would like to understand how the preprocessor inlines includes into the code in Fortran. With C, it's pretty simple:
Test.c:
#include <stdio.h>
int main(void) {
return 0;
}
Then I compile using:
gcc -E test.c
Then it displays the content generated by the C preprocessor, as expected.
Now assume I have this Fortran code:
Test.f:
program test
include "mpif.h"
call mpi_init
call mpi_finalize
end
Then I run:
gfortran -E -cpp test.f // For some reason I need -cpp when using -E in Fortran
But I won't have the expected result, which is the generated include embedded into the code.
Instead, I have this:
# 1 "test.f"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.f"
program test
include 'mpif.h'
call mpi_init
call mpi_finalize
end
What am I doing wrong here?
Fortran has its own include directive which must not be confused with the preprocessor directive #include. As far as I understand it, the included code is not embedded into the master file, but the compiler instead continues to compile from the include file, and returns to the master file at the end of that file. From here:
The INCLUDE statement directs the compiler to stop reading statements
from the current file and read statements in an included file or text
module.
Also, included files are not preprocessed further, while #included ones are.
Note, that there is also a naming convention that enables the preprocessor only on files with capital suffixes *.F and *.F90. If you want to preprocess *.f or *.f90 files, you need to specify that in a compile option, e.g. -cpp for gfortran, and -fpp for ifort.

Configure clang-check for c++ standard libraries

I am trying to run Ale as my linter, which in turn uses clang-check to lint my code.
$ clang-check FeatureManager.h
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "FeatureManager.h"
No compilation database found in /home/babbleshack/ or any parent directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
/home/babbleshack/FeatureManager.h:6:10: fatal error: 'unordered_map' file not found
#include <unordered_map>
^~~~~~~~~~~~~~~
1 error generated.
Error while processing /home/babbleshack/FeatureManager.h.
Whereas compiling with clang++ returns only a warning.
$ clang++ -std=c++11 -Wall FeatureManager.cxx FeatureManager.h
clang-5.0: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
There are no flags to clang-check allowing me to set compilation flags.
Took a while to figure this out, but you can do
clang-check file.cxx -- -Wall -std=c++11 -x c++
or if you are using clang-tidy
clang-tidy file.cxx -- -Wall -std=c++11 -x c++
To get both working with ALE, I added the following to my vimrc
let g:ale_cpp_clangtidy_options = '-Wall -std=c++11 -x c++'
let g:ale_cpp_clangcheck_options = '-- -Wall -std=c++11 -x c++'
If you want ALE to work for C as well, you will have to do the same for g:ale_c_clangtidy_options and g:ale_c_clangcheck_options.
I was getting stumped by a similar error message for far too long:
/my/project/src/util.h:4:10: error: 'string' file not found [clang-diagnostic-error]
#include <string>
^
I saw other questions suggesting that I was missing some critical package, but everything already seemed to be installed (and my code built just fine, it was only clang-tidy that was getting upset).
Passing -v showed that my .h file was being handled differently:
$ clang-tidy ... src/*.{h,cc} -- ... -v
...
clang-tool ... -main-file-name util.cc ... -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9 ... -x c++ ... /tmp/copy/src/util_test.cc
...
clang-tool ... -main-file-name util.h ... -x c-header /my/project/src/util.h
...
As Kris notes the key distinction is the -x c-header flag, which is because clang assumes a .h file contains C, not C++, and this in turn means that the system C++ includes weren't being used to process util.h.
But the -main-file-name flag also stood out to me as odd; why would a header file ever be the main file? While digging around I also came across this short but insightful answer that header files shouldn't be directly compiled in the first place! Using src/*.cc instead of src/*.{h,cc} avoids the problem entirely by never asking Clang to try to process a .h on its own in the first place!
This does introduce one more wrinkle, though. Errors in these header files won't be reported by default, since they're not the files you asked clang-tidy to look at. This is where the "Use -header-filter=. to display errors from all non-system headers.*" message clang-tidy prints comes in. If I pass -header-filter=src/.* (to only include my src headers and not any other header files I'm including with -I) I see the expected errors in my header files. Phew!
I'm not sure whether to prefer -x c++ or -header-filter=.* generally. A downside of -header-filter is you have to tune the filter regex, rather than just passing in the files you want to check. But on the other hand processing header files in isolation is essentially wasteful work (that I expect would add up quickly in a larger project).

How do I create a custom library in GNU?

How do I create a custom library in GNU? What I mean is:
When we use #include < stdio.h> and printf
we can compile it with gcc main.c
Now I create my custom headers and .a/.so library files, I know I can set the environment variable C_INCLUDE_PATH and include my header files with #include<> instead of #include"". However, I still have to compile it with
gcc main.c -o program -L/whatever/ -lwahtever
(with set environment variable if using .so)
Is it possible to make it behave like #include< stdio.h> where I don't need to include the paths with corresponding command line arguments?
You actually don't need -L/whatever/, just -lwhatever. The first option supplies the path to your library, but you have already taken care of that with the #include and modifying C_INCLUDE_PATH. The second option tells the linker which library to link your executable with. An example of this is when using functions from the C math library, you #include <math.h>, but to compile, you still need the linker option -lmath. So to answer your question, no. You can remove the first option, but you must leave the second.

Detect when only preprocessing, i.e. gcc -E

I currently invoke clang or gcc as
cc -E -DPREPROCESSING ...
when debugging macros.
It has occurred to me that the define is redundant. Is there an expression I could write in the source to detect when the compiler will stop after preprocessing, and so drop this definition from my build scripts?
#if magic
#define PREPROCESSING
#ending
A look at the docs suggests not, but with luck I'm missing something.
Whatever solution you come up with is going to be compiler-specific, since the C standard does not have anything to say about separate preprocessing.
In gcc, you could implement the magic by adding a custom spec file:
%rename cpp old_cpp
*cpp:
%{E:-DPREPROCESSING} %(old_cpp)
You would need to tell gcc to use this spec file (-specs=/path/to/specfile), unless you compiled your own gcc with the above definition added to the built-in cpp spec. If you are using a Makefile, you could add the -specs option above to your CFLAGS.
(I should add that I don't think this is a particularly good idea. But it is possible.)

How to force gcc to link like g++?

In this episode of "let's be stupid", we have the following problem: a C++ library has been wrapped with a layer of code that exports its functionality in a way that allows it to be called from C. This results in a separate library that must be linked (along with the original C++ library and some object files specific to the program) into a C program to produce the desired result.
The tricky part is that this is being done in the context of a rigid build system that was built in-house and consists of literally dozens of include makefiles. This system has a separate step for the linking of libraries and object files into the final executable but it insists on using gcc for this step instead of g++ because the program source files all have a .c extension, so the result is a profusion of undefined symbols. If the command line is manually pasted at a prompt and g++ is substituted for gcc, then everything works fine.
There is a well-known (to this build system) make variable that allows flags to be passed to the linking step, and it would be nice if there were some incantation that could be added to this variable that would force gcc to act like g++ (since both are just driver programs).
I have spent quality time with the gcc documentation searching for something that would do this but haven't found anything that looks right, does anybody have suggestions?
Considering such a terrible build system write a wrapper around gcc that exec's gcc or g++ dependent upon the arguments. Replace /usr/bin/gcc with this script, or modify your PATH to use this script in preference to the real binary.
#!/bin/sh
if [ "$1" == "wibble wobble" ]
then
exec /usr/bin/gcc-4.5 $*
else
exec /usr/bin/g++-4.5 $*
fi
The problem is that C linkage produces object files with C name mangling, and that C++ linkage produces object files with C++ name mangling.
Your best bet is to use
extern "C"
before declarations in your C++ builds, and no prefix on your C builds.
You can detect C++ using
#if __cplusplus
Many thanks to bmargulies for his comment on the original question. By comparing the output of running the link line with both gcc and g++ using the -v option and doing a bit of experimenting, I was able to determine that "-lstdc++" was the magic ingredient to add to my linking flags (in the appropriate order relative to other libraries) in order to avoid the problem of undefined symbols.
For those of you who wish to play "let's be stupid" at home, I should note that I have avoided any use of static initialization in the C++ code (as is generally wise), so I wasn't forced to compile the translation unit containing the main() function with g++ as indicated in item 32.1 of FAQ-Lite (http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html).

Resources