Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #42821 > unrolled thread

Meta-C question about header order

Started byJens Schweikhardt <usenet@schweikhardt.net>
First post2014-04-12 19:37 +0000
Last post2014-06-10 09:40 -0700
Articles 9 on this page of 69 — 15 participants

Back to article view | Back to comp.lang.c


Contents

  Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-12 19:37 +0000
    Re: Meta-C question about header order Keith Thompson <kst-u@mib.org> - 2014-04-12 13:51 -0700
      Re: Meta-C question about header order glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-04-13 00:11 +0000
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:40 +0000
        Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-13 13:10 +0100
        Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-13 06:29 -0700
        Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 14:41 +0000
      Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:36 -0400
    Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-12 16:58 -0400
      Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 03:40 +0000
        Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-13 16:26 +1200
          Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 05:02 +0000
            Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-13 17:21 +1200
              Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:59 -0400
              Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 11:02 -0400
            Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:59 -0400
              Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 08:26 -0700
              Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-15 15:56 +0000
        Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:34 +0000
        Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-13 15:04 -0400
        Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:52 -0400
    Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-13 11:09 +1200
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:47 +0000
        Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-14 08:54 +1200
          Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 21:37 +0000
            Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-14 09:49 +1200
          Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-14 19:17 +0000
            Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-15 10:24 +1200
              Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-16 19:58 +0000
            Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-14 21:45 -0400
    Re: Meta-C question about header order luser- -droog <luser.droog@gmail.com> - 2014-04-12 16:48 -0700
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:52 +0000
    Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 01:04 +0000
    Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-13 10:15 +0100
      Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-13 04:06 -0700
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 12:01 +0000
        Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-13 13:46 +0100
          Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 13:58 +0000
    Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:29 +0000
      Re: Meta-C question about header order Martin Shobe <martin.shobe@yahoo.com> - 2014-04-13 08:48 -0500
        Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 14:25 +0000
          Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 15:02 +0000
          Re: Meta-C question about header order Martin Shobe <martin.shobe@yahoo.com> - 2014-04-13 21:45 -0500
            Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-14 01:16 -0700
              Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-14 10:16 +0100
              Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-14 21:33 -0400
            Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-14 16:25 +0000
              Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-14 09:47 -0700
              Re: Meta-C question about header order Martin Shobe <martin.shobe@yahoo.com> - 2014-04-14 13:29 -0500
                Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-14 19:31 +0000
                  Re: Meta-C question about header order Les Cargill <lcargill99@comcast.com> - 2014-04-14 20:03 -0500
                    Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-15 01:04 +0000
                Re: Meta-C question about header order Keith Thompson <kst-u@mib.org> - 2014-04-14 15:15 -0700
              Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-14 22:01 -0400
              Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-15 09:51 +0100
                Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 06:01 -0700
                  Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-15 14:29 +0100
                    Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 10:38 -0700
                    Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-15 18:27 +0000
                      Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 12:45 -0700
                        Re: Meta-C question about header order ralph <nt_consulting@yahoo.com> - 2014-04-15 22:02 -0500
            Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-14 17:44 +0000
    Re: Meta-C question about header order Tim Rentsch <txr@alumni.caltech.edu> - 2014-04-19 01:25 -0700
      Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-19 10:30 -0400
        Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-23 19:47 +0000
          Re: Meta-C question about header order James Kuyper <jameskuyper@verizon.net> - 2014-04-23 15:53 -0400
        Re: Meta-C question about header order Tim Rentsch <txr@alumni.caltech.edu> - 2014-06-10 09:25 -0700
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-23 19:27 +0000
        Re: Meta-C question about header order Tim Rentsch <txr@alumni.caltech.edu> - 2014-06-10 09:40 -0700

Page 4 of 4 — ← Prev page 1 2 3 [4]


#43003

Fromralph <nt_consulting@yahoo.com>
Date2014-04-15 22:02 -0500
Message-ID<s0rrk9tdbv5750ev24gaeh25gj9kan9tee@4ax.com>
In reply to#42991
On 15 Apr 2014 19:53:04 GMT, ram@zedat.fu-berlin.de (Stefan Ram)
wrote:

>Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>>Unfortunately MS Visual Studio creates massive precompiled header files.
>
>  I think this is the preset, so that it will not compile
>  standard C or C++ source code out of the box IIRC. First,
>  one has to change the compiler settings not to use precompiled
>  header files.

