Make

Szerző: Stuart Feldman

Make originated with a visit from Steve Johnson (author of yacc, etc.),
storming into my office, cursing the Fates that had caused him to waste
a morning debugging a correct program (bug had been fixed, file had not
been compiled, cc *.o was therefore unaffected). As I had spent a part
of the previous evening coping with the same disaster on a project I was
working on, the idea of a tool to solve it came up. It began with an
elaborate idea of a dependency analyzer, boiled down to something much
simpler, and turned into Make that weekend. Use of tools that were still
wet was part of the culture. Makefiles were text files, not magically
encoded binaries, because that was the Unix ethos: printable, debuggable,
understandable stuff.
        
-- Stuart Feldman        



.h --->
        .s ----> .o ----> a.out
.c --->      


pelda1.make:
=================================
hello: hello.cpp
        g++ hello.cpp -o hello
=================================

$ make -f pelda1.make
g++ hello.cpp -o hello

$ make -f pelda1.make
make: `hello' is up to date

$ make hello -f pelda1.make
g++ hello.cpp -o hello

$ make hallo -f pelda1.make
make: *** No rule to make target `hallo'.  Stop.




Makefile alapvető szerkezete:

cel: elofeltetel1 elofeltetel2 ...
<TAB>   parancs

cel1 cel2 cel3 ... : elofeltetel1 elofeltetel2 elofeltetel3 ...
<TAB>   parancs1
<TAB>   parancs2
<TAB>   parancs3



make összetevői
 - explicit szabályok
 - implicit szabályok
 - változó definíciók
 - függőségek
 - produkciós szabályok
 - kommentek

explicit szabály
    hogyan készítsünk el egy fájlt

implicit szabály
    hogyan készítsük el fájlok csoportját

változók definíciók
    src = a.cpp b.cpp \
          c.cpp d.cpp

direktvák
    pl. más makefile-ok beolvasása
        include otherMakefile1 otherMakefile2 ...

    (Trükk: készítsünk el egy makefile-t, majd hajtsuk végre)

    a makefile egyes részeinek elhagyása
    változók definiálása

kommentek
    # karakterrel kezdődő sorok



Wildcards - mint a shell programozásban

    *   ?   [...]   [^...]


Automatikus változók

    $@  a szabály céljának fájlneve

    $%  a szabály céllpontja, ha archív

    $<  az első előfeltétel neve

    $?  az összes előfeltétel neve, melyek a célnál fiatalabbak üreshellyel..
    
    $^  az összes előfeltétel neve üreshellyel elválasztva
    
    $+  mint az előző, de megengedi a duplikátumokat

    $*  a cél fájlnév, kiterjesztés nélkül (stem)

    $(@D)   a cél könyvtár része

    $(@F)   a cél fájl része


pelda2.make:
===============================
hello: hello.cpp
        g++ $< -o $@
===============================


pelda3.make:
====================================
CC = g++
CPPFLAGS = -ansi -pedantic -Wall -W

hello: hello.cpp
        $(CC) $(CPPFLAGS) $< -o $@ 
====================================




Nem-fájl (phony) célpontok


# ne legyen clean nevű fájlunk!

=========================
clean:
        rm -f *.o
=========================

a phony szabályok mindig out of date állapotúak, azaz végrehajtódnak

Tipikus phony szabályok:

all
install
clean
info
check


Feltételes részek:

    ifeq($(CC),gcc)
        $(CC) -o foo $(objects) $(libs_for_gcc)
    else
        $(CC) -o foo $(objects) $(libs_for_other)
    endif




Implicit szabályok
 
    foo:  foo.o bar.o
        cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

    Nincsen szabályunk a foo.o -ra, de automatikusan használja      


    x.o : x.c
        $(CC) -c $(CPPFLAGS) $(CFLAGS) x.c
        
    x.o : x.cc | x.C
        $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) x.cc x.C

   Más nyelvekre is vannak automatikus szabályok:
   pascal, fortran, modula2, assembly

   linkelés:

    x: x.o
        $(CC) $(LDFLAGS) x.o $(LOADLIBES) $(LDLIBS)


Implicit szabályokat írhatunk un. minta-szabályok (pattern rules) segítségével.
Ezek hasonlítak a normál szabályokhoz, de a cél pontosan egy % karaktert
tartalmaz:
  

    %.c  pontosan .c-re végződő nevek
    s.%.c legalább 5 karakteres, s-el kezdődő c-re végződő nevek

    Az aktuális illeszkedés a  "stem".

    Az előfeltételekben a '%' pont ugyanazt a mintát jelenti, ami a célnál volt

===============================
%.o : %.c
        $(CC) $(CPPFLAGS) $<
===============================

    Néha az előfeltételek nem használják a '%' karaktert

    Példa:

    %.o : %.c
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@


   $@ a cél
   $< a forrás





Suffix szabályok (elavult stílus)

    .o : .c     ekvivalens      %.o : %.c

    .c.o :
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
                                                    
Inkább

    %.c : %.o
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
    


