[comp.sources.wanted] Desperately Seeking Makefile Maker

nate@cpocd2.UUCP (Nathan Hess) (12/16/87)

I'm posting this request for a colleague.  Please mail any and all
responses to me, and I will forward them on to him.  Many thanks!


	Is there a program available that creates makefiles, preferrably
	written in C?


--woodstock
-- 
	   "How did you get your mind to tilt like your hat?"

...!{decwrl|hplabs!oliveb|pur-ee|qantel|amd}!intelca!mipos3!cpocd2!nate
<domainish> :   nate@cpocd2.intel.com		ATT :    (602) 961-2037

creps@silver.bacs.indiana.edu (Steve Creps) (12/17/87)

In article <1034@cpocd2.UUCP> nate@cpocd2.UUCP (Nathan Hess) writes:
>	Is there a program available that creates makefiles, preferrably
>	written in C?

   I thought this may be of general interest to the group, so I'm posting
it here.
   This problem sounds like something that could be easily done using the
standard Unix utilities. If your only file dependencies come from #include
lines in the files, then this should work pretty well. Use fgrep to
find all the #include's, and pipe it to awk for prettying up.
You could say something like this:
fgrep #include *.c *.h | awk -f makefile.awk >makefile

and makefile.awk might look something like this:
BEGIN { ORS = " "; filename = 0 }
{ if ($1 != filename) { filename = $1; print "\n" filename,":",$3 }
  else print " " $3 }
END { print "\n" }

What I'm hoping is that fgrep will output records of the form
file1: #include "foo.h"
file1: #include "bar.h"
file2: #include "foo.h"

and that for example $1 will get file2, and $3 will get "foo.h". Also, note
how I changed the output record separator (ORS) from newline to space,
and then print a newline with a file name every time the file name changes.
What I'm trying to get as output for the above example is this:
file1 : "foo.h" "bar.h"
file2 : "foo.h"

I'm writing this on the fly, so it may be a little buggy, but it should
work with little or no modification. I'll test it after I post this, and
see how it works.

-	-	-	-	-	-	-	-	-
Steve Creps on the VAX 8650 running Ultrix 2.0-1 at Indiana University.
	creps@silver.bacs.indiana.edu
"F-14 Tomcat! There IS no substitute."

creps@silver.bacs.indiana.edu (Steve Creps) (12/17/87)

   What I posted previously on using fgrep and awk worked just fine,
except that I had to first edit the output from fgrep to change the
":"'s following the file names to spaces. Then all you'll have to do
is some minor editing to remove quote characters, and remove any
system include files which you probably don't want in your makefile.
Anyway, this method gave me a good makefile list of dependencies.

-	-	-	-	-	-	-	-	-
Steve Creps on the VAX 8650 running Ultrix 2.0-1 at Indiana University.
	creps@silver.bacs.indiana.edu
"F-14 Tomcat! There IS no substitute."

ljz@fxgrp.UUCP (Lloyd Zusman, Master Byte Software) (12/18/87)

In article <538@silver.bacs.indiana.edu> creps@silver.UUCP (Steve Creps) writes:
>In article <1034@cpocd2.UUCP> nate@cpocd2.UUCP (Nathan Hess) writes:
>>	Is there a program available that creates makefiles, preferrably
>>	written in C?
> ...
>   This problem sounds like something that could be easily done using the
>standard Unix utilities.  ...
> ...
>You could say something like this:
>fgrep #include *.c *.h | awk -f makefile.awk >makefile
> ...

This sort of thing is fine as far as it goes, but what about nested
includes?  What about the differences between #includes that use
double quotes and those that use angle brackets?

There is something much better called 'mkmf' that makes makefiles.  It
handles the above cases just fine and produces a useful makefile.  As
far as I know, it's "netware", which means it's public domain and is
distributed over the net.  We have it here at my installation, and as
soon as I can determine if it truly *is* netware, I could shar it up
and email it to whomever is interested, source and all.  Contact me at
the address below if you want this, but *PLEASE* check here on the net
first to see if it's in one of the source archives, as it would be
better to get it from there.

In addition, I have a program I developed for the IBM PC that also
generates makefiles.  Its advantage is that it uses regular expression
syntax to define the format of an include statement, and each file
suffix can have such a regular expression (or group thereof)
associated with it.  This allows the utility also to be used for
programs written in languages other than C, most notably assembly
language and Pascal on the IBM PC.  This program handles nested
includes, but right now doesn't do anything special to distinguish
angle-bracket and double-quote includes.  This is because the various
C compilers on the IBM PC don't handle these in a uniform manner.  An
added feature of this program is for it to produce an include map for
all the source files processed by it.  This is particularly useful for
figuring out what's going on with nested includes.

