Michael Darling wrote: > I'm not sure if this is an issue with my KDevelop settings, or rather > if it is a g++ problem. If it's a g++ problem, I'm wondering if First of all, realise that g++ doesn't have any say in the matter. g++ invokes collect2 which invokes the linker (ld), and it's the linker that issues the error. g++ is just a driver to invoke the linker with some extra options, it doesn't actually do any linking. (But you should always link by calling the driver and not 'ld' precisely because those extra options that the driver adds behind the scenes are vital.) The second thing to realize is that the linker scans each object/archive incrementally in the order specified on the command line from left to right. When scanning an archive (.a), if any objects in that archive contain symbols that satisfy references that the linker has seen so far but not yet resolved, those objects get copied from the archive into the output. Any remaining objects in the archive are ignored. In other words, when the linker examines an archive it can only use it to resolve symbols that it knows are necessary at that point in the process. If some object or library later down the line refers to a symbol in one of the objects that was not copied, it will result in an undefined reference because the linker only examines each argument once in the order specified. The implication of this is that you must supply arguments in the correct order of dependency. Furthermore, if there is a circular dependency, you must specify some arguments twice, e.g. if liba and libb mutally refer to symbols in each other then you would need to specify something like "liba.a libb.a liba.a". The linker also has alternative ways of dealing with the problem, such as the --start-group and --end-group options, or the --whole-archive option. See the ld manpage for details. Note also that since these are linker options, you must use -Wl when specifying them to g++ so that the driver will pass them through to the linker rather than trying to interpret them as compiler options, which they are not. For example, instead of "../../liba/liba.a ../../libb/libb.a" you might need "-Wl,-( ../../liba/liba.a ../../libb/libb.a -Wl,-)" to tell the linker that there's a circular dependency between the two. I should also note that as stated (app only depends on liba, and liba only depends on libb) that your command: > g++ -g -O2 -o app app.o -L/usr/lib/mysql ../../liba/liba.a > ../../libb/libb.a -lmysqlclient > ../../liba/liba.a(liba.o): In function `@@@`: > liba.cpp:@: undefined reference to `libb::@@@` > collect2: ld returned 1 exit status ...seems correct and should work. But the fact that it does not suggests that there is some additional circular dependency that exists between liba and libb that you're not aware of, perhaps in something unobvious like a constructor for a static object. If you use the linker's --verbose option (i.e. g++ -Wl,--verbose) it will show you explicitly the order in which archives and objects are processed, and which objects get included into the final link. Hopefully you can compare the verbose output from the working and the non-working case and see the nature of the liba<->libb interdependency. > If I change app's main() from: > libAClass goingToUseThis(); > > to: > libBClass hack(); > libAClass goingToUseThis(); > > Then it links fine. When you do this, ld sees a reference to libBClass at the point where it scans app.o, which is apparently sufficiently early enough in the process to cause it to link the necessary objects from libb.a when it is later encountered. > Is there a way for me to forces g++ to actually link libb.a, when app > is only directly using liba.a? I'm suprised g++ can't figure out that > libb.a really has to be linked since it's being told to do so through > the arguments given. Then again, maybe I'm missing something > simple... You need to have a better mental model of how linking works. It's not a yes/no "should I include this library or not" kind of deal (and it's not even g++ that is at work here.) It's more like "I will scan this archive and from it copy any objects that satisfy undefined references that I've encountered so far" -- the key words being "so far", as it's impossible for the linker to know beforehand what it will need out of a given archive unless it's already scanned every object that might reference something in that archive. The reason that the linker cannot simply consider everything at once in whole is performance. It might not matter on small projects but on medium or large sized links it would be prohibitively slow if it worked that way. I suppose you could force it to operate that way by grouping all arguments into one giant --begin-group/--end-group, but I think you would experience a significant increase in link time for anything of size. > I'm using versions all included in the default RHEL5 yum repositories. > KDevelop 3.5.1, g++ 4.1.2, automake 1.9.6, autoconf 2.59. Note that the linker is not part of gcc. On GNU/Linux systems the linker is part of the binutils package. Also note that in some circumstances and on some platforms, the rules are different, e.g. with shared libraries on GNU/Linux the order given on the link command doesn't matter because the symbols are resolved at run-time anyway as opposed to link-time. But that shouldn't be license to ignore proper dependency-ordering on the link command, since it does matter even for shared libraries on other platforms, and it always matters for static libraries (.a archives.) Brian