Függvények


    $(function arguments...)
    ${function arguments...}
    


    $(subst from,to,text)
    $(strip string)
    $(findstring what,where) 
    $(sort list)
    $(word n text)
    $(dir names...)
    $(suffix names...)
    $(wildcard pattern...)
    

    Wildcard kifejtés automatikus.    

    Példák:

        $(wildcard *.c)     lists all the .c files
        $(patsubst %.c,%.o,$(wildcard *.c))  changing x.c to x.o


Why the tab in column 1? Yacc was new, Lex was brand new. I had not tried
either, so I figured this would be a good excuse to learn. After getting
myself snarled up with my first stab at Lex, I just did something simple
with the pattern newline-tab. It worked, it stayed. And then a few weeks
later I had a user population of about a dozen, most of them friends, and
I did not want to screw up my embedded base. The rest, sadly, is history.
        
-- Stuart Feldman        


    $ make
        az alábbi fileneveket keresi: GNUmakefile makefile Makefile

    $ make -f my_make_file.mk                  
vagy
    $ make --file


.VARIABLES

    $ make -n       # only prints the commands not executes.




######################## sample ######################

.PHONY: doc clean show graph

SRC     = $(wildcard src/*)
TEXSRC  = $(wildcard *.tex)
DIASRC  = $(wildcard pic/*.dia)

article.dvi: $(TEXSRC) $(DIASRC)

%.dvi: %.tex
        latex $<
        latex $<

%.eps: pic/%.dia
        dia --nosplash --export=$@ $<


default: doc

show: doc
        xdvi.bin article.dvi &

doc: pics $(SRC) article.dvi

pics: $(DIASRC) 

purge: clean
        rm -f *.eps
        
clean:
        rm -f *.aux
        rm -f *.lo*
        rm -f *.toc
        rm -f *.dvi
        rm -f *.bbl *.blg
        rm -f *~ pic/*~ src/*~

help:
        @echo "Available targets:"
        @echo "  show     - compile and show document"
        @echo "  doc      - compile documents (default)"
        @echo "  pics      - compile pictures to document format"
        @echo "  clean    - remove generated files"
#       @echo "  retab     - retabulates the sources"
#       @echo "  longlines - show too long lines in the sources"
        @echo ""


# --- Still unused
%.eps: %.plot
        echo 'set terminal postscript eps; set output "$@"' | \
                gnuplot - $<

retab:
        for i in $(SRC); do vim -s retab.vim -e $$i; done

longlines:
        egrep '^.{76,}' $(SRC)


#source.tex: $(SRC)
#graph: benchmark.eps

######################### end sample #########################


******************************************************************


Makefile generators:


makedepend
==========

- reads sources, parses precompiler directives

SRCS = file1.c file2.c ...
CFLAGS = -O -DHACK -I../foobar -xyz
depend:
    makedepend -- $(CFLAGS) -- $(SRCS)
                                                                                

// a.h:
#include "b.h"
#include "b.c"

// b.h:
/* empty */

// a.c:
#include <list>
#include "a.h"

int main()
{
    return 0;
}

// b.c:
#include "b.h"


$ makedepend -fMakefile a.c
$ cat Makefile

# DO NOT DELETE
 
a.o: a.h b.h
b.o: b.h



*****************************************************************




Imake
=====

Imake is a Makefile generator to separate machine-dependent issues
from other make instructions.

Imake is based on CPP (C precompiler).



Imake was written in an attempt to mechanize makefile generation
for the X window system. It builds on makedepend to tackle both
the dependency-derivation and portability problems.

hard to learn, hard to use  :(

Archive for "Software Portability with imake" (2nd edition) (O Reilly)
http://www.kitebird.com/imake-book/
FAQ:
http://www.snake.net/software/imake-stuff/imake-faq.html

$ xmkmf
mv -f Makefile Makefile.bak
imake -DUseInstalled -I/usr/X11R6/lib/X11/config
imake: No such file or directory
imake: No description file.
  Stop.


You never run imake directly. You should use a bootstrapper, to tell
imake


********************************************************************



autoconf
========

- produces per-project configure shell scripts
- shell scripts generate makefiles

Manual:
http://www.gnu.org/software/autoconf/manual/index.html


your source files --> [autoscan*] --> [configure.scan] --> configure.ac
configure.ac --.
               |   .------> autoconf* -----> configure
[aclocal.m4] --+---+
               |   .-----> [autoheader*] --> [config.h.in]
[acsite.m4] ---.

Makefile.in -------------------------------> Makefile.in


Files used in configuring a software package:

                         .-------------> [config.cache]
configure* --------------+-------------> config.log
                         |
[config.h.in] ----.      v             .-> [config.h] -.
                  +--> config.status* -+               +--> make*
Makefile.in ------.                    .-> Makefile ---.  


automake
========

- put imake-like dependency derivation as a layer on
  top of autoconf.
- relatively new

              automake
Makefile.am  ---------> Makefile.in



$ make love
  "Don't know how to make love"                     (original)
  make: *** No rule to make target "love".  Stop.   (current gnu make)