This program of mine is not quite ready for distribution, as I have
not yet tried to port it to unix and because it is not fully tested.
I would distribute it as is to anyone who might want it, but I refuse
to support it until I've done more work on it.  Anyone who is
interested in this program please contact me at the address below.  Be
sure to give a nice, long, accurate uucp return address in your
posting, as I have extremely limited access to network maps.  The
only way to access my site is via 'ames' in California.

-------------------------------------------------------------------------
 Lloyd Zusman
 Master Byte Software
 Los Gatos, California	    	    	Internet:   fxgrp!ljz@ames.arpa
 "We take things well in hand."	    	UUCP:	    ...!ames!fxgrp!ljz

hunt@spar.SPAR.SLB.COM (Neil Hunt) (12/19/87)

In article <1034@cpocd2.UUCP> nate@cpocd2.UUCP (Nathan Hess) writes:
>	Is there a program available that creates makefiles, preferrably
>	written in C?

Here is a makefile maker which I have been using for a year or so.
It is based upon a version from Steve Rubin at Schlumberger, which may
be based upon something else...

Enjoy - Neil/.

#! /bin/csh
#
#	Script to make makefile entries for C source files.
#	Neil Hunt, Schlumberger Palo Alto Research 1986.
#	Ideas from Steve Rubin at Schlumberger.
#
# note: source files must spell /^#include/ with no spaces, and nested
#	includes are not supported. <files> are assumed stable, and
#	are not included in the dependency listing.
#
# example% depend file1.c file2.c >> Makefile
#
# egrep searches for include lines in source files; /dev/null is included
#	to force the filename to be printed even for a single source file.
#
# sed edits the lines to a form 'file.c: file.o include.h'
#
# awk assembles the lines into makefile format:
#	prev holds the previous file.c arg
#	doit holds a line of the form '   cc -c ${CFLAGS} file.c'
#	rec is a record initialised when a new 'file.c' is found,
#	and built up over the next few lines until its length would be > 75
#

egrep '^#include.*".*"' /dev/null $* | \
sed -e 's/\(.*\).c:[^"]*"\([^"]*\)".*/\1.o: \1.c \2/' | \
awk ' \
{ \
	if ($1 != prev) \
	{ \
		if (rec != "") \
		{ \
			print rec; \
			print doit; \
			print ""; \
		} \
		rec = $0; \
		prev = $1; \
		doit = "	cc -c ${CFLAGS} " $2; \
	} \
	else \
	{ \
		if (length(rec $3) > 75) \
		{ \
			print rec " \\"; \
			rec = "          " $3; \
		} \
		else rec = rec " " $3 \
	} \
} \
END { print rec; print doit; print ""; } '

bd@hpsemc.UUCP (bob desinger) (12/19/87)

Lloyd Zusman writes [edited]:  "What about nested includes?
What about #includes that use double quotes or angle brackets?"

Chris Torek wrote a script called `depend' that handles those.  It
appears below.  Run it with a command like `depend *.c' and your
output will appear on stdout in make-rule format.

Marshall Rose wrote some rules for `make' that append the dependency
list to your Makefile.  It's below too, in "makedepend".  You just
suck it into your Makefile, edit the line mentioned there to be
edited, and type `make depend'.  It examines the files you specify,
creating the list of dependencies.  If you don't have an existing list
of dependencies in your Makefile, it injects it into the Makefile.
If you already have one in the right format, it updates the list
(actually, it wipes the old list clean and re-creates a new one
from scratch).

But what if you want to do more than just generate dependency lists?
Lloyd further writes:
> There is something much better called 'mkmf' that makes makefiles.  It
> handles the above cases just fine and produces a useful makefile.  As
> far as I know, it's "netware", which means it's public domain and is
> distributed over the net.

Written by Peter Nicklin, a program called `mkmf' was distributed
with 4.2BSD.  Be careful about sending that one around; it was on the
Contributed Sources tape, so I'm not sure if it's okay to send it to
anyone or if recipients need the usual BSD (and AT&T) source licenses.

There's another script called, I think, `makemake' that really did appear
on the Usenet as public-domain software.  I couldn't find it in my
archives; maybe I threw it away after months of non-use.  Anyone have it?

