GCC: Inconsistent "undefined function" warnings? - gcc

Recently I've been poking around and trying to figure out how C compilers work.
I've noticed that different computers seem to exhibit different behaviours for the following actions:
// a.c
// #include"oui.h"
int main() {
oui();
}
// oui.h
void oui();
gcc -c a.c
On one computer, I am warned that function oui in a.c is undefined. This makes sense to me, and uncommenting the include fixes the problem.
On another computer, however, even with the include commented out, the compiler produces the object a.o without complaint. This does not make sense to me, because isn't oui undefined without the header file?
Which is the normal behaviour? Are some settings on one of my computers messed up?
Don't bother with the following questions if you don't want to, they just popped into my mind and I'll make another thread if need be :).
Side question: The -c flag produces object files but does not link, so is there a special "link" flag afterwards to put the object files together, or is it just gcc? Why not just gcc everything together at the start?
Side question #2: if I do gcc filea fileb filec, is filea inherently special for being the first argument? Or does the order of gcc not matter because the compiler finds whichever file has main by itself?

It's maybe a version difference between the two computers.
Which is the normal behaviour?
The compiler should warn, if you use a function, that isn't declared.
Are some settings on one of my computers messed up?
I don't think so, that you have one newer gcc and a older one.
Side question #1:
If you use gcc without -c, it will try to invoke the linker. In this example, the linker will fail, as oui is undefined.
-c is often used in Makefiles/for bigger projects, as you can recompile faster, because the compiler doesn't have to compile every source file again.
Side question #2:
The order of the source files doesn't matter, as the linker finds main by itself.

Related

What is the right order of linker flags in gcc?

Normally, I would compile a program that requires a specific library, e.g. math, by passing the linker flag after the sources that need it like so:
gcc foo.c -lm
However, it seems that older versions of gcc work equally well with the reverse order (let's call this BAD ORDER):
gcc -lm foo.c
I wouldn't worry about it if some popular open-source projects I'm trying to compile didn't use the latter while my version of gcc (or is it ld that's the problem?) work only in the former case (also, the correct one in my opinion).
My question is: when did the BAD ORDER stop working and why? It seems that not supporting it breaks legacy packages.
when did the BAD ORDER stop working and why? It seems that not supporting it breaks legacy packages.
When?
Not dead sure but I think pre-GCC 4.5. Long ago. Subsequently, the --as-needed option is operative for shared libraries by default,
so like static libraries, they must occur in the linkage sequence later than the objects for which they provide definitions.
This is a change in the default options that the gcc/g++/gfortran etc. tool-driver passes to ld.
Why?
It was considered confusing to inexpert users that static libraries by default has to appear
later that the objects to which they provided definitions while shared libraries by default did
not - the difference between the two typically being concealed by the -l<name> convention
for linking either libname.a or libname.so.
It was perhaps an unforeseen consequence that inexpert users who
had formerly had a lot of luck with the mistaken belief that a GCC
[compile and] link command conforms to the normal Unix pattern:
command [OPTION...] FILE [FILE...]
e.g.
gcc -lthis -lthat -o prog foo.o bar.o
now fare much worse with it.

G++/LD fails: can't find library when library isn't actually needed

I have a program foo I'm trying to compile and link and I'm running into a chicken and egg dillemma.
For reasons I'll explain below, Within a given directory I'm forced to add a link to several libraries we build (let's call them libA and libB) regardless of my target. I know I only actually need libA for my program; so after all libs are built and this binary is built I verified with ldd -u -r foo to show that libB is an unused direct dependency.
Being unused I altered the makefiles and flags such that libB is enveloped with -Wl --as-needed and -Wl --no-as-needed. I make rebuild, use ldd again and this time it doesn't show any unused deps. So far so good.
Now the fun part: Since its unused I would expect that if libB is not found/available/built that I should still be able to compile and link foo as long is libA is available. (example: If I did a fresh checkout and only built libA before trying to compile this specific test). But ld errors out with /usr/bin/ld: cannot find -lB
This suggests that ld needs to locate libB even if it won't need any of the symbols it provides? That doesn't seem to make sense. If all symbolic dependencies are already met, why does it even need to look at this other library? (That would explain the problem ld has and why this is not possible)
Is there a way I can say "Hey don't complain if you can't find this library and we shouldn't need to link with it?"
The promised reasons below
For various reasons beyond my control I have to share makeflags with many other tests in this directory due to the projects makefile hierarchy. There is a two level makefile for all these tests that says foo is a phony target, his recipe is make -f generictest.mk target=foo, and the generictest.mk just says that the source file is $(target).C, that this binary needs to use each library we build, specifies relative path to our root directory and then includes root's generic makefile. The root directory generic makefile expands all the other stuff out (flags, options, compiler, auto-gen of dependencies through g++ etc), and most importantly for each statement that said "use libX" in generictest.mk it adds -lX to the flags (or in my case enveloped in as-needed's)
While I'm well aware there are lots of things that are very unideal and/or horribly incorrect in terms of makefile best practices with this, I don't have the authority/physical ability to change it. And compared to the alternative employed in other folders, where others make individual concrete copies of this makefile for each target, I greatly prefer it; because that forces me to edit all of them whenever want to revise our whole make pattern, and yields lot of other typos and problems.
I could certainly create another generictest.mk like file to use for some tests and group together those using each based on actual library needs, but it would be kind of neat if I didn't have to as long as I said "you don't all of them, you need each of them but only if you actually use it".
There's no way that the linker can know that the library is not needed. Even after all your "normal" libraries are linked there are still lots and lots of unresolved symbols: symbols for the C runtime library (printf, etc.). The linker has no idea where those are going to come from.
Personally I'd be surprised if the linker didn't complain, even if every single symbol was already resolved. After all there may be fancy things at work here: weak bindings, etc. which may mean that symbols found later on the link line would be preferred over symbols found earlier (I'm not 100% sure this is possible but I wouldn't be surprised).
As for your situation, if you know that the library is not needed can't you just use $(filter-out ...) on the link command line to get rid of it? You'd have to write your own explicit rule for this with your own recipe, rather than using a default one, but at least you could use all the same variables.
Alternatively it MIGHT be possible to play some tricks with target-specific variables. Declare a target-specific variable for that target that resets the variable containing the "bad library" with a value that doesn't contain it (maybe by using $(filter-out ...) as above), and it will override that value for that target only. There are some subtle gotchas with target-specific variables overriding "more general" variables but I think it would work.

