I want to print out all #define macros when compiling u-boot using ARM cross compiler.
According to GCC dump preprocessor defines link I can add -dM -E flags to achieve this. However using
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- CFLAGS=-dM
does not print out any #define macros.
Is there way to achieve this and print out all #define macros to a txt file?
Related
My toolchain is a recent version of arm-gcc.
I have a piece of code in an assembly file which must be conditionally included/assembled.
.ifdef MACRO_FROM_CMDLINE
Assembly instr1
Assembly instr2
.endif
Encapsulated code is a recent addition.
I have tried both:
gcc -x assembler-with-cpp --defsym MACRO_FROM_CMDLINE=1 <along with other necessary options>
gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 <along with other necessary options>
The -D results in "Invalid identifier for .ifdef " and ".endif without .if" errors.
The --defsym results in "MACRO_FROM_CMDLINE=1 : No such file or directory", "unrecognized option --defsym" errors.
The gcc binary drives the compilation process by invoking a number of other programs in sequence to actually perform the various stages of work (compiling, assembling, linking).
When you say:
gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 ...
you are asking it to run the source through the C preprocessor, and then run the result through the assembler.
The C preprocessor step will turn:
.ifdef MACRO_FROM_CMDLINE
into:
.ifdef 1
before passing it to the assembler, which then can't make sense of it. This is why you get the "invalid identifier" error. It also explains why using C preprocessor #ifdef fixes the problem.
--defsym doesn't work because it's an option to the assembler, not the gcc driver program. (The gcc driver does understand and pass through some options to some of the programs it invokes, but not all.)
You can, however, pass arbitrary options through to the assembler using the
-Wa,option[,option...]
syntax, which tells the gcc driver to pass those option(s) through to the assembler (as a list of space-separated options).
For example:
gcc -x assembler-with-cpp -Wa,--defsym,MACRO_FROM_CMDLINE=1 ...
adds
--defsym MACRO_FROM_CMDLINE=1
to the list of options passed to as when gcc invokes it, and that's how to make your original .ifdef example work.
You can see the individual programs invoked by gcc, and the options it actually passes to them, by adding the -v option.
In this case, you should see something called cc1 (the actual GCC C compiler binary) invoked with the -E flag (preprocess only) to preprocess the input to a temporary file, and then as invoked on the temporary file to assemble it.
Strange, but it it turns out I needed to use the C syntax in the assembly file.
#ifdef MACRO
Assembly Instruction
Assembly Instruction
#endif
And the macro had to be passed using the -D option.
I've been attempting to make a folder for each architecture my code can support. In this folder are platform specific files to include. I include them as follows:
#define STR(x) #x
#define ASSTR(x) STR(x)
#include ASSTR(ARCHITECTURE/sizes.h)
My compilation line in make looks like this:
gcc -o $# -c $< -DARCHITECTURE=i386
Which works, until I define ARCHITECTURE to be i386. When this happens, it looks for 1/sizes.h, so I assume it's already defined somewhere.
I believe the C preprocessor (cpp), which is called by gcc, defines i386 (for i386 systems). You can find out what it defines like so:
touch foo.h; cpp -dM foo.h; rm foo.h
This method is described by the cpp man page, under -d, with the character M (so, -dM):
Instead of the normal output, generate a list of #define directives for all the macros defined during the execution of the preprocessor, including predefined macros. This gives you a way of finding out what is predefined in your version of the preprocessor. Assuming you have no file foo.h, the command
touch foo.h; cpp -dM foo.h
will show all the predefined macros.
In a makefile I work on, gcc is used with the -D XOPEN_SOURCE=500 and -D_BSD_SOURCE options. gcc --help does not tell me what these are; a quick google search didn't help either. I'm quite a newbie with gcc, could someone give me a hint?
According to the GCC documentation ("3.11 Options Controlling the Preprocessor"), the -D switch defines the macros XOPEN_SOURCE and _BSD_SOURCE with the values 500 and 1 respectively. It's as though you have this code at the beginning of all the source files you pass to GCC:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE 1
Build scripts usually take advantage of the compiler's ability to "insert" macros like these to "communicate" to the source code details about the platform being targeted (e.g. operating system version).
The "opposite" command-line switch for -D is -U, which #undefs a macro.
Most (if not all) modern C/C++ compilers include similar switches. For example, Visual C++ compilers accept the /D compiler switch, which essentially serves the same purpose as GCC's -D switch.
For future reference, the GCC option index is great if you need to look up compiler switches for the GCC compiler.
-D is used to set defines. The source code you are compiling most likely is using those defines to include specific header files.
Think of -D as doing the same thing as:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE 1
at the top of the file it is currently compiling.
These do not nothing for gcc. These are definitions like similar you have in your .c, .cpp or .h files:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE
-D is equlivant of a #define
i.e.
#define XOPEN_SOURCE 500
-D sets a define. It's like adding a header file that contains:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE 1
You can then use #ifdef _BSD_SOURCE to enable conditional compilation of certain part of the code.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Running the GCC preprocessor
Is there a GCC option to make the GCC preprocessor generate C source code but filter out irrelevant source code?
For example, a C file has #define switch to define for many different platforms. I'm only intersted in one platform, so I want the C preprocessor to filter out unrelated code. Does GCC support this?
Use gcc -E to only run the preprocessor part, e.g. give a file in.c
#if 0
0;
#endif
#if 1
1;
#endif
running
$ gcc -E in.c -o in.i
yields a file in.i
# 1 "in.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "in.cpp"
1;
i.e. the parts behind the #if 0 got removed. If you would have #include'd files they would have been pasted too though, so I am not sure how much help this is.
It sounds like you actually want unifdef, not the GCC preprocessor.
Yes - almost certainly your compiler provides certain default definitions in the environment that you can use to turn code on and off for different systems. __GNUC__ is a good one for GCC. For example:
#ifdef __GNUC__
#define SOME_VALUE 12
#else
#define SOME_VALUE 14
#endif
If you compile that block with GCC, SOME_VALUE will be 12, and if you compile with MSVC, for example, SOME_VALUE will be 14. A list of platform specific definitions is available at this question.
You probably can use:
gcc -CC -P -Uswitch -undef -nostdinc -fdirectives-only -dDI -E
With switch the #define you know will be undefined.
I am compiling a demo project.
The project is written for windows and linux. I have written a Makefile. However, I am not sure how to specify the platform the compiler will be compiling on.
I will be compiling on Linux.
In my source file I have this:
#if defined(WIN32)
#include ...
#include ...
#elif defined(LINUX)
#include ...
#include ..
#else
#error "OS not supported"
#endif
My simple Makefile is this. And when I compile I get the error "OS not supported".
How can I add the directive so that it will compile with the #elif defined(LINUX).
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
app: *.cpp *.h Makefile
g++ $(LIBS_PATH) $(INC_PATH) *.cpp -o app
Many thanks for any suggestions,
Decide which is going to be your default platform - say LINUX.
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
PLATFORM = -DLINUX
CXX = g++
app: *.cpp *.h Makefile
${CXX} ${CFLAGS} ${PLATFORM} ${INC_PATH} *.cpp -o $# ${LIBS_PATH} ${LIBS}
You can use round brackets in place of braces. This uses a macro for the C++ compiler, allows you to add other flags via CFLAGS (though that is also usually set by 'make'), and adds a platform, the include path, the library path and the actual library to the compile line.
Note that your rule enforces a complete recompilation of everything every time anything changes. This is 'safe' but not necessarily efficient. Note that wild-cards are dangerous too - more so for the source than the headers. You may include that backup copy of a file in the build (old-reader.cpp - you only wanted reader.cpp in there really). More conventionally, you list the object files needed for the program so that each object file can be individually rebuilt when needed, and the results linked together. If you get your dependencies correct (a moderately big 'if'), then there's no problem. If you get them wrong, you can end up with inconsistent programs.
However, if the difference is between a 5 second recompile and a 5 minute recompile, you should probably take the 5 minute recompilation (as shown) and answer another SO question while waiting.
To compile on Linux (64-bit):
make CFLAGS="-m64"
To compile on Linux (32-bit):
make CFLAGS="-m32"
To compile on Windows 64:
make PLATFORM=-DWIN64
To compile on Windows 32:
make PLATFORM=-DWIN32
Etc.
You can add -DLINUX=1 when compiling.
Also, if you run:
echo "" | cpp -dD
You can see the list of default #define when compiling. In linux, there will always be a:
#define __linux__ 1
in the output. So if you change your LINUX by the above #define, you don't need to do anything special. Ie:
...
#elif defined(__linux__)
...
As for the Makefile itself, I would do something like:
CXX=g++
CPPFLAGS = -I/usr/norton/include
LDFLAGS = -L/usr/norton/lib -lntr
OBJ_FILES = one.o two.o
app: $(OBJ_FILES) Makefile
one.o: one.cpp one.h
two.o: two.cpp two.h
So the implicit rules are used.