Compiling previously preprocessed file changes output - c++

I have a source file which I preprocess using the options -E and -P (using GCC 4.1.2 for a vxWorks-based embedded platform). All other options are the same as when I compile the file. These options are:
-Wall
-march=pentium
-nostdinc
-O0
-fno-builtin
-fno-defer-pop
-g
-c
-o
as well as all include-paths. Now when I compile this preprocessed file, the resulting object-file is much smaller (about 30%) than when I compile the original directly. And when I then link the program, the linker complains about missing symbols (all in user-code), which again does not happen when using the original source-file. Why is there a difference? Is there any way to make this work?

You're sure you're not missing any -D defines from your command line? Your result would be consistent with parts not being compiled due to conditionals.
Another possibility (since you don't name the compiler specifically) is that you're using a generic gcc -E rather than the arch-specific cross compiler for your vxWorks environment. The cross-gcc will predefine some variables that you'll need for gcc -E.

When compiling the preprocessed output, try passing the -fpreprocessed option to tell GCC not to preprocess again.
The only difference I can think of is macros that result in expanding to an identifier that's a macro name that has already been expanded - the preprocessor stops expansion at that point, but if you ran the preprocessor again, the identifier would be expanded again. I would have expected any instances of this to probably cause a compiler error, but who knows?

Related

Code size is doubled when compiling with GCC ARM Embedded?

I've just ported a STM32 microcontroller project from Keil uVision (using Keil ARM Compiler) to CooCox CoIDE (using GCC ARM Embedded compiler).
Problem is, the code size is the double size when compiled in CoIDE with GCC compared to Keil uVision.
How can this be? What can I do?
Code size in Keil: 54632b (.text)
Code size in CoIDE: 100844b (.text)
GCC compiler flags:
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -g2 -Wl,-Map=project.map -Os
-Wl,--gc-sections -Wl,-TC:\arm-gcc-link.ld -g -o project.elf -L -lm
I am suspecting CoIDE and GCC to compile a lot of functions and files, that are present in the project, though aren't used (yet). Is it possible that it compiles whole files even if I only use 1 function out of 20 in there? (even though I have -Os)..
Hard to say which files are really compiled/linked in your final binary from the information you give. I suppose it takes all the C files it finds on your project if you did not explicitly specified which one to compile or if you don't use your own Makefile.
But from the compiler options you give, the linker flag --gc-sections won't do much garbage if you don't have the following compiler flags: -ffunction-sections -fdata-sections. Try to add those options to strip all unused functions and data at link time.
Since the question was tagged with C++, I wonder if you would like to disable exceptions and RTTI. Those take quite a bit of code. Add -fno-exceptions -fno-rtti to linker flags.

If you specify conflicting command line arguments to GCC, which one is accepted? [duplicate]

I know that if you execute GCC as such:
gcc -O3 -O2 foo.c
GCC will use the last optimization flag passed (in this case O2). However, is this true for all flags? For example, if I execute GCC like so:
gcc -mno-sse -msse bar.c
Will it support SSE since that was the last flag passed, or would this result in undefined behavior? My initial experimentation seems to indicate that it will support SSE, but I'm not sure if this is true for all cases.
Normally later options on the line override ones passed previously, as you mention in your first example. I haven't personally come across any different behaviour for -m or -f flags, but I don't know of a specific reference in the documentation.
Note that some options don't behave this way:
$ gcc example.c -DABC -DABC=12
<command-line>: warning: "ABC" redefined
<command-line>: warning: this is the location of the previous definition
So there would need to be a -UABC in between there to shut that warning up.
As an aside, clang is particularly good at solving this problem - it will produce a warning if it ignores a command line option, which can help you out.

Configuring g++ from Code::Blocks doesn't take affect on command line

I'm trying to change the settings of g++ from the Code::Blocks IDE. I went to the Settings tab, clicked Compiler... and checked various options for the compiler to use, like
Enable all warnings (-Wall)
Have g++ follow the C++11 ISO C++ language standard (-std=c++11)
......
These are just two of many others; when I compile on the command line, here is what comes up:
g++ -o example example.cpp
# warning: initializer lists only available with -std=c++11 ...
Notice how there's no warning either - I have an unused variable in my program. It only works if I give the options manually:
g++ -Wall -std=c++11 -o example example.cpp
Do you think I might have done something wrong when setting up the compiler? Why aren't the options taking affect?
Invoking the compiler from the ide is completely independent from doing it in a command line shell. There's no reason for the setting and usage of one to have any effect on the other.

equivalent gcc flags for g++ call

I'm playing around with a toolchain that seems to wrap gcc (qcc), but also uses g++ for a few things. This caused a bit of confusion when I couldn't link libs I built with g++ using g(q)cc even though it was for the same architecture (due to missing lib errors). After a bit more research, I found that g++ is basically gcc with a few default flags and a slightly different interpretation mechanism for file extensions (there may be other differences I've glanced over). I'd like to know exactly which flags can be passed to gcc to amount to the equivalent g++ call. For instance:
g++ -g -c hello.cpp // I know at the very least that this links in stl
gcc -g -c -??? // I want the exact same result as I got with g++... what flags do I use?
The way the tool chain is set up makes it sort of difficult to simply replace the gcc calls with g++. It'd be much easier to know which flags I need to pass.
The differences between using gcc vs. g++ to compile C++ code is that (a) g++ compiles files with the .c, .h, and .i extensions as C++ instead of C, and that (b) it automatically links with the C++ standard library (-lstdc++). See the man page.
So assuming that you're not compiling .c, .h., or .i files as C++, all you need to do to make gcc act like g++ is add the -lstdc++ command line option to your linker flags. If you are compiling those other files as C++, you can add -x c++, but I'd advise you instead to rename them to use .cc or .ii files (.h can stay that way, if you're using precompiled headers).

F77: problem to compile with g77 a program which was normally compiled with Absoft compiler

I am not a Fortran programmer (just a short experience), but I need to compile a program partly written in F77. Someone has compiled it with Absoft compiler before me, but now I need to repeat the procedure on another machine with g77. For Absoft, the makefile has
f77 -f -w -O -B100 -B108 -c *.f
mv *.f flib && mv *.o olib
f77 -B100 -o runme olib/*.o clib/*.o -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lX11 -L$PVM_ROOT/lib/$PVM_ARCH -lfpvm3 -lpvm3 -L$ABSOFT/lib -lU77
I have modified these lines to be
g77 -w -O -B100 -B108 -c *.f
mv *.f flib && mv *.o olib
g77 -B100 -o runme olib/*.o clib/*.o -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lX11 -L$PVM_ROOT/lib/$PVM_ARCH -lfpvm3 -lpvm3 -lgfortran -lgfortranbegin
But I get the following error messages
somefile.f:(.text+0x93): undefined reference to `for_open'
somefile.f:(.text+0xf4): undefined reference to `for_write_seq_fmt'
somefile.f:(.text+0x128): undefined reference to `for_write_seq_fmt_xmit'
somefile.f:(.text+0x454): undefined reference to `for_read_seq'
How can I fix this?
UPDATE1
If I add -libifcore to the end of the last line (linker), then I get
/usr/bin/ld: cannot find -libifcore
I have located the library
$ find /opt/intel/* -name 'libifcore*'
/opt/intel/fce/9.1.036/lib/libifcore.a
/opt/intel/fce/9.1.036/lib/libifcore.so
/opt/intel/fce/9.1.036/lib/libifcore.so.5
/opt/intel/fce/9.1.036/lib/libifcore_pic.a
/opt/intel/fce/9.1.036/lib/libifcoremt.a
/opt/intel/fce/9.1.036/lib/libifcoremt.so
/opt/intel/fce/9.1.036/lib/libifcoremt.so.5
/opt/intel/fce/9.1.036/lib/libifcoremt_pic.a
But even if I do the following in the source directory
$ export PATH=$PATH:/opt/intel/fce/9.1.036/lib/
$ ln -s /opt/intel/fce/9.1.036/lib/libifcore.so
it is not found.
Moreover, it is the same machine where I get another problem How to pass -libm to MPICC? libimf.so: warning: feupdateenv is not implemented and will always fail
It seems that the compiler should find the library, if needed
$ echo $LD_LIBRARY_PATH
/opt/intel/fce/9.1.036/lib:/opt/intel/cce/9.1.042/lib:/usr/local/lib/openmpi:/usr/local/lib:/usr/lib:
Absoft accepted an extended version of Fortran 77 that is not completely compatible with the extended version of Fortran 77 accepted by g77.
So there is no guarantee that you can do this without editing the code. I seem to recall that the Absoft compiler accepted a handy initialization syntax that can not be replicated with g77.
If you want to compile & link using g77, the easiest way is to use the command "g77". (What compiler does f77 invoke on your computer? Try "f77 -v" or similar to find out...) It should automatically find the g77 Fortran-specific libraries. You should not need to explicitly link to Fortran libraries, and especially not to the libraries of gfortran, which is a different compiler. You could also compile & link with gfortran -- it will probably recognize that the source code is Fortran 77 and compile appropriately if the files have the correct file type, otherwise you will have to use options -- for this compiler, use the command "gfortran".
With g77 and gfortran it should not need Intel libraries -- maybe f77 is connected to ifort, the Intel compiler, on your computer?
Edited later:
I suggest trying something simpler first to test your setup.
Try this FORTRAN 77 program as file "junk.f"
C234567
write (6, *) "Hello World"
stop
end
Try this command:
g77 junk.f -o junk.exe
Run it via:
./junk.exe
This will test whether g77 is working.
it looks like you are trying to link with libifcore.
Edit:
You can include this library by adding
'-lifcore' to your compiler options. To quote the gcc tutorial
In general, the compiler option -lNAME will attempt to link object files with a library file ‘libNAME.a’ in the standard library directories.
why do you use g77 and not gfortran?
what do you mean with multiprocessing? openmp or vectorized?
you can use openmp with the gfortran compiler and when you want to use vector mode like the ifort compiler does, you have to specify sse explicitly in the compiler options.
It seems that the problem was in an error in one of the source files, which wasn't a big deal for Absoft compiler. g77 was giving a warning about it, but compiling this file and producing the original errors (mentioned in the question) without a binary.
When I tried ifort, compilation of that file was aborted, but other files were compiled and a binary was created.
fortcom: Error: somefile.f, line 703: An extra comma appears in the format list. [)]
& (1p5e12.3,5h ...,))
-------------------------^
compilation aborted for somefile.f (code 1)
When I removed the extra comma, then both compilers have compiled everything and created binaries, although ifort produced a number of warnings.
Then, when I tried to run both binaries, the one made by Intel comiler was working fine, but the one by g77 was behaving very strange and didn't really do what I wanted.
So now the original problem is resolved, however the code doesn't run in multiprocessing mode, so the binary is unfortunately useless for me.