samperi@marob.MASA.COM (Dominick Samperi) (02/26/89)
Are recursive #includes hazardous to your software's health? I'm working on a system where each header file has the form: <contents of foo.h>: #ifndef H_FOO #define H_FOO defines, declarations, etc. #endif This scheme permits header files to be included two or more times, even recursively, where the second and subsequent includes of the same file will have no effect. (That is, a header file A can include another header file B, which in turn includes A, but since H_A will be defined when A is included the first time, the second include of A will have no effect, and the recursion will end.) Although this trick will avoid the common problems caused by including a header file more than once, I suspect that it will also encourage the inclusion of files that are not even needed (since there is no chance for multiple definitions, if there is some chance that the definitions may be needed, what the heck). Furthermore, permitting recursive includes may tend to smear the separation between modular components of the software system, and designing a correct makefile will be a mess. These problems, together with the discovery that some preprocessors consider any recursive include to be a fatal error, have motivated me to discontinue the use of this trick, and discontinue the use of recursive includes as well. Perhaps others could comment on this. -- Dominick Samperi -- ESCC samperi@marob.masa.com uunet!hombre!samperi
hans@nlgvax.UUCP (Hans Zuidam) (02/27/89)
Commodore uses the same scheme for their include files for the Amiga software and it is a blessing. This way I (the user) never have to deal with multiple includes. Commodore has extended the above a little: #ifndef EXEC_TASKS_H #define EXEC_TASKS_H #ifndef EXEC_NODES_H #include <exec/nodes.h> #endif !EXEC_NODES_H #ifndef EXEC_LISTS #include <exec/lists.h> #endif !EXEC_LISTS ... Stuff here ... #endif !EXEC_TASKS_H The include files are distributed over several related directories ("exec", "graphics", "devices" and what not). Furthermore the header files include what they themselves need. This is as it should be. On BSD you reguarly have to include files that your program do not need but files included do need. See for example the files in "net". If you try to compile a file which only includes <net/if.h> you will get a nice bunch of errors, and you will be left completely blank as to what to include also. Or said different: I have to figure out what someone already figured out before me (the BSD networking software does work ;-)). Include files should be as much self contained as possible. They are in many cases an interface between a pieces of code. A good test is that you should be able to take a single include file and compile it without errors. With respect to Makefile dependencies: use makedepend and you will not have troubles there. The method above even lets you build a dependency list by hand *quickly*. -- Hans Zuidam E-Mail: hans@pcg.philips.nl Philips Telecommunications and Data Systems, Tel: +31 40 892288 Project Centre Geldrop, Building XR Willem Alexanderlaan 7B, 5664 AN Geldrop The Netherlands
psrc@pegasus.ATT.COM (Paul S. R. Chisholm) (02/27/89)
In article <570@marob.MASA.COM>, samperi@marob.MASA.COM (Dominick Samperi) writes: > <contents of foo.h>: > > #ifndef H_FOO > #define H_FOO >...stuff... > #endif This issue was beaten to death a few weeks ago in the comp.lang.c++ news group. The obvious proposal is to not #include a file that's already been #included, even if you see a second (or third, or forty- second) #include for it. This would also be more efficient that what you suggest above, since the file doesn't even need to be opened again, let alone read. Unfortunately, it can break existing C code. We had such a cpp (back in the bad old days of Net 1000, a large development project). People tended to #include the whole world, just in case; but it did speed up compilation quite a bit (we had lots of big header files). The C++ header files I've seen do things like #ifndef STDIO_H, as you suggest above. It may not the best solution, but it works. For more information, look at old comp.lang.c++ articles (no, I don't know of any place that archives them). >Dominick Samperi -- ESCC, samperi@marob.masa.com, uunet!hombre!samperi Paul S. R. Chisholm, AT&T Bell Laboratories, att!pegasus!psrc psrc@pegasus.att.com, AT&T Mail !psrchisholm I'm not speaking for the company, I'm just speaking my mind.
coggins@coggins.cs.unc.edu (Dr. James Coggins) (02/27/89)
In article <2630@pegasus.ATT.COM> psrc@pegasus.ATT.COM (Paul S. R. Chisholm) writes: > >This issue was beaten to death a few weeks ago in the comp.lang.c++ >news group. The obvious proposal is to not #include a file that's >already been #included, even if you see a second (or third, or forty- >second) #include for it. > >Paul S. R. Chisholm, AT&T Bell Laboratories, att!pegasus!psrc I was one of the principal beaters of this topic. My net postings have been cleaned up, enhanced, and submitted to SIGPLAN Notices (no idea yet on publication date). They are also available as a technical report from my department's SoftLab (software research laboratory). You can either watch SIGPLAN for J. Coggins and G. Bollella, "Managing C++ Libraries" or e-mail for a copy of our technical report (which will soon include an addendum with some further techniques) to Pam Payne, Softlab Coordinator at softlab@cs.unc.edu or to the address below. The organization scheme I descibed requires no preprocessor hacks, includes headers once and once only, imposes minimally on the program development process, and is still working well with VERY little maintenance required. In fact, we have extended it recently to handle compilations of my research library for multiple architectures (Sun3, Sun4, Vax780) and are preparing to incorporate RCS support directly into the management structure. (These points will be described in the addendum to the SoftLab TR). USmail for the tech report: Pam Payne, SoftLab Coordinator Computer Science Department CB#3175 University of North Carolina Chapel Hill, NC 27599-3175 --------------------------------------------------------------------- Dr. James M. Coggins coggins@cs.unc.edu Computer Science Department UNC-Chapel Hill Whaat! is the sound of an issue being Chapel Hill, NC 27514-3175 beaten to death! ---------------------------------------------------------------------
heather@burnett.SEAS.UCLA.EDU (02/28/89)
In article <570@marob.MASA.COM> samperi@marob.MASA.COM (Dominick Samperi) writes: >Are recursive #includes hazardous to your software's health? > > etc... > >definitions may be needed, what the heck). Furthermore, permitting >recursive includes may tend to smear the separation between modular >components of the software system, and designing a correct makefile >will be a mess. > For those that have BSD 4.3 based C compilers, I would like to point out that a recent addition to the C preprocessor enables the preprocessor to generate a dependancy list that can be included in a Makefile. Since the C preprocessor had to parse #include directives anyway (and it does this recursively), adding an option (-M) to simply parse #includes and spit them out wasn't difficult. For those of you unlucky enough not to have this tool, here's something to look forward to (and it's actually pretty easy to write something that will do this for you in the meantime). Heather Burris, UCLA
jbn@glacier.STANFORD.EDU (John B. Nagle) (02/28/89)
In article <2630@pegasus.ATT.COM> psrc@pegasus.ATT.COM (Paul S. R. Chisholm) writes: >In article <570@marob.MASA.COM>, samperi@marob.MASA.COM (Dominick Samperi) writes: >> <contents of foo.h>: >> >> #ifndef H_FOO >> #define H_FOO >>...stuff... >> #endif It does add to your compile times, since the entire file you're not including has to be read and parsed. I support the idea that #include should not include files "already included". The exact semantics of this need to be carefully defined, so that it's well-defined whether #include <stdio.h> and "#include "stdio.h" are considered to be identical, and the implications of pathnames need to be thought out. But it's a good idea. Given this, it would be normal for all .h files to contain includes for any .h files they require, and creators of .c files could totally ignore the internal dependency problems of the library. For those rare situations when you really want to insert a file more than once, a new command, perhaps "#insert" should be defined.
djones@megatest.UUCP (Dave Jones) (02/28/89)
From article <570@marob.MASA.COM), by samperi@marob.MASA.COM (Dominick Samperi): ) Are recursive #includes hazardous to your software's health? ) ) I'm working on a system where each header file has the form: ) ) <contents of foo.h): ) ) #ifndef H_FOO ) #define H_FOO ) ) defines, declarations, etc. ) ) #endif ) It is very hazardous to your health. If you write recursively nested include-files, you can work yourself into all sorts of quandries if things get a little messed up. (I speak from experience.) The reason for the #ifndef is not for recursively defined headers. (Use undeclared struct-this and struct-that for forward references.) It is to let you include that include-file without worrying about whether some other include-file has already included it. (There are some who reject includes in includes, for this very reason, but that's a different holy war.) So.... do this instead: #ifndef H_FOO defines, declarations, etc. #define H_FOO #endif This allows you to include an include-file twice, but not recursively.
jef@ace.ee.lbl.gov (Jef Poskanzer) (02/28/89)
In the referenced message, jbn@glacier.UUCP (John B. Nagle) wrote: }>> #ifndef H_FOO }>> #define H_FOO }>>...stuff... }>> #endif } } It does add to your compile times, since the entire file you're not }including has to be read and parsed. Read, yes; parsed, no. You would be surprised at how few cycles are used in reading an include file and just handling the #ifs. On a Sun 3/260: stdio.h's user system elapsed 1 0.6 0.4 5 delta 6.3 1.5 7 501 6.9 1.9 12 delta 6.5 1.3 7 1001 13.4 3.2 19 delta 6.7 1.0 10 1501 20.1 4.2 29 Looks to me like handling a stdio-sized include file for a second time costs about 0.013 user, 0.003 system, and 0.015 elapsed. I think I can live with that, especially considering the minutes to hours of my time that the current idiotic #include scheme wastes each time I need to figure out what files to include. I argued this issue a few years ago when I was working at UniSoft. I provided data similar to the above, and assumed that the benefits of including only the files you explicitly reference would be obvious to all. Sadly, I was ignored. --- Jef Jef Poskanzer jef@helios.ee.lbl.gov ...well!pokey In Stereo (where available)
billwolf@hubcap.clemson.edu (William Thomas Wolfe,2847,) (02/28/89)
From article <2532@goofy.megatest.UUCP>, by djones@megatest.UUCP (Dave Jones):
> ) Are recursive #includes hazardous to your software's health?
Could we move this discussion to comp.lang.c, please?