Also of minor note that precompile keys off the stdafx.h/c/cpp files -
in that everything up to and including may be precompiled - anything
following may not. Thus a general default is that
"system-implementation" files will be precompiled and project-specific
headers will not. Individual programmers have multiple options to
manage for what and when "precompile" is invoked.

This is a very broad description. Just thought I would highlight that
precompiled headers was not an "All or Nothing" proposition, but a
flexible development tool.

-ralph

[toc] | [prev] | [next] | [standalone]


#42901

FromJens Schweikhardt <usenet@schweikhardt.net>
Date2014-04-14 17:44 +0000
Message-ID<br2l3kF8uajU1@mid.individual.net>
In reply to#42892
Martin Shobe <martin.shobe@yahoo.com> wrote
	in <lifi4h$3fe$1@dont-email.me>:
# On 4/13/2014 9:25 AM, Jens Schweikhardt wrote:
#> Martin Shobe <martin.shobe@yahoo.com> wrote
#>       in <lie4jc$2r1$1@dont-email.me>:
#> ...
#> # The problem is the dependencies are still that big, messy, uglier than
#> # hell graph doxygen generated.
#>
#> No, they aren't. The dependencies are directed *acyclic* graphs. Before,
#> they contained cycles since with the include guards, a.h can include b.h
#> and b.h can include a.h without an actual cycle emerging. But both
#> directions must appear as edges in the graph for each header might be
#> included in isolation. Cycles are impossible by design under the
#> "headers don't include headers" rule.
# 
# There is such a thing as a circular dependency.

No, not in any meaningful (for the C compiler) way. But maybe I'm
misunderstanding your point. Could you give an example of a circular
dependency?

# Your rule won't change 
# that fact at all. Neither does it change anything about what information 
# any part of the code needs to be compiled correctly. All you are 
# changing the one responsible for providing that information.
# 
#> # That graph now has to be kept in the heads
#> # of each and every developer. Really, really, really, ..., ugly!
#>
#> Why in the heads? If you forget one, the compiler tells you
#> "foo_t undeclared" and you include the header with typedef foo_t
#> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)
# 
# Yes, and the developers need to remember where foo_t is declared. 

Of course. Any SW engineer worth a bean uses ctags or whatever his
IDE provides. That's not a burden.

Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)

[toc] | [prev] | [next] | [standalone]


#43115

FromTim Rentsch <txr@alumni.caltech.edu>
Date2014-04-19 01:25 -0700
Message-ID<kfnbnvxlo8w.fsf@x-alumni2.alumni.caltech.edu>
In reply to#42821
Jens Schweikhardt <usenet@schweikhardt.net> writes:

> consider a small project of 100 C source and 100 header files.
> The coding rules require that only C files include headers,
> headers are not allowed to include other headers (not sure if
> this is 100% the "IWYU - Include What You Use" paradigma).
>
> The headers contain only what headers should contain:
> prototypes, typedefs, declarations, macro definitions.
>
> The problem:  given a set of headers, determine a sequence of
> #include directives that avoids syntax errors due to undeclared
> identifiers.  I.e. if "foo.h" declares type foo_t and "bar.h" uses
> foo_t in a prototype, "bar.h" must be included before "foo.h".

I have been reading the many comments in this thread with some
interest.  Reading through your responses, I have come up with
this summary of motivations for using this approach (these are
my paraphrasings, often not quotes of the originals):

  + no lint warnings about repeated headers
  + no need for include guards
  + doxygen dependency graph much simpler
  + no cycles in include graph
  + removing unneeded includes is easier
  + simpler compiler diagnostics
  + easier to generate dependency makefile
  + improved identifiability of refactoring opportunities
  + ... and of interface accumulation [not sure what this means]
  + ... and of code collecting fat
  + constant reminders of all dependencies of each .c file

Some questions:

  1. Is this an accurate summary?

  2. Has anything been left out (ie, is there any other
     positive you would add to the list)?

  3. Would you mind listing these from most important
     to least important, and giving some indication of
     relative weight for each item?

> I'm not a computer scientist, but it sounds as if this requires a
> topological sort of all the '"foo.h" needs "bar.h"' relations.
> Now the interesting part is:  how to automate this, i.e. how to
> determine "this header declares identifiers A, B, C and requires
> X, Y, Z"?  [IWYU by google was looked at but seems not a good
> solution]