bob desinger
Hewlett-Packard Co., Cupertino, CA

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unwrap it by saving it in a file and typing "sh file".
#
# Wrapped by bd at hpsemc on Fri Dec 18 12:41:38 1987
# Contents:
#	depends 	makedepend 	

PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:$PATH; export PATH
echo 'At the end, you should see the message "End of shell archive."'


echo Extracting depends
cat >depends <<'@//E*O*F depends//'
: getdep - get dependency lists.
# In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
# Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

: change ":" comments to "#" comments if your shell supports those;
: the result will run faster.

: find cpp
cpp=unknown
for where in /lib /usr/lib /bin /usr/bin; do
	if test -f $where/cpp; then cpp=$where/cpp; break; fi
done
if test $cpp = unknown; then
	echo "I cannot find cpp, sorry" 1>&2; exit 1
fi

: handle arguments
incl=
for i
do
	case "$i" in
	-I*)
		incl="$incl $i";;
	*)
		: assume source file
		: put '$dep' in front of dependencies
		dep=`echo "$i" | sed -e 's,/,\\\\/,g' -e 's/\.c$/.o/'`
		: Find includes, remove leading numerics, remove ./,
		: remove double quotes, and remove trailing numerics.
		: Sort that, discarding duplicates, and add '$dep'.
		$cpp $incl "$i" | grep "^#" |
		sed -e 's/# [0-9]* //' -e 's,"./,",' -e 's/"\(.*\)"/\1/' \
		    -e 's/ [ 0-9]*$//' |
		sort -u | sed -e "s/^/$dep: /";;
	esac
done
@//E*O*F depends//

set `wc -lwc <depends`
if test $1 -ne 36 -o $2 -ne 168 -o $3 -ne 996
then	echo ! depends should have 36 lines, 168 words, and 996 characters
	echo ! but has $1 lines, $2 words, and $3 characters
fi
chmod 755 depends


echo Extracting makedepend
cat >makedepend <<'@//E*O*F makedepend//'
# @(#)makedepend	1.2	87/03/19
##################
#  Dependencies  #
##################

# Replace the three sample modules below with the source-file basenames
# used in this directory.  (The samples below assume your sources are
# named date.c, dtime.c, and dtimep.c)
MODULES	=	date dtime dtimep
# Stop editing.

depend:;	for m in $(MODULES); do ( \
		    i=`basename $$m .c`; \
		    echo $$i.o: $$i.c >> makedep; \
		    grep '^#[ 	]*include' $$i.c | \
			sed -e 's,[^"]*"/\([^"]*\)".*,'$$i'.o: /\1,' \
			    -e 's,[^"]*"\([^"]*\)".*,'$$i'.o: \1,' \
			    -e 's,[^<]*<\(.*\)>.*,'$$i'.o: /usr/include/\1,' \
			>> makedep \
		); done
		echo '/^# DO NOT DELETE THIS LINE/+2,$$d' > eddep
		echo '$$r makedep' >> eddep
		echo 'w' >> eddep
		cp Makefile Makefile.old
		ed - Makefile < eddep
		rm eddep makedep
		echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
		echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile

# DO NOT DELETE THIS LINE
# DEPENDENCIES START HERE

# DEPENDENCIES MUST END AT END OF FILE
# IF YOU PUT STUFF HERE IT WILL GO AWAY
@//E*O*F makedepend//

set `wc -lwc <makedepend`
if test $1 -ne 34 -o $2 -ne 169 -o $3 -ne 1064
then	echo ! makedepend should have 34 lines, 169 words, and 1064 characters
	echo ! but has $1 lines, $2 words, and $3 characters
fi
chmod 644 makedepend

echo "End of shell archive."
exit 0

dougs@sequent.UUCP (Doug Schwartz) (12/19/87)

O'Reilly and Associates have a book out called "UNIX Text Processing",
which is published by Hayden, that has a shell script on page 566 that
builds a makefile.  Of course, this is oriented toward n/troff tasks,
but you can modify it for any environment.  This is left as an exercise
for the reader :-).

If you fancy yourself as a n/troff hacker or want to know more about
UNIX text processing, I highly recommend this book.  It and Gehani's
"Document Formatting & Typesetting on the UNIX System", Silicon Press,
are the best I've seen.

Doug Schwartz
Sequent Computer
Beaverton, Oregon
tektronix!ogcvax!sequent!dougs

jgy@hropus.UUCP (John Young) (12/19/87)