Can I tell GCC to fail if I include header files unnecessarily?

The project I'm working on recently made a big effort to cleanup the code by turning on all the strictest GCC warnings and iterating until it compiled. Now, for instance, compilation fails if I declare a variable and don't use it.
After my latest development task there I see that there is a header file included somewhere that is now unnecessary. Is there any good way to find other such header files (and in such a way reduce dependencies) other than trying to remove a header file and seeing if anything breaks?
I am using GCC 4.3.2 on Linux.
No, there's no way to get gcc to fail if a header isn't required. Included headers can contain pretty much anything, so it is assumed that whoever included them had good reason to do so. Imagine the following somewhat pathological case:
int some_function(int x) {
#include "function_body.h"
return x;
}
It's certainly not good form, but it would still compile if you removed the include. So, an automatic checker might declare it "unnecessary," even though the behavior is presumably different when the function body is actually there.

Where to find a full list of gcc warnings and errors?

Sometimes I need to use a gcc for cross-platform work, and sometimes gcc really amuses me with its warnings. For example:
#pragma once in a main file
This is very informative warning, but I really don't know what a 'main file' IS in terminology of gcc and WHY it must not contain #pragma once :). So, does any documentation exist that covers all gcc warnings and errors (mostly warnings, errors are trivial) with some comments on them?
The objective of '#pragma once' is to prevent a header from being reincluded. If you have it in a source file (usually a '.c' file), you won't be reading that twice (normally - I do know of a source file that reincludes itself [and I don't like it]; it does not use or want #pragma once, though!). So, a 'main file' in this context is one listed on the command line, for instance, rather than a header.
As to the subject matter of the question - the GCC manual does not seem to have a comprehensive list. I don't know whether there actually is one.

Is there a way to strip all functions from an object file that I am not using?

I am trying to save space in my executable and I noticed that several functions are being added into my object files, even though I never call them (the code is from a library).
Is there a way to tell gcc to remove these functions automatically or do I need to remove them manually?
If you are compiling into object files (not executables), then a compiler will never remove any non-static functions, since it's always possible you will link the object file against another object file that will call that function. So your first step should be declaring as many functions as possible static.
Secondly, the only way for a compiler to remove any unused functions would be to statically link your executable. In that case, there is at least the possibility that a program might come along and figure out what functions are used and which ones are not used.
The catch is, I don't believe that gcc actually does this type of cross-module optimization. Your best bet is the -Os flag to optimize for code size, but even then, if you have an object file abc.o which has some unused non-static functions and you link statically against some executable def.exe, I don't believe that gcc will go and strip out the code for the unused functions.
If you truly desperately need this to be done, I think you might have to actually #include the files together so that after the preprocessor pass, it results in a single .c file being compiled. With gcc compiling a single monstrous jumbo source file, you stand the best chance of unused functions being eliminated.
Have you looked into calling gcc with -Os (optimize for size.) I'm not sure if it strips unreached code, but it would be simple enough to test. You could also, after getting your executable back, 'strip' it. I'm sure there's a gcc command-line arg to do the same thing - is it --dead_strip?
In addition to -Os to optimize for size, this link may be of help.
Since I asked this question, GCC 4.5 was released which includes an option to combine all files so it looks like it is just 1 gigantic source file. Using that option, it is possible to easily strip out the unused functions.
More details here
IIRC the linker by default does what you want ins some specific cases. The short of it is that library files contain a bunch of object files and only referenced files are linked in. If you can figure out how to get GCC to emit each function into it's own object file and then build this into a library you should get what you are looking.
I only know of one compiler that can actually do this: here (look at the -lib flag)

Resources