Yes, a topological sort.  The topological sort is the easy
part - the harder part is identifying what the first-level
dependencies are.

> Can you think of a lightweight way to solve this?  Maybe using
> perl, the unix tool box, make, gmake, gcc, a C lexer?

I may have some suggestions here, but first I would like to read
through responses to the questions asked above, to make sure I'm
going in a good direction.

[toc] | [prev] | [next] | [standalone]


#43124

FromRichard Damon <Richard@Damon-Family.org>
Date2014-04-19 10:30 -0400
Message-ID<JLv4v.45915$S85.11888@en-nntp-16.dc1.easynews.com>
In reply to#43115
On 4/19/14, 4:25 AM, Tim Rentsch wrote:
> Jens Schweikhardt <usenet@schweikhardt.net> writes:
 I have been reading the many comments in this thread with some
> interest.  Reading through your responses, I have come up with
> this summary of motivations for using this approach (these are
> my paraphrasings, often not quotes of the originals):
> 
>   + no lint warnings about repeated headers

>   + no need for include guards

>   + doxygen dependency graph much simpler
I am not sure I would call a "flat" graph simpler. It obscures the
difference between what you actually reference and what has been pulled
in due to implementation detail of something you reference.

>   + no cycles in include graph
Neither method will generated cycles. What becomes a "cycle" in nested
includes becomes a broken topographical order (a.h must be before b.h,
but b.h also must be before a.h)

>   + removing unneeded includes is easier
I disagree here, with headers include what they need, you need to only
look at one file to see what is needed, so if you make a change, you
have less to look at to see what is no longer needed. With all
dependencies, both direct and indirect, expressed in the .c file, to
identify that a header is no longer needed you need to look at every
header file included after it to confirm. Also, if you make a change in
a header, you need to know every client for that header, to know where
you need to make the changes.

>   + simpler compiler diagnostics
Yes, you get simpler diagnostics, but a lot more of them (or a lot more
work to avoid them). If headers include what they need, you don't need
to look at the include trace, if foo.h has a error because it is missing
a dependency, it doesn't matter how it got included, it needs to resolve
it, once. In the .c includes everything case, every file that included
that header will need to have the needed dependency fixed.

>   + easier to generate dependency makefile
Yes, if you are manually generating makefiles.

>   + improved identifiability of refactoring opportunities
I disagree. Since you have lost all the real dependency information, you
have lost the hints that help you see the refactoring.

>   + ... and of interface accumulation [not sure what this means]
>   + ... and of code collecting fat
>   + constant reminders of all dependencies of each .c file
> 
> 

