ellis@ultra.dec.com (David Ellis 15-Nov-1990 0915) (11/15/90)
Consider a Makefile for an executable built from a large number of .o files, each separately compiled from a .c file. If we use a single .c.o rule for compiling all the source files, then it seems that a change in a .h file that is #include'd in a .c file will not be picked up by Make to automatically force recompilation of the .c file. One workaround is to replace the single .c.o rule with a collection of rules, one for each .o file, listing the dependencies on the .h files #include'd in the corresponding .c file. But this is a lot of writing, and if we change the "#include" lines in any .c file, we have to update the Makefile with the corresponding change. Is there a simpler way? ---- David J Ellis Digital Equipment Corporation, Secure Systems Group Mailstop LTN1-1/D07 295 Foster Street, Littleton MA 01460 (508) 486-6157 Usenet: {ucbvax,allegra,decvax}!decwrl!ultra.enet!ellis Internet: ellis@ultra.enet.dec.com
jik@athena.mit.edu (Jonathan I. Kamens) (11/16/90)
The somewhat standard solution to this problem is to create a program or sequence of shell commands to parse the source files and determine the dependencies on .h files, and to append those dependencies to the end of the Makefile (or, in some versions of make, to put them in a file that is included by the Makefile). There are various "makedepend" programs and scripts floating all over the place. The standard X11 distribution includes a makedepend, for example. Also, I believe there are a few Makefiles in the standard 4.3BSD distribution that have shell dependency generators based on "cc -E" on the source files built in. There may even be some stuff in the comp.sources.unix or comp.sources.misc archives to do this. -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
s887212@minyos.xx.rmit.oz.au (Stephen Riehm [Romulis]) (11/16/90)
jik@athena.mit.edu (Jonathan I. Kamens) writes: > The somewhat standard solution to this problem is to create a program or >sequence of shell commands to parse the source files and determine the >dependencies on .h files, and to append those dependencies to the end of the >Makefile (or, in some versions of make, to put them in a file that is included >by the Makefile). [stuff not saved] >-- >Jonathan Kamens USnail: >MIT Project Athena 11 Ashford Terrace >jik@Athena.MIT.EDU Allston, MA 02134 >Office: 617-253-8085 Home: 617-782-0710 This might be the current "standard method" of getting around this problem.. but wouldn't it be "Better" <totally subjective term> to "modify" make / pmake to accept lines similar to.. .o : .c header.h or maybe some form of wildcard system? Is this concept TOTALLY unrealistic. I have found that most of the programs that I write have only one or two .h files so this sort of structure would be most reasonable for most of my applications. Does this also apply to others or am I on my own on this. Comments welcome by email or news. thanx in advance ============================================================================ Romulis [Stephen Riehm] Royal Melbourne Institute of Technology, (124 Latrobe St., Melbourne.) s887212@minyos.xx.rmit.oz.au Australia. @>---`--,--( Still Stuck on the wrong side of the deep pink sea )--.--'---<@ ======================< Insert Usual Disclaimer >===========================
pmoore@hemel.bull.co.uk (Paul Moore) (11/16/90)
ellis@ultra.dec.com (David Ellis 15-Nov-1990 0915) writes: >Consider a Makefile for an executable built from a large number of .o files, >each separately compiled from a .c file. >If we use a single .c.o rule for compiling all the source files, then it >seems that a change in a .h file that is #include'd in a .c file will >not be picked up by Make to automatically force recompilation of the .c file. >One workaround is to replace the single .c.o rule with a collection of rules, >one for each .o file, listing the dependencies on the .h files #include'd in >the corresponding .c file. But this is a lot of writing, and if we change >the "#include" lines in any .c file, we have to update the Makefile with the >corresponding change. >Is there a simpler way? Yes - the simplest think to do is leave the single rules line in there and then add the dependancy lines after:- .c.o cc ....... foo.o: foo.c inc.h bar.o: bar.c inc.h This says that to make a .o from and .c do a cc on it AND that foo.o depends both on foo.c and inc.h. This works fine. However you must update the make to reflect the changes in dependancy if you add another .h. There are dependancy makers around - ie progs/scripts that scan the sources and build the rules but I have never used them as it seems to me you can keep them up to date by hand. >---- >David J Ellis >Digital Equipment Corporation, Secure Systems Group >Mailstop LTN1-1/D07 >295 Foster Street, Littleton MA 01460 >(508) 486-6157 >Usenet: {ucbvax,allegra,decvax}!decwrl!ultra.enet!ellis >Internet: ellis@ultra.enet.dec.com
mark@hsi86.hsi.com (Mark Sicignano) (11/16/90)
Our cc program has a -M option that prints dependencies on stdout. This output is suitable to be included in a makefile. If I do a cc -M chmod.c This is the output I get: chmod.o: chmod.c chmod.o: /usr/include/stdio.h chmod.o: /usr/include/sys/types.h chmod.o: /usr/include/sys/stat.h chmod.o: /usr/include/sys/dir.h This should get you going in the right direction perhaps. -- Mark Sicignano ...!uunet!hsi!mark 3M Health Information Systems mark@hsi.com
lbr@holos0.uucp (Len Reed) (11/17/90)
In article <9011151442.AA02010@decpa.pa.dec.com> ellis@ultra.dec.com (David Ellis 15-Nov-1990 0915) writes:
=Consider a Makefile for an executable built from a large number of .o files,
=each separately compiled from a .c file.
=
=If we use a single .c.o rule for compiling all the source files, then it
=seems that a change in a .h file that is #include'd in a .c file will
=not be picked up by Make to automatically force recompilation of the .c file.
=
=One workaround is to replace the single .c.o rule with a collection of rules,
=one for each .o file, listing the dependencies on the .h files #include'd in
=the corresponding .c file. But this is a lot of writing, and if we change
=the "#include" lines in any .c file, we have to update the Makefile with the
=corresponding change.
=
=Is there a simpler way?
You don't want a separate rule for each C file, just a separate dependency
line. Like this:
MOST = this.h that.h more.h another.h etc.h
one.o : $(MOST) header_a.h header_b.h
two.o : $(MOST) header_c.h
three.o : $(MOST)
.c.o :
$(CC) $(CFLAGS) $<
The MOST macro is used to group headers that most C files include. You only
have one rule. Note that x.o depends implicitly upon x.c for all x. In
this example the rule is superfluous, since it's just the default.
Now, what about those dependency lines? There are dependency
checkers out there, and for complicated projects using one is far better
than trying to maintain these by hand.
--
Len Reed
Holos Software, Inc.
Voice: (404) 496-1358
UUCP: ...!gatech!holos0!lbr
weimer@ssd.kodak.com (Gary Weimer) (11/17/90)
In article <6268@minyos.xx.rmit.oz.au> s887212@minyos.xx.rmit.oz.au (Stephen Riehm [Romulis]) writes: >jik@athena.mit.edu (Jonathan I. Kamens) writes: > > >> The somewhat standard solution to this problem is to create a program or >>sequence of shell commands to parse the source files and determine the >>dependencies on .h files, and to append those dependencies to the end of the >>Makefile (or, in some versions of make, to put them in a file that is included >>by the Makefile). > >This might be the current "standard method" of getting around this >problem.. but wouldn't it be "Better" <totally subjective term> to "modify" >make / pmake to accept lines similar to.. >.o : .c header.h >or maybe some form of wildcard system? >Is this concept TOTALLY unrealistic. I have found that most of the programs >that I write have only one or two .h files so this sort of structure would >be most reasonable for most of my applications. >Does this also apply to others or am I on my own on this. Does this method imply that all .c files built with this makefile include header.h? This would hardly be practical for large projects. As long as we are modifying make, why not do something a little more robust and automated? SunOS's make has the "special-function target": .KEEP_STATE: which causes make to keep a record (in the file .make.state?) of which include files each .c file uses (amoung other information). When make is invoked after changing only one of these include files, make will catch this and recompile the appropriate .c files. If a .c file is changed, it needs recompiled anyway and a new list of include files is generated. Notice that jnk.c does not get recompiled because header.h was changed if jnk.c does not include it. No tinkering with the makefile is needed when new include files are created, or old ones reorganized. Very clean, very sweet.
rwhite@nusdecs.uucp (0257014-Robert White(140)) (11/17/90)
In article <9011151442.AA02010@decpa.pa.dec.com> ellis@ultra.dec.com (David Ellis 15-Nov-1990 0915) writes: >If we use a single .c.o rule for compiling all the source files, then it >seems that a change in a .h file that is #include'd in a .c file will The simplest thing to do is to take the line someobj.o: someobj.c and turn it into: someobj.o: someobj.c someheader.h When the header is older than the .o then everything is as it should be but when the header is changed the object is out of date wrt the source(s) and it is recompiled. An automatic way to generate this sort of dependancy list is to get make cc output the included file list instead of compiling an object. Take that output and massage it into a dependancy list. Rob.
hsandhu@white.toronto.edu (Harjinder S Sandhu) (11/17/90)
ellis@ultra.dec.com (David Ellis 15-Nov-1990 0915) writes: >If we use a single .c.o rule for compiling all the source files, then it >seems that a change in a .h file that is #include'd in a .c file will >not be picked up by Make to automatically force recompilation of the .c file. >One workaround is to replace the single .c.o rule with a collection of rules, >one for each .o file, listing the dependencies on the .h files #include'd in >the corresponding .c file. But this is a lot of writing, and if we change >the "#include" lines in any .c file, we have to update the Makefile with the >corresponding change. >Is there a simpler way? I do the following to generate my entire makefile note: I have all my .c files in c/ and all .h files in h/ and I put all objects in o/ note 2: I use awk excessively due to the lack of a better output formatter ---------------------------------------- # Find the Source echo SRC | awk '{printf("\n%s= ",$1)}' foreach i (c/*) echo $i | awk '{printf("\\\n\t\t\t%s ", $1) }' end # The objects to compile, echo OBJ | awk '{printf("\n\n%s= ",$1)}' foreach i (c/*) echo $i | awk '{printf("\\\n\t\t\to/%s.o ", substr($1,3,length($1)-4))}' end # The make command, assuming flags and everything are defined already echo " " echo $all': $(OBJ)' echo '$(CC) $(CFLAGS) $(OBJ) -o ' $all '$(LIB) -lm' | \ awk '{printf("\t%s\n",$0)}' echo " " echo '$(OBJ):' echo '$(CC) $(CFLAGS) $(IDIR) -c -o o/$*.o c/$*.c' | \ awk '{printf("\t%s\n",$0)}' echo " " # Generate the dependencies, basically searches .c files for # include statements. If the included files is in quotes, # it is a dependency, otherwise not. egrep include c/* | sed -e "s/#/\ /g" -e s/\"/\ /g | \ awk 'BEGIN {src=" "} \ {sn=substr($1,3,length($1)-5) } \ {if (src!=$1)printf("\n\no/%s.o:\t\tc/%s.c", sn, sn) } \ {src=$1} \ {if (substr($3,1,1)!="<") printf("\t\\\n\t\t\th/%s\t\t",$3) }' -------------------------- Harjinder Sandhu hsandhu@white.toronto.edu --
jik@athena.mit.edu (Jonathan I. Kamens) (11/19/90)
In article <6268@minyos.xx.rmit.oz.au>, s887212@minyos.xx.rmit.oz.au (Stephen Riehm [Romulis]) writes: |> This might be the current "standard method" of getting around this |> problem.. but wouldn't it be "Better" <totally subjective term> to "modify" |> make / pmake to accept lines similar to.. |> .o : .c header.h |> or maybe some form of wildcard system? That's just fine if every one of your source files includes the same header files, but in a large software project, that is almost definitely not the case. Recompiling is a slow process; I want it to take place *only* when necessary, which means that I only want dependencies for each .o file to exist for the actual include files upon which that .o file depends, not for every include file in the software project. Another reason automatically generated dependencies are a good thing is that they do recursive dependency generation. That means that if I include <X11/Xlib.h>, and that file includes <X11/X.h>, then both of those include files will be added as dependencies. Some people see this as a bad thing; they say, "Why should I have to recompile everything if my administrator changes <stdio.h>?" My answer is that if any standard system include file was changed, there's a *reason* for it, and you should be recompiling if for no other reason than to verify that your source code still works with the changed header files. -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
jik@athena.mit.edu (Jonathan I. Kamens) (11/19/90)
In article <1990Nov16.171816.7173@ssd.kodak.com>, weimer@ssd.kodak.com (Gary Weimer) writes: |> SunOS's make has the "special-function target": |> |> .KEEP_STATE: |> |> which causes make to keep a record (in the file .make.state?) of which |> include files each .c file uses (amoung other information). When make |> is invoked after changing only one of these include files, make will |> catch this and recompile the appropriate .c files. If a .c file is |> changed, it needs recompiled anyway and a new list of include files |> is generated. How does the SunOs make figure out which files were included by each source file? Does it do a "cc -E" on the source file, or something similar? If so, isn't that (a) slow since it has to do it again each time the .c file changes, and (b) a problem with source files on which "cc -E" (or whatever command make uses) won't do the right thing? It seems to me that you're introducing a lot of complexity into make, and it isn't clear to me that it can do the job correctly and reliably. -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
ericco@ssl.berkeley.edu (Eric C. Olson) (11/20/90)
Why not compile the object files directly into a compilation dependent library. Like: lib1.a : $(SRC) cc $(CFLAGS1) $? | exit ar a $@ $(?:.c=.o) /bin/rm $(?:.c=.o) lib2.a : $(SRC) cc $(CFLAGS2) $? | exit ar a $@ $(?:.c=.o) /bin/rm $(?:.c=.o) exe1 : main.c lib1.a cc $(LFLAGS) -o $@ main.c lib1.a exe2 : main.c lib2.a cc $(LFLAGS) -o $@ main.c lib2.a If the compilation fails, you may get into trouble, i think the exit will take care of this. In general, in Sun make, this could be: all : exeDEF1 exeDEF2 exeDEF3 lib%.a : $(SRC) cc -c -D% $? | exit ar a $@ $(?:.c=.o) /bin/rm $(?:.c=.o) exe% : main.c lib%.a cc -o $@ main.c lib%.a -- Eric ericco@ssl.berkeley.edu
guy@auspex.auspex.com (Guy Harris) (11/20/90)
> How does the SunOs make figure out which files were included by each source >file? Does it do a "cc -E" on the source file, or something similar? "Something similar". Basically, it provokes the compiler into producing a dependency list as it compiles. >If so, isn't that (a) slow since it has to do it again each time the .c >file changes, Well, if the ".c" file changes, it has to compile it in any case. There is some extra overhead in getting the compiler (in particular, the "C preprocessor" phase of the compiler) to produce the dependency list as it compiles.
jik@athena.mit.edu (Jonathan I. Kamens) (11/20/90)
In article <ERICCO.90Nov19112308@soc1.ssl.berkeley.edu>, ericco@ssl.berkeley.edu (Eric C. Olson) writes: |> Why not compile the object files directly into a compilation dependent |> library. Like: Maybe I'm missing something, but I don't see how this resolves the problem of dependencies on include files. Your answer doesn't seem to have anything at all to do with include files. |> ar a $@ $(?:.c=.o) |> |> lib%.a : $(SRC) What do the "(?:.c=.o)" and "%" do? I can guess given the context, but these are *not* portable Make constructs... -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (11/20/90)
In article <1990Nov18.204706.7044@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes: > How does the SunOs make figure out which files were included by each source > file? Does it do a "cc -E" on the source file, or something similar? I don't know what it actually uses, but cc -M would be one solution. > If so, > isn't that (a) slow since it has to do it again each time the .c file changes, It has to recompile every time the file changes. The extra time is negligible. > and (b) a problem with source files on which "cc -E" (or whatever command make > uses) won't do the right thing? If every transformation command accepted -M, it wouldn't be a problem. One strategy to handle all cases would be to trace the executable and keep track of what files were opened. Shared libraries could be special-cased here. Under some tracing mechanisms this would even allow the recursive make that some people want. ---Dan
sralston@srwic.UUCP (Steve Ralston) (11/20/90)
Of the many replies to this subject, I have not seen mention of the method which I am currently using, namely: gcc -M file.c For those without gcc, press the 'n' key: According to the man page on gcc: -M Tell the preprocessor to output a rule suitable for make(1) describing the dependencies of each source file. For each source file, the preprocessor outputs one make-rule whose target is the object file name for that source file and whose dependencies are all the files #included in it. This rule may be a single line or may be continued with \-newline if it is long. -M implies -E. -E Run only the C preprocessor. Preprocess all the C source files specified and output the results to standard output. It's not real difficult to incorporate this command right in your Makefile (piping to sed, etc, or whatever) so that when you type something like: make depend the dependency lists are recreated from scratch. -- Steve Ralston sralston@srwic.UUCP 235 N Zelta voice: 316-686-2019 Wichita, KS 67206 ..!uunet!ncrlnk!ncrwic!srwic!sralston
meissner@osf.org (Michael Meissner) (11/21/90)
In article <4455@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes: | > How does the SunOs make figure out which files were included by each source | >file? Does it do a "cc -E" on the source file, or something similar? | | "Something similar". Basically, it provokes the compiler into producing | a dependency list as it compiles. I added this type of functionality to GCC's cpp. I added a new switch -MD, which runs the compile as normal, but places the dependency list for foo.c into foo.d in the current directory (CMU had done a similar thing previously). Part of the OSF/1 build process uses this and automatically updates the Makefiles. It was fairly simple to do providing you have source to the compiler (or a tame compiler wizard on hand).... -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142 Considering the flames and intolerance, shouldn't USENET be spelled ABUSENET?
tif@doorstop.austin.ibm.com (Paul Chamberlain) (11/22/90)
In article <9011151442.AA02010@decpa.pa.dec.com> ellis@ultra.dec.com (David Ellis 15-Nov-1990 0915) writes: >a change in a .h file that is #include'd in a .c file will not be picked >up by Make to automatically force recompilation of the .c file. > >One workaround is to [use] a collection of rules, ... It has already been pointed out that if one .c file does an include you can simply add this to the bottom of the makefile with no other changes: file1.o: include1.h But I thought it would be useful to point out these syntaxes as well: file1.o file2.o: common.h $(ALL_OBJS): common1.h common2.h Paul Chamberlain | I do NOT represent IBM. tif@doorstop, sc30661 at ausvm6 512/838-7008 | ...!cs.utexas.edu!ibmchs!auschs!doorstop.austin.ibm.com!tif