views:

128

answers:

6

Hello all,

i've been working for some time with an opensource library ("fast artificial neural network"). I'm using it's source in my static library. When i compile it however, i get hundreds of linker warnings which are probably caused by the fact that the library includes it's *.c files in other *.c files (as i'm only including some headers i need and i did not touch the code of the lib itself).

My question: Is there a good reason why the developers of the library used this approach, which is strongly discouraged? (Or at least i've been told all my life that this is bad and from my own experience i believe it IS bad). Or is it just bad design and there is no gain in this approach?

I'm aware of this related question but it does not answer my question. I'm looking for reasons that might justify this.

A bonus question: Is there a way how to fix this without touching the library code too much? I have a lot of work of my own and don't want to create more ;)

A: 

If you ever declare a single global variable or function in that .c file, it cannot be included in two places which both compile to the same binary, or the two definitions will collide. If it is included in even one place, it cannot also be compiled on its own while still being linked into the same binary as its user.

If the file is only included in one place, why not just make it a discrete compilation unit (and use its globals via extern declarations)? Why bother having it included at all?

If your C files declare no global variables or functions, they are header files and should be named as such.

Therefore, by exhaustive search, I can say that the only time you would ever potentially want to include C files is if the same C code is used in building multiple different binaries. And even there, you're increasing your compile time for no real gain.

This is assuming that functions which should be inlined are marked inline and that you have a decent compiler and linker.

I don't know of a quick way to fix this.

Borealid
+1  A: 

Including C/C++ code leads to all the code being stuck together in one translation unit. With a good compiler, this can lead to a massive speed boost (as stuff can be inlined and function calls optimized away).

If actual code is going to be included like this, though, it should have static in most of its declarations, or it will cause the warnings you're seeing.

cHao
Upvoting since you provided a nice explanation, but marked another answer as correct, since the poster helped with the issue i was having :)
PeterK
A: 

I don't know that library, but as you describe it, it is either bad practice or your understanding of how to use it is not good enough.

A C project that wants to be included by others should always provide well structured .h files for others and then the compiled library for linking. If it wants to include function definitions in header files it should either mark them as static (old fashioned) or as inline (possible since C99).

Jens Gustedt
A: 

I haven't looked at the code, but it's possible that the .c or .cpp files being included actually contain code that works in a header. For example, a template or an inline function. If that is the case, then the warnings would be spurious.

Steven Sudit
+3  A: 
Roger Pate
Thank you for your response, i looked at their example projects and found what needs to be done. Excluding those three *.c files which included other *.c files from build solved the issue, my library compiles fine (warnings disappeared) and the project using the library works perfect (with correct output from the part which uses FANN). Thanks a lot!
PeterK
@Peter: Welcome. I was going the other way in this answer: rather than excluding double-/fixed-/floatfann.c, I see now I assumed they had important settings and thus one of them had to be used, but apparently that isn't true. Hopefully you can see how it accomplishes the same thing (avoiding linking with conflicting definitions).
Roger Pate
A: 

I'm doing this at the moment at home because I'm a relative newcomer to C++ on Linux and don't want to get bogged down in difficulties with the linker. But I wouldn't recommend it for proper work.

(I also once had to include a header.dat into a C++ program, because Rational Rose didn't allow headers to be part of the issued software and we needed that particular source file on the running system (for arcane reasons).)

Brian Hooper