Ultimately, it is the programmer putting effort in to make the computer
jobs easier. The biggest advantage it gains is that for a naive
compiler, that doesn't recognize include guards, it will reparse
multiply included files (looking for the #endif). This can be fixed in
the most used headers by making the include itself conditional testing
the include guard.

The main purpose we use computers is that they can do work much faster
than us, and there job is to take away the mechanical operations so we
can focus on the creative. This "rule" puts back on the programmer a lot
of mechanical operations that belong really to the computer.

It works best on smaller projects, where it might be expected that the
programmer can keep more of the interdependencies in his head, but those
don't gain benefit from it. The main cases where it is claimed it helps
are for the gigantic projects with very long build times, but in this
case, the programmer is going to need help keeping track of the
dependencies.

[toc] | [prev] | [next] | [standalone]


#43455

FromJens Schweikhardt <usenet@schweikhardt.net>
Date2014-04-23 19:47 +0000
Message-ID<brqjm9Fa4lcU2@mid.individual.net>
In reply to#43124
Richard Damon <Richard@damon-family.org> wrote
	in <JLv4v.45915$S85.11888@en-nntp-16.dc1.easynews.com>:
# On 4/19/14, 4:25 AM, Tim Rentsch wrote:
#> Jens Schweikhardt <usenet@schweikhardt.net> writes:
# I have been reading the many comments in this thread with some
#> interest.  Reading through your responses, I have come up with
#> this summary of motivations for using this approach (these are
#> my paraphrasings, often not quotes of the originals):
#> 
#>   + no lint warnings about repeated headers
# 
#>   + no need for include guards
# 
#>   + doxygen dependency graph much simpler
# I am not sure I would call a "flat" graph simpler. It obscures the
# difference between what you actually reference and what has been pulled
# in due to implementation detail of something you reference.

You can't see this in a graph of 20 nodes with 40 edges either.
I understand the graph with a root and 20 leaves.

#>   + no cycles in include graph
# Neither method will generated cycles. What becomes a "cycle" in nested
# includes becomes a broken topographical order (a.h must be before b.h,
# but b.h also must be before a.h)

The cycles I mean a closed loops of edges via one or more nodes.

#>   + removing unneeded includes is easier
# I disagree here, with headers include what they need, you need to only
# look at one file to see what is needed, so if you make a change, you
# have less to look at to see what is no longer needed. With all
# dependencies, both direct and indirect, expressed in the .c file, to
# identify that a header is no longer needed you need to look at every
# header file included after it to confirm. Also, if you make a change in
# a header, you need to know every client for that header, to know where
# you need to make the changes.

Well, I use a tool (Gimpel FlexeLint) to tell me which headers are
not needed. That is at least simple for me. However, FlexeLint can
tell this only for a C file, not for headers.

#>   + simpler compiler diagnostics
# Yes, you get simpler diagnostics, but a lot more of them (or a lot more
# work to avoid them). If headers include what they need, you don't need
# to look at the include trace, if foo.h has a error because it is missing
# a dependency, it doesn't matter how it got included, it needs to resolve
# it, once. In the .c includes everything case, every file that included
# that header will need to have the needed dependency fixed.
# 
#>   + easier to generate dependency makefile
# Yes, if you are manually generating makefiles.
# 
#>   + improved identifiability of refactoring opportunities
# I disagree. Since you have lost all the real dependency information, you
# have lost the hints that help you see the refactoring.

See my answer to Tim Rentsch for details of what I expect to find and how.

...
# Ultimately, it is the programmer putting effort in to make the computer
# jobs easier. The biggest advantage it gains is that for a naive
# compiler, that doesn't recognize include guards, it will reparse
# multiply included files (looking for the #endif). This can be fixed in
# the most used headers by making the include itself conditional testing
# the include guard.

Which nobody does. Having the include guard *in* the included header
instead of some intelligence in the preprocessor is the ugly kluge.
Have you ever seen

    #ifndef PROJECT_TYPES_H
    #include "project_types.h"
    #endif
    ...repeat for N other headers...

out in the wild? I haven't. So the common wisdom accepts endless
rereading and retokenization of the same headers in the header djungle.
I question the status quo in search of a paradigm shift. Big words :-)

# The main purpose we use computers is that they can do work much faster
# than us, and there job is to take away the mechanical operations so we
# can focus on the creative. This "rule" puts back on the programmer a lot
# of mechanical operations that belong really to the computer.

I believe this burden is quite lightweight. You get the header sequence
right once, that's basically it. I provide a reference in a dummy C file
including all headers with an empty main()). Look up where your header
appears in the reference sequence--no more guessing or compiler errors.

Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)

[toc] | [prev] | [next] | [standalone]


#43457

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-04-23 15:53 -0400
Message-ID<53581A45.7090105@verizon.net>
In reply to#43455
On 04/23/2014 03:47 PM, Jens Schweikhardt wrote:
...
> Well, I use a tool (Gimpel FlexeLint) to tell me which headers are
> not needed. That is at least simple for me. However, FlexeLint can
> tell this only for a C file, not for headers.

test_header.c:
#include "header.h"
int dummy=0; // to silences some compiler warning messages.

[toc] | [prev] | [next] | [standalone]


#45761

FromTim Rentsch <txr@alumni.caltech.edu>
Date2014-06-10 09:25 -0700
Message-ID<kfnbnu0spdd.fsf@x-alumni2.alumni.caltech.edu>
In reply to#43124
Richard Damon <Richard@Damon-Family.org> writes:

> On 4/19/14, 4:25 AM, Tim Rentsch wrote:
>> Jens Schweikhardt <usenet@schweikhardt.net> writes:
>  I have been reading the many comments in this thread with some
>> interest.  Reading through your responses, I have come up with
>> this summary of motivations for using this approach (these are
>> my paraphrasings, often not quotes of the originals):
>> 
>>   + no lint warnings about repeated headers
>>
>>   + no need for include guards
>>
>>   + doxygen dependency graph much simpler
>
> [..several point by point responses..]

I think you may have misunderstood my intentions there.  I wasn't
trying to agree with his points, just restate them to make sure
I understood his position and didn't leave out anything.  It was
useful to see his reply, much moreso I think than if I had started
by arguing against the scheme proposed.