> In article <1034@cpocd2.UUCP> nate@cpocd2.UUCP (Nathan Hess) writes:
> >	Is there a program available that creates makefiles, preferrably
> >	written in C?
> 
>    I thought this may be of general interest to the group, so I'm posting
> it here.
>    This problem sounds like something that could be easily done using the
> standard Unix utilities. If your only file dependencies come from #include
> lines in the files, then this should work pretty well. Use fgrep to
> find all the #include's, and pipe it to awk for prettying up.
> You could say something like this:
> fgrep #include *.c *.h | awk -f makefile.awk >makefile
> 
> and makefile.awk might look something like this:
> BEGIN { ORS = " "; filename = 0 }
> { if ($1 != filename) { filename = $1; print "\n" filename,":",$3 }
>   else print " " $3 }
> END { print "\n" }
> 
> 
	.......
> 
> -	-	-	-	-	-	-	-	-
> Steve Creps on the VAX 8650 running Ultrix 2.0-1 at Indiana University.
> 	creps@silver.bacs.indiana.edu
> "F-14 Tomcat! There IS no substitute."
> 

The major issue here (for C programs) is #include files of course;
As pointed out they may be nested and they also may have dependencies
of the #ifdef, and -I (or #if) nature .  Therefore the way to
reliably determine include files is in the environment that
the compilation is desired. Therefore:

	cc -Dwhatever -Dotherstuff -Iwhatever/path -E filename.c |
		sed -n -e 's/^# 1 .*"\(.*\)"/\1/p' | sort -u

Is what you need to find the #include files necessary for a particular
style of compilation.  If you have a fairly recent version of a AT&T
C compiler you can use the -H flag instead of the -E to just get
desired info.

john young

creps@silver.bacs.indiana.edu (Steve Creps) (12/19/87)

   Note: followups to this discussion have been routed to comp.unix.questions,
so you may want to hit "n" now.

In article <178@fxgrp.UUCP> fxgrp!ljz@ames.arpa (Lloyd Zusman, Master Byte Software) writes:
>In article <538@silver.bacs.indiana.edu> creps@silver.UUCP (Steve Creps) writes:
>>In article <1034@cpocd2.UUCP> nate@cpocd2.UUCP (Nathan Hess) writes:
>>>	Is there a program available that creates makefiles, preferrably
>>>	written in C?
>> ...
>>You could say something like this:
>>fgrep #include *.c *.h | awk -f makefile.awk >makefile
>> ...
>
>This sort of thing is fine as far as it goes, but what about nested
>includes?  What about the differences between #includes that use
>double quotes and those that use angle brackets?

   I thought that make was smart enough that if you do have nested
#includes, it would pick this up. Am I wrong about this? That is, if
you have the following lines in the makefile:

aaa.c : bbb.h
bbb.h : ccc.h

and modified ccc.h, won't it know to recompile aaa.c? If so, the fgrep
method should be OK.
   As for the #include's with < >'s (system includes), I don't think
these are ever included in makefiles. If that's the case, then piping
the output from the "fgrep #include" through an "fgrep -v \<" should
take care of that problem. Anyway, I don't mean to argue about this;
the program you mentioned is probably a good thing to have.
   This discussion is really getting off from what the groups involved
are for, so I'm routing followups to comp.unix.questions.

-	-	-	-	-	-	-	-	-
Steve Creps on the VAX 8650 running Ultrix 2.0-1 at Indiana University.
	creps@silver.bacs.indiana.edu
"F-14 Tomcat! There IS no substitute."

wfp@dasys1.UUCP (William Phillips) (12/21/87)

Have you looked into SCCS?  The "makef" function of this source code
control system will create your Makefile for you.  The "help" function
leaves a lot to be desired, though :-)


-- 
William Phillips                 {allegra,philabs,cmcl2}!phri\
Big Electric Cat Public Unix           {bellcore,cmcl2}!cucard!dasys1!wfp
New York, NY, USA                (-: Just say "NO" to OS/2! :-)

garys@bunker.UUCP (Gary M. Samuelson) (12/22/87)

In article <538@silver.bacs.indiana.edu> creps@silver.UUCP (Steve Creps) writes:
>In article <1034@cpocd2.UUCP> nate@cpocd2.UUCP (Nathan Hess) writes:
>>	Is there a program available that creates makefiles, preferrably
>>	written in C?
>
>   I thought this may be of general interest to the group, so I'm posting
>it here.
>   This problem sounds like something that could be easily done using the
>standard Unix utilities. If your only file dependencies come from #include
>lines in the files, then this should work pretty well. Use fgrep to
>find all the #include's, and pipe it to awk for prettying up.
>You could say something like this:
>fgrep #include *.c *.h | awk -f makefile.awk >makefile
>
>and makefile.awk might look something like this:
>BEGIN { ORS = " "; filename = 0 }
>{ if ($1 != filename) { filename = $1; print "\n" filename,":",$3 }
>  else print " " $3 }
>END { print "\n" }

