Headers including headers and precompilation

Rich Felker dalias at aerifal.cx
Fri Mar 31 18:45:15 UTC 2006


On Fri, Mar 31, 2006 at 10:12:09AM -0800, Devin Bayer wrote:
> >IMO this is very bad practice. Not only does it hide what the real
> >dependencies are,
> 
> The dependency is simple: SUSv3 and maybe Linux headers.

No. Some modules depend on very little and could work on tiny systems
with only a fraction of this. Others depend on it all. Making the
distinction explicit is useful!

> >but it also brings lots of unnecessary symbols and
> >definitions into the namespace of each file, increasing memory
> >requirements to compile, decreasing speed,
> 
> I assume you mean decreasing compile speed.  Wrong.  On a modern system
> it's faster to use precompiled headers for the entire system then to use
> even a single un-precompiled header.

Compile speed has an O(log n) factor for number of symbols and memory
usage has an O(n) term for number of symbols. Clearly this will grow
higher than the time for parsing any small fixed set of headers as the
number of headers/symbols included in your bloated catch-all header
grows.

Anyway I don't know wtf you mean by modern. I have never used a system
with precompiled headers except msvc ages and ages ago, and that was
because windows.h was such bloated crap that it needed to be
precompiled. On my system the headers are so
small/trivial/nonconditional that they take essentially zero time to
parse. I suspect it's the GNU header crap with 10 levels of nested
includes and conditionals that makes it slow.

> >and possibly causing
> >conflicts with names due to inclusion of unexpected headers.
> 
> Which is a good thing.  If you are using SUSv3 names in your program you
> should change them.

Ah, if only this were the case. Look at your favorite crappy C library
(glibc comes to mind) and then tell me the only conflicts are names
that appear in SUSv3. :))

Even if this were the case, there is NO REASON to avoid using names
from SUSv3 as static symbols in a module as long as that module has
nothing to do with the system components in which the name is used.

> >For example: in another project I work on, we use the name open() as a
> >static, module-internal symbol for many modules, and export it via a
> >struct full of function pointers.
> 
> Which is just going to confuse a new programmer using your code or make
> it difficult to re-use that code in any project using open().

Not at all. The code can be reused just fine as long as it's left in
its own translation unit where it belongs. Converting static functions
to external linkage is _not_ proper reuse.

> >It's not the responsibility of an author to make sure
> >their static symbols do not conflict with unrelated system headers
> >which they do not use.
> 
> It isn't hard, there are advantages, and nothing good comes from using 
> standard
> function names in other ways.

It finds bugs in compilers and library implementations. This is good.

Actual cases that happened recently: MSVC user complained about a
_local_ variable named "time" in a function. Apparently MSVC refused
to compile this even though time.h was not included. User trying to
compile our software on broken compiler should complain to the
compiler vendor, not to us.

Second case: MSVC user complained about struct member named "near"
(not quite the same issue but similar). We told them the same thing,
complain to compiler vendor or add -Dnear=msvc_sucks_near.

> Including all the header files
> makes it easier to find these conflicts, since the compiler will help you.

No, it masks bugs in the implementation since you get errors when
there is nothing wrong.

Rich




More information about the busybox mailing list