[toc] | [prev] | [next] | [standalone]


#43454

FromJens Schweikhardt <usenet@schweikhardt.net>
Date2014-04-23 19:27 +0000
Message-ID<brqignFa4lcU1@mid.individual.net>
In reply to#43115
Tim Rentsch <txr@alumni.caltech.edu> wrote
	in <kfnbnvxlo8w.fsf@x-alumni2.alumni.caltech.edu>:
# Jens Schweikhardt <usenet@schweikhardt.net> writes:
# 
#> consider a small project of 100 C source and 100 header files.
#> The coding rules require that only C files include headers,
#> headers are not allowed to include other headers (not sure if
#> this is 100% the "IWYU - Include What You Use" paradigma).
#>
#> The headers contain only what headers should contain:
#> prototypes, typedefs, declarations, macro definitions.
#>
#> The problem:  given a set of headers, determine a sequence of
#> #include directives that avoids syntax errors due to undeclared
#> identifiers.  I.e. if "foo.h" declares type foo_t and "bar.h" uses
#> foo_t in a prototype, "bar.h" must be included before "foo.h".
# 
# I have been reading the many comments in this thread with some
# interest.  Reading through your responses, I have come up with
# this summary of motivations for using this approach (these are
# my paraphrasings, often not quotes of the originals):
# 
#  + no lint warnings about repeated headers
#  + no need for include guards
#  + doxygen dependency graph much simpler
#  + no cycles in include graph
#  + removing unneeded includes is easier
#  + simpler compiler diagnostics
#  + easier to generate dependency makefile
#  + improved identifiability of refactoring opportunities
#  + ... and of interface accumulation [not sure what this means]
#  + ... and of code collecting fat
#  + constant reminders of all dependencies of each .c file

Thanks Tim, for taking the time. To expand on interface accumulation:
the process where interface A needs another, which then grows the need
for yet another and eventually includes half the total number of
interfaces of the project.

Lets face it: programmers are lazy, and its too easy in C to blow up an
initially small interface design by writing another #include in the
first header that looks like it's included by "most" of the files where
it is needed and include it directly where not. How many projects have
you seen with project_types.h, misc.h, macros.h, and such headers
invented on the spot.


# Some questions:
# 
#  1. Is this an accurate summary?
# 
#  2. Has anything been left out (ie, is there any other
#     positive you would add to the list)?

+ Reduced processing time by all the tools that operate on
  C source. That's the compiler of course, but also lint,
  auto dependency generators, static checkers, doxygen, ...
  For each translation unit, the headers are tokenized and
  parsed at most once (not at all when in an disabled #ifdef).
  I observe 20% in our project.

+ Giving developers a hard and fast unambiguous rule in which file the
  include directives go. There is only one choice. If foo.c needs the
  bar_t declaration from bar.h, it gets included. Contrast this with
  "traditional wisdom", where possibly a large number of headers would be
  candidates for the new #include statement. A good design would make this
  choice obvious, a bright developer would know the state of the art, but
  it's a rare trait. "Indented six feet down and covered with dirt" is the
  reality out there. Yes, this requires selection of the proper *line*
  among the includes. But *any* compiler will tell in no uncertain words
  if that was the wrong line or you're missing another header. It's fool
  proof.

#  3. Would you mind listing these from most important
#     to least important, and giving some indication of
#     relative weight for each item?

  + improved identifiability of refactoring opportunities
    $ grep -c '#include "foo.h"' */*.c
    Whoa! foo.h is included by 95% of files, why?
    Whoa! foo.h is included by one file only. Maybe incorporate it.
    Hmm. All foo.h require bar.h, baz.h and blurb.h. Could I
    encapsulate this better? Maybe merge some headers?
    (50 points)
  + ... and of interface accumulation
    $ grep -c '#include' */*.c
    Whoa! big.c includes everything and the kitchen sink. What's up?
    (30 points)
  + ... and of code collecting fat - optional debug code in #ifdef maze.
    Should be moved out to separate object files, linked in when needed.
    (20 points)
  + doxygen dependency graph much simpler. It's a document for
    the customer.
    (20 points)
  + removing unneeded includes is easier
    (20 points)
  + constant reminders of all dependencies of each .c file
    (10 points)
  + no cycles in include graph
    (10 points)
  + giving developers a fast rule in what file the include goes.
    (10 points)
  + reduced processing time by all the tools that operate on source
    (10 points)
  + no lint warnings about repeated headers
    (10 points)
  + easier to generate dependency makefile
    (7 points)
  + no need for include guards
    (5 points)
  + simpler compiler diagnostics
    (5 points)

The overall goal is to make emerging complexity stand out the moment it
emerges, opening developers eyes. The reality in any random project is:
not all developers are stellar C programmers (the set of participants in
this newsgroup then and now looks like an accurate statistical sample.
From Tanmoy to Bill...)

Unfortunately, the C preprocessor is a deceptive tool (apologies to dmr,
may his soul rest in peace, I know why it was needed in the time back
then) and gets frequently abused. Taming it is probably what I'm after.
The only reason cpp has survived is because of the include guard kluge.
Making interfaces stand out, both in number and circumference, should
help, I hope.

[...]
#> Can you think of a lightweight way to solve this?  Maybe using
#> perl, the unix tool box, make, gmake, gcc, a C lexer?
# 
# I may have some suggestions here, but first I would like to read
# through responses to the questions asked above, to make sure I'm
# going in a good direction.

This is certainly incomplete:
One would need to find the identifiers of macro definitions (easy)
and typedefs (harder). In prototypes one must distinguish between
types and optional parameter names.
In other declarations one needs to determine the declared identifier.
This is a little more involved for enums and aggregates.
Build the "needed by" pairs and pipe to tsort(1). VoilĂ !
Version 7 came with all the goodies built in, didn't it?


Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)