Besides being buggy (for example, foo.c doesn't depend on bar.h,
foo.o does), this doesn't cover several things which I would consider
important in such a utility, (in roughly decreasing order of importance):

1. Header files in a directory other than the one containing the
	makefile.
2. Source files other than 'foo.c' -- such as lex or yacc source.
3. The possibility that one makefile makes several different programs,
	each of which depends on different (but overlapping) subsets
	of include files.
4. Nested includes.  If bar.h includes baz.h, everything that depends
	on bar.h also depends on baz.h
5. The possibility of spaces or tabs between "#" and "include".  Easy
	to fix if you don't use fgrep, but this would hurt performance.
6. "#include" appearing in a comment.
7. "#include" in a conditional compilation context (should such includes
	be, ah, included in the dependencies?)

Of course, I don't know if the original poster considers these
requirements, but I would.

Such a script is bound to be slow.  It will have to be run before
make is run, every time a program is to be built, in case the actual
dependencies have changed (includes added or deleted).

We have a utility called 'gendepend' which generates a dependency list
and appends it to a makefile.  I don't know if it would be proper or
even desirable to post it, and offhand I'm not sure it handles all of
the cases I mentioned.  I know it handles nested includes, and I am
pretty sure it handles include files in other directories, but I am unsure
of the others.  (I personally don't use it that much.)  If there is
sufficient interest, I will look into it.

Gary Samuelson

tim@ora.UUCP (Tim O'Reilly) (12/23/87)

In article <3086@sequent.UUCP>, dougs@sequent.UUCP (Doug Schwartz) writes:
> 
> O'Reilly and Associates have a book out called "UNIX Text Processing",
> which is published by Hayden, that has a shell script on page 566 that
> builds a makefile.  Of course, this is oriented toward n/troff tasks,
> but you can modify it for any environment.  This is left as an exercise
> for the reader :-).
> 
> If you fancy yourself as a n/troff hacker or want to know more about
> UNIX text processing, I highly recommend this book.  

While I appreciate the plug for my book, I have to say that
the makefile generator Doug refers to is quite crude.  It is
aimed at people who don't know much about make, and probably
don't want to.  As a result, it takes a minimally
sophisticated, brute-force approach.  

In short, I wouldn't recommend that anyone get the book for 
pointers on how to use make!  For information on
troff, sed and awk, vi or any of the other text
processing utilities, yes...but the treatment of make (and
of shell programming) is mainly aimed at writers, not
programmers.   It is designed to tease people who might not
otherwise be comfortable with programming into "letting the
computer do the dirty work."

-- 
Tim O'Reilly (617) 527-4210
O'Reilly & Associates, Inc., Publishers of Nutshell Handbooks
981 Chestnut Street, Newton, MA 02164
UUCP:	uunet!ora!tim      ARPA:   tim@ora.uu.net

mmengel@cuuxb.ATT.COM (Marc W. Mengel) (12/24/87)

In article <538@silver.bacs.indiana.edu> creps@silver.UUCP (Steve Creps) writes:
>In article <1034@cpocd2.UUCP> nate@cpocd2.UUCP (Nathan Hess) writes:
>>	Is there a program available that creates makefiles, preferrably
>>	written in C?
>
>You could say something like this:
>fgrep #include *.c *.h | awk -f makefile.awk >makefile

Well, you could do what the maketd utility floating around Purdue
University did, and use the C preprocessor to include all of the
files for you, take the preprocessed output and grab all of the

# 1 "foo.h"
# 1 "/usr/include/bogus.h"

lines out of the file, and use them to generate your dependency lines.
It works quite well. (Maybe someone at Purdue would like to (re?)post
it...
-- 
 Marc Mengel	

 attmail!mmengel
 ...!{moss|lll-crg|mtune|ihnp4}!cuuxb!mmengel

rich@oxtrap.UUCP (K. Richard Magill) (12/31/87)

I once read about a (V8?) utility called build.  Did this ever leave
the author's machine?  or even (gasp) at&t? ;-).

rich.
----------
Real men write self-modifying code.