[toc] | [prev] | [next] | [standalone]


#45762

FromTim Rentsch <txr@alumni.caltech.edu>
Date2014-06-10 09:40 -0700
Message-ID<kfn4mzssopb.fsf@x-alumni2.alumni.caltech.edu>
In reply to#43454
Jens Schweikhardt <usenet@schweikhardt.net> writes:

> Tim Rentsch <txr@alumni.caltech.edu> wrote
> 	in <kfnbnvxlo8w.fsf@x-alumni2.alumni.caltech.edu>:
> # Jens Schweikhardt <usenet@schweikhardt.net> writes:
> # 
> #> consider a small project of 100 C source and 100 header files.
> #> The coding rules require that only C files include headers,
> #> headers are not allowed to include other headers (not sure if
> #> this is 100% the "IWYU - Include What You Use" paradigma).
> #>
> #> The headers contain only what headers should contain:
> #> prototypes, typedefs, declarations, macro definitions.
> #>
> #> The problem:  given a set of headers, determine a sequence of
> #> #include directives that avoids syntax errors due to undeclared
> #> identifiers.  I.e. if "foo.h" declares type foo_t and "bar.h" uses
> #> foo_t in a prototype, "bar.h" must be included before "foo.h".
> # 
> # I have been reading the many comments in this thread with some
> # interest.  Reading through your responses, I have come up with
> # this summary of motivations for using this approach (these are
> # my paraphrasings, often not quotes of the originals):
> # 
> #  + no lint warnings about repeated headers
> #  + no need for include guards
> #  + doxygen dependency graph much simpler
> #  + no cycles in include graph
> #  + removing unneeded includes is easier
> #  + simpler compiler diagnostics
> #  + easier to generate dependency makefile
> #  + improved identifiability of refactoring opportunities
> #  + ... and of interface accumulation [not sure what this means]
> #  + ... and of code collecting fat
> #  + constant reminders of all dependencies of each .c file
>
> Thanks Tim, for taking the time.  [snip]

Thank you for the extended reply.  Reading through it, I
don't find any of your arguments convincing.  In almost all
cases they either mischaracterize one of the two positions
or make use of a non-logical inference.  It isn't necessary
to use the scheme you propose to get the benefits you say
are important, and it's significantly more work for developers,
starting with having to build a tool that will produce the
necessary include ordering.  By contrast, following the more usual
rule that include files will #include any other header directly
necessary for themselves, I did a little scripting in my regular
development environment to produce a list of include files used
by each .c file.  It took 10 or 15 minutes.  The arguments you
give just don't make your case.

[toc] | [prev] | [standalone]


Page 4 of 4 — ← Prev page 1 2 3 [4]

Back to top | Article view | comp.lang.c


csiph-web