






                   Probleme durch rekursives Make


             [4mPeter[24m [4mMiller[24m           Aus dem Amerikanischen
         millerp@canb.auug.org.au   ins  Deutsche  uber-
                                         setzt von
                                       [4mUlrike[24m [4mAmoore[0m
                                    uamoore@cmmagazin.de


                              [1mVorwort[0m
         Zur Produktion groer UNIX-Projekte  verwendet  man
         traditionellerweise  rekursives  Make. Bei manchen
         Projekten fuhrt das  zu  sehr  langen  Produktion-
         szeiten, was insbesondere, wenn man nur eine Datei
         andern  mochte,  unvertretbar  ist.  Als  wir  das
         Phanomen  naher untersuchten, stellte sich heraus,
         dass eine Reihe  von  Problemen,  die  voneinander
         unabhangig  zu  sein  schienen,  gemeinsam fur die
         Verzogerung verantwortlich waren. Eine genaue Ana-
         lyse zeigte jedoch eine gemeinsame Ursache.
         Dieser  Artikel  beschaftigt  sich mit einigen der
         Probleme, die im Zusammenhang  mit  der  Anwendung
         von  rekursivem Make regelmaig auftreten, und legt
         dar, dass sie  alle  Symptome  desselben  Problems
         sind. Diese Symptome haben die UNIX-Anwender lange
         als unumgangliche Tatsachen hingenommen, aber  sie
         mussen  nicht langer geduldet werden. Dazu gehort,
         dass ein rekursives Make oft sehr  lange  braucht,
         um  herauszufinden, dass es nichts zu tun braucht,
         dass es zu viel oder zu wenig  tut  oder  dass  es
         ubermaig  empfindlich  auf Veranderungen von Quel-
         lkode reagiert und fur  eine  ungestorte  Funktion
         den  standigen  Eingriff in das Makefile notwendig
         macht.
         Man kann die Losung  fur  diese  Probleme  finden,
         indem   man  sein  Augenmerk  erst  einmal  darauf
         richtet, wie Make grundsatzlich arbeitet, und dann
         die   Auswirkungen   analysiert,   die  durch  das
         Hinzufugen von rekursivem Make, hervorgerufen wer-
         den.  Die  Analyse zeigt, dass das Problem von der
         kunstlichen Einteilung des  Builds  in  gesonderte
         Teilmengen  herruhrt.  Das  wiederum  fuhrt zu den
         beschriebenen Symptomen. Um die Symptome  zu  ver-
         meiden,  ist  es  lediglich  notwendig  diese Ein-
         teilung zu verhindern, d. h. einen einzigen  Make-
         Durchgang zu veranlassen, was nicht bedeutet, dass
         es nur ein einziges Makefile gibt.
         Diese   Schlussfolgerung    widerspricht    vielen
         bezuglich  der  Produktion groer Projekte angesam-
         melten Volksweisheiten. Einige der von  Vertretern
         dieser Volksweisheiten vorgebrachten Einwande wer-
         den  hier  untersucht  und   erweisen   sich   als



    Peter Miller          31 December 2013                Page 1





    CM Magazin, Dec-2002          Probleme durch rekursives Make


         unbegrundet.   Die   praktische  Umsetzung  dieser
         Schlussfolgerung fuhrt  zu  wesentlich  ermutigen-
         deren  Ergebnissen.  Wird  diese  Methode  laufend
         weiterentwickelt,   werden   Verbesserungen    der
         Effizienz  erheblich schneller als erwartet sicht-
         bar, ohne dass die Modularitat  aufgegeben  werden
         muss. Die Durchfuhrung eines Ganzprojekt-Makes ist
         nicht so schwierig  umzusetzen,  wie  es  zunachst
         erscheint.




    [1m1.  Einfuhrung[0m

    Die traditionellen Produktionsmethoden fur groe UNIX Softwa-
    reentwicklungsprojekte  sind  als  [4mrekursives[24m  [4mMake[24m  bekannt
    geworden. Der Name verweist auf die Verwendung einer Hierar-
    chie  von  Verzeichnissen, die die Quelldateien fur die Mod-
    ule, aus denen das Projekt besteht, beinhalten, wobei  jedes
    der  Unterverzeichnisse ein Makefile enthalt, das die Regeln
    und  Anweisungen  fur  das  Make-Programm  beschreibt.   Das
    vollstandige  Projekt-Build wird durchgefuhrt, indem man das
    Haupt-Makefile  veranlasst,  in  allen   Unterverzeichnissen
    wiederum Make aufzurufen.

    Dieser Artikel untersucht ein paar wesentliche Probleme, auf
    die man stot, wenn man bei der Entwicklung von  Softwarepro-
    jekten  mit  dem rekursiven Make arbeitet. Auerdem wird eine
    einfache Losung aufgezeigt  und  einige  ihrer  Auswirkungen
    werden untersucht.

    Durch  Rekursives Make erhalt man einen Verzeichnisbaum, der
    ungefahr so aussieht:
                          +++
                          ++[4mP[24m+[4mr[24m|[4moject[0m
                           ++++Mmaokdeufliel1e
                           |++ +|Makefile
                           | + +|source1.c
                           | + +|[4metc...[0m
                           ++++m+odule2
                             + +|Makefile
                             + +|source2.c
                             + +|[4metc...[0m

    Diese  verschachtelte  Modulhierarchie  kann  beliebig  aus-
    geweitet  werden.  Reale  Projekte  haben oft zwei oder drei
    Ebenen.



    -----------
    Copyright (C) 1997 Peter Miller
    German  translation Copyright (C) 2002 CM-Magazin.



    Ulrike Amoore         31 December 2013                Page 2





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [1m1.1.  Kenntnisse vorausgesetzt[0m

    Dieser Artikel setzt voraus, dass Sie  mit  Softwareentwick-
    lung auf Unix, dem Make-Programm, den Grundsatzen von C-Pro-
    grammierung und mit Dateiabhangigkeiten vertraut ist.

    Weiterhin geht er davon aus, dass  Sie  GNU-Make  auf  ihrem
    System  installiert  haben  und  seine  Funktionen mehr oder
    weniger gut kennen. Falls Sie  eine  eingeschrankte  Version
    verwenden,  kann  es  sein,  dass  Ihnen  einige  der  unten
    beschriebenen Funktionen nicht zur Verfugung stehen.

    [1m2.  Das Problem[0m

    Es gibt eine Vielzahl von Problemen mit rekursivem Make;  in
    der  Praxis  begegnet man ihnen normalerweise taglich.  Hier
    sind einige dieser Probleme aufgelistet:

    +o Es ist sehr schwierig, die Reihenfolge der Rekursion  kor-
      rekt in die Unterverzeichnisse zu formulieren.  Diese Rei-
      henfolge nicht sehr stabil und ab und zu muss man sie  von
      Hand  korrigieren.   Je mehr Verzeichnisse es gibt oder je
      mehr Ebenen dem Verzeichnisbaum hinzugefugt werden,  desto
      unstabiler wird diese Reihenfolge.

    +o Es ist oft notwendig, die Unterverzeichnisse mehr als ein-
      mal zu durchlaufen, um das ganze System herzustellen.  Das
      fuhrt naturlich zu langeren Build-Zeiten.

    +o Da  die  Produktionszeiten  sonst unvertretbar lang waren,
      was mit einer Unproduktivitat der Entwickler  gleichbedeu-
      tend  ware,  lasst  man einige Informationen bezuglich der
      Abhangigkeiten der Verzeichnisse untereinander  weg.   Das
      fuhrt  in der Regel dazu, dass einige Produkte nicht aktu-
      alisiert werden, obwohl sie es  sollten,  wodurch  haufige
      Produktionen   von   Null   an   erforderlich  werden,  um
      sicherzustellen, dass tatsachlich alles aufgebaut wird.

    +o Da die Abhangigkeiten zwischen den Verzeichnissen entweder
      weggelassen  werden oder zu schwer auszudrucken sind, wer-
      den die Makefiles oft so geschrieben,  dass  sie  zu  viel
      machen,  um  sicherzustellen,  dass wirklich nichts ausge-
      lassen wurde.

    +o Die Ungenauigkeit der Abhangigkeiten  oder  einfach  deren
      Fehlen  kann  zur Folge haben, dass ein Produkt sich nicht
      fehlerfrei bauen lasst.   Dadurch  wird  eine  sorgfaltige
      Kontrolle   des  Build-Prozesses  durch  einen  Entwickler
      erforderlich.

    +o Eine andere Folge des oben Beschriebenen ist, dass  manche
      Projekte  von den Moglichkeiten der Parallelisierung durch
      Make nicht  profitieren  konnen,  weil  das  Build  offen-
      sichtlich Unsinn macht.



    Peter Miller          31 December 2013                Page 3





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Nicht  jedes Projekt hat alle diese Probleme.  Wenn sie auf-
    tauchen, tun sie das oft unregelmaig  und  werden  dann  als
    unerklarbare  einmalige  Macken  abgetan.  In diesem Artikel
    sollen eine Reihe Symptome, die uber eine langen Zeitraum in
    der  Praxis  beobachtet  wurden,  miteinander  in  Beziehung
    gesetzt werden.  Es folgen eine  systematische  Analyse  und
    ein Losungsvorschlag.

    It  must be emphasized that this paper does not suggest that
    [4mmake[24m itself is the problem.  This paper is working from  the
    premise  that  [4mmake[24m  does [1mnot [22mhave a bug, that [4mmake[24m does [1mnot[0m
    have a design flaw.  The problem is not in [4mmake[24m at all,  but
    rather  in  the  input given to [4mmake[24m - the way [4mmake[24m is being
    used.

    [1m3.  Analyse[0m

    Bevor es moglich ist, sich  diesen  scheinbar  in  keinerlei
    Beziehung  zueinander stehenden Problemen zuzuwenden, ist es
    notwendig,  zu  verstehen,  was  Make  bewirkt  und  wie  es
    arbeitet.  Dann  erst  kann man die Auswirkungen, die rekur-
    sives Make auf das Verhalten von Make hat, betrachten.

    [1m3.1.  Ganzprojekt-Make[0m

    Make ist ein Expertensystem. Sie versehen es mit einem  Satz
    Regeln,  nach  denen  gebaut werden soll, und einem Zielpro-
    dukt, das gebaut werden soll. Die Regeln konnen in paarweise
    geordnete  Abhangigkeiten  zwischen  den Dateien zergliedert
    werden.  Make  liest  die  Regeln  und  ermittelt,  wie  das
    angegebene   Zielprodukt   gebaut  werden  soll.  Sobald  es
    entschieden hat,  wie  das  Zielprodukt  konstruiert  werden
    soll, verfahrt es entsprechend. Make ermittelt die Konstruk-
    tionsweise, indem es einen gerichteten  azyklischen  Graphen
    erstellt,  den DAG (directed acyclic graph), der vielen Stu-
    denten der Computerwissenschaften vertraut ist. Die  Knoten-
    punkte  dieses Graphs sind die Dateien des Systems, die Kan-
    ten stellen die Abhangigkeiten zwischen den Dateien dar. Die
    Kanten  des  Graphen  sind  gerichtet, da die Abhangigkeiten
    paarweise  geordnet  sind,  wodurch  ein  azyklischer  Graph
    entsteht - was in einem ungerichteten Graphen wie ein Zyklus
    aussieht, wird im gerichteten Graphen durch die Richtung der
    Kanten aufgelost.

    In  diesem Artikel wird eine kleines Beispielprojekt fur die
    Analyse benutzt. Obwohl die  Anzahl  der  Dateien  in  diese
    Beispiel  klein  ist,  ist  es  komplex  genug, um alle oben
    beschriebenen Probleme mit rekursivem Make zu demonstrieren.
    Zuerst  einmal  wird  das  Projekt in einer nicht rekursiven
    Form vorgestellt.







    Ulrike Amoore         31 December 2013                Page 4





    CM Magazin, Dec-2002          Probleme durch rekursives Make


                           +++
                           ++[4mP[24m+[4mr[24m|[4moject[0m
                            + +|Mmaakienf.icle
                            + +|parse.c
                            + +|parse.h
                              -


    Das Makefile in diesem kleinen Projekt sieht so aus:

                    +--------------------------+
                    |OBJ = main.o parse.o      |
                    |prog: $(OBJ)              |
                    |  $(CC) -o $@ $(OBJ)      |
                    |main.o: main.c parse.h    |
                    |  $(CC) -c main.c         |
                    |parse.o: parse.c parse.h  |
                    |  $(CC) -c parse.c        |
                    +--------------------------+
    Ein paar der impliziten Regeln von Make sind  hier  explizit
    aufgeschrieben, um es fur Sie einfacher zu machen, das Make-
    file in den zugehorigen DAG umzuformen.

    Das oben genannte Makefile kann als DAG in  folgender  Weise
    dargestellt werden:
    [40m[0m
                                prog



                          main.o   parse.o


                      main.c   parse.h  parse.c



    [40mAufgrund  der  Pfeile,  die  die Ordnung der Beziehungen der[0m
    [40mDateien zueinander ausdrucken,  handelt  es  sich  um  einen[0m
    [40mazyklischen  Graphen.  Wenn  es  den  Pfeilen  zufolge  eine[0m
    [40mkreisformige Abhangigkeit gabe, lage ein Fehler vor.[0m

    [40mBeachten Sie bitte, dass  die  Objektdateien  (.o)  von  den[0m
    [40mInclude-Dateien  (.h)  abhangig  sind,  obwohl es die Quell-[0m
    [40mdateien (.c) sind, die das Einfugen vornehmen. Das hat  fol-[0m
    [40mgenden  Grund:  Wird  eine  Include-Datei geandert, sind die[0m
    [40mObjektdateien nicht mehr aktuell, nicht die Quelldateien.[0m

    [40mDer zweite Schritt des Make-Prozesses  ist  eine  Postorder-[0m
    [40mTraversierung  des  DAG.  Das  bedeutet, dass die abhangigen[0m
    [40mKnotenpunkte zuerst besucht werden. Die eigentliche  Reihen-[0m
    [40mfolge der Traversierung ist nicht festgelegt, aber die meis-[0m
    [40mten Make-Anwendungen gehen von oben nach unten und bei  Kan-[0m
    [40mten  unter  demselben  Knotenpunkt von links nach rechts und[0m



    Peter Miller          31 December 2013                Page 5





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mdie meisten  Projekte  verlassen  sich  stillschweigend  auf[0m
    [40mdieses  Verhalten.  Die  zuletzt  geanderten Versionen aller[0m
    [40mDateien werden untersucht  und  eine  weiter  oben  liegende[0m
    [40mDatei  wird  als  nicht mehr aktuell eingestuft, wenn irgen-[0m
    [40mdeine der darunterliegenden Dateien, von denen sie  abhangig[0m
    [40mist, junger ist. Wenn eine Datei als nicht mehr akuell klas-[0m
    [40msifiziert wurde, wird die zu der  entsprechenden  Graphkante[0m
    [40mgehorende   Aktion  ausgefuhrt  (in  dem  oben  aufgefuhrten[0m
    [40mBeispiel ware das ein Kompilations- oder ein  Bindeprozess).[0m

    [40mDie  Anwendung  von rekursivem Make beeinflusst beide Phasen[0m
    [40mder Make-Operation: Es veranlasst Make, einen ungenauen  DAG[0m
    [40mzu  erstellen  und  es zwingt Make, den DAG in einer unange-[0m
    [40mbrachten Reihenfolge zu traversieren.[0m

    [1m[40m3.2.  Rekursives Make[0m

    [40mUm die Auswirkungen des  rekursiven  Makes  zu  untersuchen,[0m
    [40mteilen  wir  das  obige  Beispiel  in zwei Module ein. Jedes[0m
    [40mModul hat sein eigenes Makefile und  ein  Makefile  fur  die[0m
    [40moberste  Ebene,  deren Aufgabe es ist, jedes der Modul-Make-[0m
    [40mfiles aufzurufen.[0m

    [40mDieses Beispiel ist absichtlich konstruiert und  zwar  durch[0m
    [40mund  durch.  Aber  jede  Modularitat  in  Projekten  ist  in[0m
    [40mgewisser Weise ein Konstrukt. Bedenken Sie: Bei vielen  Pro-[0m
    [40mjekten ebnet der Linker am Ende alles wieder ein.[0m

    [40mDie Verzeichnisstruktur ist folgendermaen:[0m
                          [40m+++[0m
                          [40m++[4mP[24m+[4mr[24m|[4moject[0m
                           [40m++++Maanktefile[0m
                           [40m|++ +|Makefile[0m
                           [40m| - +|main.c[0m
                           [40m++++b+ee[0m
                             [40m+ +|Makefile[0m
                             [40m+ +|parse.c[0m
                             [40m+ +|parse.h[0m


    [40mDas  Makefile  der  obersten  Ebene  sieht oft sehr wie eine[0m
    [40mShell-Befehlsdatei aus:[0m

                  [40m+-------------------------------+[0m
                  [40m|MODULES = ant bee              |[0m
                  [40m|all:                           |[0m
                  [40m|  for dir in $(MODULES); do \  |[0m
                  [40m|    (cd $$dir; ${MAKE} all); \ |[0m
                  [40m|  done                         |[0m
                  [40m+-------------------------------+[0m
    [40mDas ant/Makefile sieht so aus:[0m






    Ulrike Amoore         31 December 2013                Page 6





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m              +------------------------------+[0m
                  [40m|all: main.o                   |[0m
                  [40m|main.o: main.c ../bee/parse.h |[0m
                  [40m|  $(CC) -I../bee -c main.c    |[0m
                  [40m+------------------------------+[0m
    [40mund der entsprechende DAG sieht so aus:[0m
    [40m[0m
                               [40mmain.o[0m



                          [40mmain.c    parse.h[0m

    [40mDas bee/Makefile sieht so aus:[0m

                   [40m+----------------------------+[0m
                   [40m|OBJ = ../ant/main.o parse.o |[0m
                   [40m|all: prog                   |[0m
                   [40m|prog: (OBJ)                 |[0m
                   [40m|  $(CC) -o $@ $(OBJ)        |[0m
                   [40m|parse.o: parse.c parse.h    |[0m
                   [40m|  $(CC) -c parse.c          |[0m
                   [40m+----------------------------+[0m
    [40mund der entsprechende DAG sieht so aus:[0m
    [40m[0m
                              [40mprog[0m



                        [40mmain.o    parse.o[0m


                             [40mparse.h  parse.c[0m



    [40mSchauen Sie sich die DAGs genau an. Sie stellen  fest,  dass[0m
    [40mkeiner von ihnen komplett ist. Beiden DAGs fehlen Knoten und[0m
    [40mKanten. Wenn die vollstandige Produktion  von  der  obersten[0m
    [40mEbene ausgefuhrt wird, funktioniert alles.[0m

    [40mAber  was passiert, wenn eine kleine Anderung eintritt?  Was[0m
    [40mwurde passieren, wenn parse.c und parse.h von einer  parse.y[0m
    [40mYacc  Grammatik  erzeugt wurden? Dann wurden folgende Zeilen[0m
    [40mdem bee/Makefile hinzugefugt:[0m

                    [40m+--------------------------+[0m
                    [40m|parse.c parse.h: parse.y  |[0m
                    [40m|  $(YACC) -d parse.y      |[0m
                    [40m|  mv y.tab.c parse.c      |[0m
                    [40m|  mv y.tab.h parse.h      |[0m
                    [40m+--------------------------+[0m
    [40mUnd die entsprechenden Veranderungen des DAGs sahen so aus:[0m




    Peter Miller          31 December 2013                Page 7





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m[0m
                              [40mprog[0m



                        [40mmain.o    parse.o[0m


                             [40mparse.h  parse.c[0m



                                  [40mparse.y[0m



    [40mDiese Veranderung hat eine einfache Folge: Wenn parse.y edi-[0m
    [40mtiert  wird,  wird main.o nicht correct aufgebaut. Das ruhrt[0m
    [40mdaher, dass der DAG fur ant nur  einige  der  Abhangigkeiten[0m
    [40mvon  main.o  kennt,  wahrend der DAG fur bee sogar keine von[0m
    [40mihnen kennt.[0m

    [40mUm zu verstehen, warum das passiert, ist es notwendig,  sich[0m
    [40mdie  Aktionen,  die  Make von der obersten Ebene aus untern-[0m
    [40mimmt, anzuschauen. Nehmen Sie einmal an, dass das Projekt in[0m
    [40msich  konsistent  ist.  Jetzt editieren Sie parse.y, so dass[0m
    [40mdie   generierte   parse.h   nicht-triviale    Veranderungen[0m
    [40maufweist. Wenn nun das Haupt-Make aufgerufen wird, wird erst[0m
    [40mant und dann bee besucht. Aber  ant/main.o  ist  noch  nicht[0m
    [40mrekompiliert,  weil bee/parse.h noch nicht regeneriert wurde[0m
    [40mund deshalb noch  nicht  anzeigt,  dass  main.o  nicht  mehr[0m
    [40maktuell  ist.  Das  ist auch immer noch nicht der Fall, wenn[0m
    [40mdas rekursive Make bee besucht, wobei  parse.c  und  parse.h[0m
    [40mund  zuletzt parse.o rekonstruiert werden. Wenn das Programm[0m
    [40mgelinkt wird, sind main.o und  parse.o  in  erheblichem  Mae[0m
    [40mnicht kompatibel. D. h. das Programm funktioniert nicht.[0m

    [1m[40m3.3.  Herkommliche Losungen[0m

    [40mEs  gibt  drei  herkommliche  Korrekturmoglichkeiten fur die[0m
    [40moben beschriebene Storung.[0m

    [1m[40m3.3.1.  Umstrukturierung[0m

    [40mDie erste ist, die Anordnung der Module in  dem  Haupt-Make-[0m
    [40mfile  von  Hand  zu  berichtigen. Die Frage ist, warum diese[0m
    [40mKorrektur uberhaupt notwendig ist. Schlielich soll Make eine[0m
    [40mExpertensystem  sein.  Hat Make irgendeinen Fehler oder ging[0m
    [40metwas anderes schief?[0m

    [40mZur Beantwortung dieser Frage muss man  nicht  den  Graphen,[0m
    [40msondern   die   Anordnung   der  Traversierung  des  Graphen[0m
    [40manschauen. Um fehlerlos zu arbeiten,  muss  Make  eine  Pos-[0m
    [40mtorder-Traversierung  vornehmen,  aber dadurch, dass der DAG[0m



    Ulrike Amoore         31 December 2013                Page 8





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40min zwei Teile geteilt wurde, war es Make nicht mehr  moglich[0m
    [40mden Graphen in der notwendigen Reihenfolge zu traversieren -[0m
    [40mstattdessen  wurde  von   dem   Projekt   eine   Reihenfolge[0m
    [40mvorgeschrieben.  Eine  Reihenfolge, die, wenn man den Origi-[0m
    [40mnalgraphen betrachtet, schlichtweg falsch ist. Indem man das[0m
    [40mHaupt-Makefile  korrigiert, stellt man eine Reihenfolge her,[0m
    [40mdie der,  die  Make  hatte  benutzen  konnen,  ahnlich  ist.[0m
    [40mSolange, bis die nachste Abhangigkeit hinzugefugt wird...[0m

    [40mBitte  beachten  Sie,  dass paralleles Build (make -j) viele[0m
    [40mder bei der manuellen  Umstrukturierung  gemachten  Annahmen[0m
    [40mstillschweigend auer Kraft setzt, wodurch diese Losung nutz-[0m
    [40mlos wird. Auerdem fuhren alle  untergeordneten  Makes  eben-[0m
    [40mfalls mehrere Aktionen gleichzeitig aus.[0m

    [1m[40m3.3.2.  Wiederholung[0m

    [40mBei  der  zweiten  herkommlichen Losung lasst man das Haupt-[0m
    [40mMakefile mehrere Male durchlaufen.  Das  sieht  ungefahr  so[0m
    [40maus:[0m

                  [40m+-------------------------------+[0m
                  [40m|MODULES = ant bee              |[0m
                  [40m|all:                           |[0m
                  [40m|  for dir in $(MODULES); do \  |[0m
                  [40m|    (cd $$dir; ${MAKE} all); \ |[0m
                  [40m|  done                         |[0m
                  [40m|  for dir in $(MODULES); do \  |[0m
                  [40m|    (cd $$dir; ${MAKE} all); \ |[0m
                  [40m|  done                         |[0m
                  [40m+-------------------------------+[0m

    [40mDadurch  wird  die  Produktionszeit verdoppelt. Aber das ist[0m
    [40mnicht alles: Es gibt keine Garantie,  dass  zwei  Durchlaufe[0m
    [40mausreichen!  Die  Hochstzahl der Durchlaufe ist nicht einmal[0m
    [40mproportional zu der Anzahl der Module, sondern  proportional[0m
    [40mzu der Anzahl der Graphkanten, die Modulgrenzen kreuzen.[0m

    [1m[40m3.3.3.  Des Guten zu viel[0m

    [40mWir  haben  schon  ein  Beispiel gesehen, bei dem rekursives[0m
    [40mMake zu wenig baute, aber ein anderes  verbreitetes  Problem[0m
    [40mist, dass zu viel gebaut wird. Bei der dritten herkommlichen[0m
    [40mLosung fugt man dem  ant/Makefile  sogar  noch  mehr  Zeilen[0m
    [40mhinzu:[0m

                    [40m+--------------------------+[0m
                    [40m|.PHONY: ../bee/parse.h    |[0m
                    [40m|../bee/parse.h:           |[0m
                    [40m|    cd ../bee; \          |[0m
                    [40m|    make clean; \         |[0m
                    [40m|    make all              |[0m
                    [40m+--------------------------+[0m




    Peter Miller          31 December 2013                Page 9





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mDas  bedeutet,  dass  immer wenn main.o gebaut wird, parse.h[0m
    [40mals nicht aktuell betrachtet wird. Alle Inhalte von bee wer-[0m
    [40mden  jedesmal  von  neuem gebaut einschlielich parse.h. Auch[0m
    [40mmain.o wird immer wieder neu gebaut, selbst  wenn  alles  in[0m
    [40msich konsistent war.[0m

    [40mBeachten Sie bitte, dass bei dieser Losung make -j (paralle-[0m
    [40mles    Build)    viele    der    angenommenen    Anordnungen[0m
    [40mstillschweigend auer Kraft setzt, wodurch diese Losung nutz-[0m
    [40mlos wird, weil alle der untergeordneten  Makes  ihre  Builds[0m
    [40mgleichzeitig durchfuhren(clean und dann all), wobei sie sich[0m
    [40mstandig gegenseitig storen.[0m

    [1m[40m4.  Vorsorge[0m

    [40mDie obige Analyse basiert auf einer  einfachen  Aktion:  Der[0m
    [40mDAG  wurde  kunstlich  in  unvollstandige Stucke unterteilt.[0m
    [40mDiese Unterteilung hat all die Probleme, die man von  rekur-[0m
    [40msiv verwendetem Make kennt, zur Folge.[0m

    [40mHat  Make  es  nicht richtig verstanden? Nein, das ist nicht[0m
    [40mder Grund. Hier liegt ein  Fall  des  uralten  GIGO-Prinzips[0m
    [40m(Garbage  in, Garbage out) vor: Wo man Mull hereintut, kommt[0m
    [40mMull heraus. Unvollstandige Makefiles sind fehlerhafte Make-[0m
    [40mfiles.[0m

    [40mWenn  Sie  diese Probleme vermeiden wollen, zerlegen Sie den[0m
    [40mDAG nicht in einzelne Teile. Verwenden sie  stattdessen  ein[0m
    [40meinziges  Makefile  fur  das ganze Projekt. Die Rekursion an[0m
    [40msich ist nicht schadlich, sondern das verstummelte Makefile,[0m
    [40mdas man fur die Rekursion verwendet, ist falsch. Es ist kein[0m
    [40mFehler von Make, dass das rekursive Make nicht funktioniert;[0m
    [40mes macht das bestmogliche aus den mangelhaften Eingabeinfor-[0m
    [40mmationen.[0m

         [40m"[4mAber,[24m [4maber,[24m [4maber...[24m [4mDas[24m  [4mkonnen[24m  [4mSie[24m  [4mdoch[24m  [4mnicht[0m
         [4m[40mmachen![24m",  hore  ich  Sie  jammern,  "[4mein[24m [4meinziges[0m
         [4m[40mMakefile[24m [4mist[24m [4mviel[24m [4mzu[24m [4mgro,[24m [4mman[24m [4mkann[24m  [4mes[24m  [4mgar[24m  [4mnicht[0m
         [4m[40mwarten,[24m [4mes[24m [4mist[24m [4mviel[24m [4mzu[24m [4mschwierig,[24m [4mdie[24m [4mRegeln[24m [4mdafur[0m
         [4m[40mzu[24m [4mschreiben,[24m  [4mder[24m  [4mPlatz[24m  [4mim[24m  [4mHauptspeicher[24m  [4mwird[0m
         [4m[40mnicht[24m [4mausreichen,[24m [4mich[24m [4mwill[24m [4mnur[24m [4mmeinen[24m [4mkleinen[24m [4mTeil[0m
         [4m[40mbauen,[24m [4mdas[24m [4mBuild[24m [4mwird[24m [4mviel[24m [4mzu[24m [4mlange[24m [4mdauern.[24m [4mEs[24m [4mist[0m
         [4m[40mschlichtweg[24m [4mnicht[24m [4mpraktikabel.[24m"[0m

    [40mDas  sind stichhaltige Einwande und oft ziehen Make-Benutzer[0m
    [40maus ihnen den Schluss, dass es keinerlei kurz- oder  langer-[0m
    [40mfristigen  Nutzen fur sie bringen wurde, ihren Build-Prozess[0m
    [40meinmal zu uberarbeiten. Diese Schlussfolgerung ist auf uber-[0m
    [40mholten,   falschen   Annahmen  gegrundet,  die  sich  jedoch[0m
    [40mhartnackig halten.[0m

    [40mIn den nachsten Abschnitten wird der Reihe  nach  auf  jeden[0m
    [40mdieser Einwande eingegangen.[0m




    Ulrike Amoore         31 December 2013               Page 10





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m[1m4.1.  Ein einziges Makefile ist zu gro[0m

    [40mWare  die vollstandige Produktionsbeschreibung fur das ganze[0m
    [40mProjekt in  einem  einzigen  Makefile  untergebracht,  wurde[0m
    [40mdieser  Satz  sicherlich zutreffen. Aber moderne Make-Imple-[0m
    [40mmentierungen kennen Include-Anweisungen. Dadurch,  dass  ein[0m
    [40mentscheidendes  Fragment jedes Moduls einschlossen wird, ist[0m
    [40mdie Gesamtgroe des Makefiles und seiner Includes nicht unbe-[0m
    [40mdingt groer als die des beim rekursiven Vorgehen verwendeten[0m
    [40mMakefiles.[0m

    [1m[40m4.2.  Ein einziges Makefile kann man nicht warten[0m

    [40mEin Haupt-Makefile, das eine Referenz auf ein Fragment jedes[0m
    [40mModuls  enthalt, ist nicht komplexer als das beim rekursiven[0m
    [40mMake verwendete. Da der DAG nicht zerstuckelt ist, ist diese[0m
    [40mArt  Makefile  sogar  weniger  komplex  und  damit besser zu[0m
    [40mwarten, einfach weil weniger Korrekturen notwendig sind,  um[0m
    [40mseine Funktionstuchtigkeit zu erhalten.[0m

    [40mRekursive  Makefiles  beinhalten  eine Menge Wiederholungen.[0m
    [40mBei vielen Projekten wird dieses Problem durch  die  Verwen-[0m
    [40mdung von Include-Dateien gelost. Wenn man ein einziges Make-[0m
    [40mfile fur das Projekt benutzt, fallt  der  Bedarf  an  diesen[0m
    [40m"allgemeinen"  Include-Dateien  weg  - das eine Makefile ist[0m
    [40mder allgemeine Teil.[0m

    [1m[40m4.3.  Es ist zu schwierig, die Regeln zu formulieren[0m

    [40mMan muss lediglich den Verzeichnisteil an  einer  Reihe  von[0m
    [40mStellen  in die Dateinamen einfugen. Das ist notwendig, weil[0m
    [40mMake vom Verzeichnis der obersten Ebene ausgefuhrt wird;  in[0m
    [40mdem  aktuellen  Verzeichnis  erscheint  die Datei nicht. Man[0m
    [40mmuss sich nicht darum kummern, wo die Ausgabedatei ausdruck-[0m
    [40mlich in einer Regel genannt wird.[0m

    [40mGCC erlaubt im Zusammenhang mit der -c-Option eine -o-Option[0m
    [40mund GNU-Make wei das. Daraus folgt eine  implizite  Kompila-[0m
    [40mtionsregel,  die  die  Ausgabedatei  an  die richtige Stelle[0m
    [40msetzt. Altere und weniger intelligente Compiler  lassen  die[0m
    [40m-o-Option  mit  der -c-Option jedoch vielleicht nicht zu und[0m
    [40mlassen die Objektdatei im  Verzeichnis  der  obersten  Ebene[0m
    [40mzuruck  (d.  h.  im  falschen  Verzeichnis).  Es  gibt  drei[0m
    [40mMoglichkeiten, wie Sie  diesen  Fehler  korrigieren  konnen:[0m
    [40mEntweder  Sie  beschaffen  sich  GNU-Make und GCC, sie uber-[0m
    [40mschreiben die Build-Regel durch eine korrekt funktionierende[0m
    [40moder Sie beschweren sich bei ihrem Handler.[0m

    [40mAuch  K&R;  C-Compiler  beginnen  den  in  Anfuhrungszeichen[0m
    [40mnotierten Includepfad (#include "filename.h") vom  aktuellen[0m
    [40mVerzeichnis aus. Das bedeutet, dass sie nicht das ausfuhren,[0m
    [40mwas Sie wollen. ANSI C-konforme C-Compiler aber beginnen den[0m
    [40min Anfuhrungszeichen notierten Includepfad von dem Verzeich-[0m
    [40mnis aus, in dem die Quelldatei erscheint;  hier  sind  keine[0m



    Peter Miller          31 December 2013               Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mVeranderungen der Quelle notwendig. Falls Sie keinen ANSI C-[0m
    [40mkonformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht[0m
    [40mziehen,  so  bald  wie moglich einen GCC auf Ihrem System zu[0m
    [40minstallieren.[0m

    [1m[40m4.4.  Ich will doch nur mein kleines Teilprodukt bauen[0m

    [40mDie  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum[0m
    [40mbeschaftigt.  Sie  bearbeiten  ein  oder zwei Dateien lassen[0m
    [40mdann Make durchlaufen, was ihre Veranderungen ubersezt,  und[0m
    [40mprobieren  sie aus. Diesen Arbeitsschritt fuhren sie taglich[0m
    [40mDutzende oder Hunderte Male aus. Es ware  absurd,  wenn  sie[0m
    [40mgezwungen waren jedesmal das ganze Projekt zu bauen.[0m

    [40mEntwickler habe immer die Option, ein besonderes Zielprodukt[0m
    [40mfur Make zu definieren. Das gilt immer,  wir  verlassen  uns[0m
    [40mlediglich  gewohnlich  auf  das  im  Makefile  des aktuellen[0m
    [40mVerzeichnisses   vorgegebene    Zielprodukt,    um    unsere[0m
    [40mBefehlszeile  zu  verkurzen.  Man  kann  also auch mit einem[0m
    [40mGanzprojekt-Makefile sein kleines Teilprodukt  bauen,  indem[0m
    [40mman  einfach ein bestimmtes Zielprodukt definiert und, falls[0m
    [40mdie Befehlszeile zu lang wird, ein Pseudonym verwendet.[0m

    [40mEs stellt sich aber auch die Frage, ob es  immer  so  absurd[0m
    [40mist,  das  ganze  Projekt zu bauen. Wenn z. B. eine in einem[0m
    [40mModul vorgenommene Anderung in anderen Modulen  Auswirkungen[0m
    [40mhat,  weil  eine  Abhangigkeit existiert, die dem Entwickler[0m
    [40mnicht bewusst ist (aber dem Makefile ist sie bewusst),  ware[0m
    [40mes dann nicht besser, wenn der Entwickler das so schnell wie[0m
    [40mmoglich herausfindet?  Solche Abhangigkeiten  werden  gefun-[0m
    [40mden,  weil  der  DAG  vollstandiger  ist als beim rekursiven[0m
    [40mVorgehen.[0m

    [40mIn den seltensten Fallen  sind  Entwickler  erfahrene,  alte[0m
    [40mHasen,  die  jede einzelne der Millionen von Zeilen Kode des[0m
    [40mProduktes  auswendig  kennen.  Meistens  haben   sie   einen[0m
    [40mzeitlich  begrenzten  Vertrag  oder  sie sind jungere Mitar-[0m
    [40mbeiter. Sie wollen naturlich nicht,  dass  Auswirkungen  wie[0m
    [40mdie eben beschriebene entdeckt werden, nachdem Ihre Anderun-[0m
    [40mgen in den Hauptkode  einfugt  wurden,  sondern  wurden  sie[0m
    [40mgerne  ganz  in  Ruhe  in  ihrem lokalen Arbeitsbereich ent-[0m
    [40mdecken, weit weg vom Hauptkode.[0m

    [40mWenn Sie "nur Ihr kleines Teilprodukt"  bauen  wollen,  weil[0m
    [40mSie befurchten, dass ein Bau des ganzen Projekts infolge der[0m
    [40mVerzeichnisstruktur, die  Sie  in  Ihrem  Projekt  verwendet[0m
    [40mhaben,  die  Master  Source des Projekts beschadigen konnte,[0m
    [40mlesen  Sie  bitte  das  Kapitel  [4mProjekte[24m  [4mim[24m  [4mVergleich[24m  [4mzu[0m
    [4m[40mSandkasten[24m.[0m








    Ulrike Amoore         31 December 2013               Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m[1m4.5.  Das Bauen dauert zu lange[0m

    [40mDiese Aussage kann man fur eine von zwei Situationen machen:[0m
    [40m1. Die Durchfuhrung des Make eines ganzen  Projekts  dauert,[0m
    [40mobwohl  alles aktualisiert ist, unvermeidlich sehr lange. 2.[0m
    [40mDiese unvermeidbaren Verzogerungen sind  unakzeptabel,  wenn[0m
    [40mder Entwickler die eine Datei, die er verandert hat, schnell[0m
    [40mkompilieren und linken will.[0m

    [1m[40m4.5.1.  Builds von Projekten[0m

    [40mStellen Sie sich ein hypothetisches  Projekt  vor  mit  1000[0m
    [40mQuelldateien  (.c),  von denen jede ihre Aufrufschnittstelle[0m
    [40mhat, welche in der zugehorigen Include-Datei (.h) mit  Defi-[0m
    [40mnitionen,   Typvereinbarungen   und   Funktionsdeklarationen[0m
    [40mdefiniert ist. Diese 1000 Quelldateien beinhalten ihre eige-[0m
    [40mnen  Interfacedefinitionen und zusatzlich die Interfacedefi-[0m
    [40mnitionen aller Module, die sie aufrufen konnen.  Diese  1000[0m
    [40mQuelldateien  werden  in  1000  Objektdateien ubersetzt, die[0m
    [40mwiederum zu einem ausfuhrbaren Programm gebunden werden.  In[0m
    [40mdiesem  System  gibt  es  etwa  3000  Dateien, uber die Make[0m
    [40minformiert werden muss. Auerdem muss Make uber die  Include-[0m
    [40mabhangigkeiten  informiert  werden und man muss untersuchen,[0m
    [40mob implizite Regeln (z. B. .y - .c) anwendbar sind.[0m

    [40mUm den DAG zu erstellen, muss Make fur  3000  Dateien  deren[0m
    [40mAnderungsdatum  ermitteln  und  auerdem  noch  fur etwa 2000[0m
    [40mzusatzliche  Dateien,  abhangig  davon,  welche   impliziten[0m
    [40mRegeln  Ihr  Make  kennt  und welche Ihr Makefile nicht aus-[0m
    [40mgeschaltet hat. Auf dem bescheidenen 66MHz i486 des  Authors[0m
    [40mdauert  das  etwa  10 Sekunden; auf systemeigenen Laufwerken[0m
    [40mauf schnelleren Hardwarebasen geht es sogar noch  schneller.[0m
    [40mMit NFS uber 10MB Ehernet dauert es ebenfalls etwa 10 Sekun-[0m
    [40mden, gleichgultig, von welcher Hardwarebasis die Aktion aus-[0m
    [40mgefuhrt wird.[0m

    [40mDas ist eine erstaunliche Statistik. Stellen Sie sich einmal[0m
    [40mvor, dass Sie ihn der  Lage  sind,  eine  einzige  von  1000[0m
    [40mQuelldateien in nur 10 Sekunden - zuzuglich der Zeit fur das[0m
    [40mKompilieren selbst - zu kompilieren.[0m

    [40mDie Dateien auf 100 Module zu verteilen und den Prozess  als[0m
    [40mein rekursives Make durchzufuhren, dauert immerhin 25 Sekun-[0m
    [40mden. Die wiederholte Prozesserzeugung  fur  die  untergeord-[0m
    [40mneten   Make-Aufrufe  nehmen  eine  relativ  lange  Zeit  in[0m
    [40mAnspruch.[0m

    [40mAber warten Sie  einen  Moment!  Bei  realen  Projekten  mit[0m
    [40mweniger  als  1000 Dateien dauert es sehr viel langer als 25[0m
    [40mSekunden bis Make herausgefunden hat, das es nichts  zu  tun[0m
    [40mhat.  Fur  manche  Projekte ware es ein Fortschritt, wenn es[0m
    [40mnur 25 Minuten dauerte. Dieses Beispiel zeigt uns,  dass  es[0m
    [40mnicht die Anzahl der Dateien ist, die bremst (das dauert nur[0m
    [40m10  Sekunden),  und  es  ist  auch  nicht  die   wiederholte[0m



    Peter Miller          31 December 2013               Page 13





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mProzesserzeugung  fur  die untergeordneten Make-Aufrufe (die[0m
    [40mdauert nur 15 Sekunden).  Was aber nimmt dann so  viel  Zeit[0m
    [40min Anspruch?[0m

    [40mBei   traditionellen  Losungen  des  durch  rekursives  Make[0m
    [40menstandenen Problems werden die untergeordneten Make-Aufrufe[0m
    [40moft  uber  das  hier  beschriebene  Minimum erhoht: z. B. um[0m
    [40mvielfaltige Wiederholungen (3.3.2.)  durchzufuhren  oder  um[0m
    [40mModulgrenzen    uberschreitende    Abhangigkeiten   (3.3.3.)[0m
    [40mubermaig abzudecken. Das kann lange Zeit dauern,  besonders,[0m
    [40mwenn  beides zusammenkommt. Aber es ist nicht fur die beson-[0m
    [40mders langen Produktionszeiten verantwortlich. Was nimmt also[0m
    [40mnoch soviel Zeit in Anspruch?[0m

    [40mDie  Komplexitat  des  Makefiles  ist so zeitaufwendig. Mehr[0m
    [40mdaruber im Kapitel [4mEffiziente[24m [4mMakefiles[24m.[0m

    [1m[40m4.5.2.  Builds wahrend der Entwicklung[0m

    [40mWenn es - wie bei dem Beispiel mit den 100 Dateien - nur  10[0m
    [40mSekunden  dauert,  herauszufinden welche Datei neu ubersetzt[0m
    [40mwerden muss, wird die  Produktivitat  der  Entwickler  nicht[0m
    [40mbedeutend   eingeschrankt,  wenn  sie  ein  Ganzprojekt-Make[0m
    [40mdurchfuhren  anstatt  eines  modulspezifischen  Makes.   Der[0m
    [40mVorteil  fur  das  Projekt  ist,  dass  der  modulzentrierte[0m
    [40mEntwickler  in  entscheidenden  Momenten  (und  nur  in  den[0m
    [40mentscheidenden)  daran erinnert wird, dass seine Arbeit auch[0m
    [40mweitgehendere Auswirkungen hat.[0m

    [40mDie standige Verwendung von  C-Include-Dateien,  die  genaue[0m
    [40mInterface-Definitionen  (einschlielich  Funktionsprototypen)[0m
    [40menthalten, wurde in  vielen  Fallen  zu  Ubersetzungsfehlern[0m
    [40mfuhren,  was  wiederum  ein  fehlerhaftes  Produkt zur Folge[0m
    [40mhatte. Werden Builds fur  das  ganze  Projekt  durchgefuhrt,[0m
    [40mentdecken  Entwickler  solche  Fehler  sehr fruh im Entwick-[0m
    [40mlungsprozess und sind  in  der  Lage  Fehlerbehebungen  dann[0m
    [40mvorzunehmen, wenn sie den geringsten Aufwand verursachen.[0m

    [1m[40m4.6.  Ihre Speicherkapazitaten sind erschopft[0m

    [40mDas  ist  der  interessanteste Einwand. Irgenwann einmal vor[0m
    [40mlanger Zeit auf einem Mikroprozessor weit, weit weg ist  das[0m
    [40mvielleicht  sogar  vorgekommen.  Als  Feldman das erste Make[0m
    [40mentwickelte, schrieb man das Jahr 1978 und er benutzte  eine[0m
    [40mPDP11. Unix-Prozesse waren auf 64B Daten beschrankt.[0m

    [40mSolch  ein  Rechner wurde bei dem oben genannte Beispiel mit[0m
    [40mseinen 3000 in dem Ganzprojekt-Makefile genau  beschriebenen[0m
    [40mDateien  warscheinlich  nicht  zulassen,  einen  DAG und die[0m
    [40mRegeln im Hauptspeicher zu halten.[0m

    [40mAber wir benutzen  keine  PDP11  mehr.  Die  physische  Spe-[0m
    [40micherkapazitat  eines  kleinen modernen Computers uberschre-[0m
    [40mitet 10MB und der virtuelle Speicher oft 100MB. Ein  Projekt[0m



    Ulrike Amoore         31 December 2013               Page 14





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mmit  hunderttausenden  Quelldateien  ist  notwendig,  um die[0m
    [40mvirtuelle Speicherkapazitat eines kleinen modernen  Rechners[0m
    [40mzu  erschopfen. Da das Beispielprojekt mit 1000 Quelldateien[0m
    [40mweniger als 100KB Speicherplatz in Anspruch nimmt (probieren[0m
    [40mSie  es  aus, Sie werden sehen, dass es stimmt), ist es sehr[0m
    [40munwahrscheinlich, dass irgendein Projekt, das man  in  einem[0m
    [40meinzigen Verzeichnisbaum auf einem einzigen Laufwerk verwal-[0m
    [40mten kann, die Speicherkapazitaten ihres Rechners ubersteigt.[0m

    [1m[40m4.7.  Warum erstellt man den DAG nicht in den Modulen?[0m

    [40mOben wurde erlautert, dass die Grunde fur die  Probleme  bei[0m
    [40mrekursivem  Make  in dem unvollstandigen DAG zu suchen sind.[0m
    [40mDem zufolge kann das Problem gelost werden,  indem  man  die[0m
    [40mfehlenden   Abhangigkeiten   wieder   hinzufugt,   ohne  die[0m
    [40mexistierende Investition in das rekursive Make aufzugeben.[0m

    +o[40m Der Entwickler darf es jedoch nicht vergessen. Die  Folgen[0m
      [40mtragt  nicht er, sondern die Entwickler der anderen Module[0m
      [40mbekommen sie zu spuren. Es  gibt  keine  bessere  Methode,[0m
      [40meinen  Entwickler daran zu erinnern, etwas zu tun, als den[0m
      [40mZorn der Kollegen.[0m

    +o[40m Es ist schwierig, herauszufinden, an  welcher  Stelle  die[0m
      [40mAnderungen  vorgenommen werden mussen. Moglicherweise muss[0m
      [40mjedes  Makefile  im  ganzen  Projekt   auf   erforderliche[0m
      [40mAnderungen  hin  untersucht  werden.  Naturlich konnen Sie[0m
      [40mauch darauf warten, dass Ihre Kollegen die Stellen fur Sie[0m
      [40mfinden.[0m

    +o[40m Die   Includeabhangigkeiten   werden   unnotigerweise  neu[0m
      [40mberechnet oder werden  nicht  korrekt  interpretiert.  Das[0m
      [40mpassiert,  weil  Make auf Zeichenketten basiert, wodurch .[0m
      [40mund ../ant zwei verschiedene Stellen sind, selbst wenn Sie[0m
      [40mim  ant-Verzeichnis  stehen.  Das  ist von Bedeutung, wenn[0m
      [40mIncludeabhangigkeiten automatisch berechnet werden, wie es[0m
      [40mbei allen groen Projekten der Fall ist.[0m

    [40mIndem man sicherstellt, dass jedes Makefile vollstandig ist,[0m
    [40mkommt man an den Punkt, dass das Makefile  wenigstens  eines[0m
    [40mModuls  bereits  die Informationen des Ganzprojekt-Makefiles[0m
    [40mumfasst (Sie durfen nicht vergessen, dass diese  Module  ein[0m
    [40meinziges  Projekt  formen  und  daher  miteinander verbunden[0m
    [40msind), wodurch das rekursive Make uberflussig wird.[0m

    [1m[40m5.  Effiziente Makefiles[0m

    [40mDas zentrale Thema dieses  Artikels  sind  die  semantischen[0m
    [40mNebenwirkungen  des  kunstlichen  In-Stucke-Zerteilens eines[0m
    [40mMakefiles,  das  notwendig  ist,  um  ein  rekursives   Make[0m
    [40mdurchzufuhren.  Wenn  Sie jedoch viele Makefiles haben, wird[0m
    [40mdie Geschwindigkeit, in der Make diese Menge Dateien  inter-[0m
    [40mpretieren kann, ebenfalls zum Thema.[0m




    Peter Miller          31 December 2013               Page 15





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mBuilds  konnen  aus  zwei Grunden ubermaig lange dauern: Die[0m
    [40mherkommlichen Korrekturen fur den zerteilten  DAG  bauen  zu[0m
    [40mviel oder Ihr Makefile ist nicht effizient.[0m

    [1m[40m5.1.  Verzogerte  Auswertung[0m

    [40mMake muss den Text eines Makefiles irgendwie aus einer Text-[0m
    [40mdatei lesen und verstehen, so dass ein DAG erstellt und  die[0m
    [40mangegebenen  Aktionen  den  Kanten zugeordnet werden konnen.[0m
    [40mAll das wird im Speicher festgehalten.[0m

    [40mDie Eingabesprache fur Makefiles  ist  irrefuhrend  einfach.[0m
    [40mSie  ist  textbasiert, im Gegensatz zu den tokenbasierten z.[0m
    [40mB. fur C und AWK. Das ist  ein  entscheidender  Unterschied,[0m
    [40mder Neulingen genauso wie Experten oft entgeht. Make tut das[0m
    [40mabsolute Minimum, um die Eingabezeilen  zu  verarbeiten  und[0m
    [40msie im Hauptspeicher zu verstauen.[0m

    [40mFolgende Zuordnung ist ein Beispiel dafur:[0m

                    [40m+--------------------------+[0m
                    [40m|OBJ = main.o parse.o      |[0m
                    [40m+--------------------------+[0m
    [40mWenn  Menschen  das  lesen, heit das, der Variablen OBJ sind[0m
    [40mzwei Dateinamen main.o und  parse.o  zugeordnet.  Aber  Make[0m
    [40mversteht  das  ganz anders. OBJ wird die Zeichenfolge main.o[0m
    [40mparse.o zugeordnet. Und es wird noch schlimmer:[0m

                    [40m+--------------------------+[0m
                    [40m|SRC = main.c parse.c      |[0m
                    [40m|OBJ = $(SRC:.c=.o)        |[0m
                    [40m+--------------------------+[0m
    [40mIn diesem Fall erwartet der Mensch, dass OBJ durch Make zwei[0m
    [40mDateinamen  zugeordnet  werden,  aber  Make  ordnet in Wirk-[0m
    [40mlichkeit die Zeichenkette $(SRC:,c=.o) zu. Das ruhrt  daher,[0m
    [40mdass es sich um eine Makrosprache mit verzogerter Auswertung[0m
    [40mhandelt im Gegensatz zu einer mit Variablen  und  sofortiger[0m
    [40mAuswertung.[0m

    [40mWenn es Ihnen nicht zu schwierig erscheint, schauen Sie sich[0m
    [40mdie folgende Makefile an:[0m

                   [40m+-----------------------------+[0m
                   [40m|SRC = $(shell echo 'Ouch!' \ |[0m
                   [40m|  1>&2 ; echo *.[cy])        |[0m
                   [40m|OBJ = \                      |[0m
                   [40m|  $(patsubst %.c,%.o,\       |[0m
                   [40m|    $(filter %.c,$(SRC))) \  |[0m
                   [40m|  $(patsubst %.y,%.o,\       |[0m
                   [40m|    $(filter %.y,$(SRC)))    |[0m
                   [40m|test: $(OBJ)                 |[0m
                   [40m|  $(CC) -o $@ $(OBJ)         |[0m
                   [40m+-----------------------------+[0m
    [40mWie oft wird das Shell-Kommando ausgefuhrt? Autsch! Er wird,[0m



    Ulrike Amoore         31 December 2013               Page 16





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mallein  um  den  DAG zu konstruieren, zweimal ausgefuhrt und[0m
    [40mnoch zweimal, wenn die Regel ausgefuhrt  werden  muss.  Wenn[0m
    [40mdieser  Shell-Befehl  nichts  komplexes oder zeitaufwendiges[0m
    [40mausfuhrt (was er aber normalerweise tut), braucht er viermal[0m
    [40mso lang, wie erwartet.[0m

    [40mAber  es  lohnt  sich,  andere Teile dieses OBJ-Makros naher[0m
    [40manzuschauen. Jedesmal, wenn es genannt wird, werden  riesige[0m
    [40mMengen von Vorgangen abgewickelt:[0m

    +o[40m Der  Parameter  fur  Shell  ist  eine einzige Zeichenkette[0m
      [40m(alle Built-in-Funktionen haben als Parameter eine einzige[0m
      [40mZeichenkette).  Die  Zeichenkette  wird in der untergeord-[0m
      [40mneten Shell ausgefuhrt und die Standardausgabe dieses Kom-[0m
      [40mmandos  wird  wieder  eingegeben,  wobei Zeilenumbruche in[0m
      [40mLeerschritte verwandelt  werden.  Das  Ergebnis  ist  eine[0m
      [40meinzige Zeichenkette.[0m

    +o[40m Der  Parameter  zum Filtern ist eine einzige Zeichenkette.[0m
      [40mDieser Parameter wird beim ersten Komma in  zwei  Zeichen-[0m
      [40mketten zerlegt. Jede der beiden Zeichenketten wird dann in[0m
      [40mdurch Leerschritte getrennte  Teilketten  aufspalten.  Die[0m
      [40merste  Reihe  entspricht  den  Mustern  und die zweite den[0m
      [40mDateinamen. Dann wird fur jede  Musterteilkette,  mit  der[0m
      [40meine  Dateinamenteilkette  ubereinstimmt, der Dateiname in[0m
      [40mdie Ausgabe eingefugt. Sobald die Ausgabe vollstandig ist,[0m
      [40mwerden die Teilketten wieder zu einer einzigen durch Leer-[0m
      [40mschritte unterteilten Zeichenkette zusammengesetzt.[0m

    +o[40m Der  Parameter  zur  Musterersetzung  ist   eine   einzige[0m
      [40mZeichenkette.   Dieser  Parameter  wird  beim  ersten  und[0m
      [40mzweiten Komma in  drei  Ketten  aufgespalten.  Die  dritte[0m
      [40mKette wird dann in durch Leerschritte getrennte Teilketten[0m
      [40mzerteilt, die den Dateinamen entsprechen. Dann wird  jeder[0m
      [40mDateiname,  der  mit  der ersten Kette ubereinstimmt, gema[0m
      [40mder zweiten Kette ersetzt. Wenn ein  Dateiname  nicht  mit[0m
      [40mder  ersten  Kette ubereinstimmt, passiert er unverandert.[0m
      [40mSobald die Ausgabe vollstandig erzeugt wurde,  werden  die[0m
      [40mTeilketten  wieder  zu  einer  einzigen durch Leerschritte[0m
      [40munterteilten Zeichenkette zusammengesetzt.[0m

    [40mSie sehen, wie  oft  diese  Zeichenketten  aufgespalten  und[0m
    [40mwieder  zusammengestzt  werden.  Sie sehen, auf wieviel ver-[0m
    [40mschiedene Weisen das passiert. Das ist langsam.  In  unserem[0m
    [40mBeispiel  gibt  es  nur  zwei Dateien, aber stellen Sie sich[0m
    [40mvor, wie lange diese Prozeduren  fur  1000  Dateien  dauern.[0m
    [40mDiese Aktion viermal auszufuhren, ist sehr ineffizient.[0m

    [40mWenn  Sie  ein  einfaches Make, das uber keine Ersetzung und[0m
    [40mkeine Built-in-Funktionen verfugt, benutzen,  beeintrachtigt[0m
    [40mSie  das  nicht.  Aber ein modernes Make hat viele Built-in-[0m
    [40mFunktionen   und   kann   sogar   nebenbei   Shell-Kommandos[0m
    [40mausfuhren. Die Semantik der Textmanipulation von Make fuhrt,[0m
    [40mverglichen mit C  oder  AWK,  zu  einer  sehr  CPU-intesiven[0m



    Peter Miller          31 December 2013               Page 17





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mZeichenkettenmanipuation in Make.[0m

    [1m[40m5.2.  Unmittelbare Auswertung[0m

    [40mModerne  Make-Ausfuhrungen haben einen := Zuordnungsoperator[0m
    [40mfur unmittelbare Auswertung. Das oben genannte Beispiel kann[0m
    [40mfolgendermaen neu geschrieben werden:[0m

                  [40m+------------------------------+[0m
                  [40m|SRC := $(shell echo 'Ouch!' \ |[0m
                  [40m|  1>&2 ; echo *.[cy])         |[0m
                  [40m|OBJ := \                      |[0m
                  [40m|  $(patsubst %.c,%.o,\        |[0m
                  [40m|    $(filter %.c,$(SRC))) \   |[0m
                  [40m|  $(patsubst %.y,%.o,\        |[0m
                  [40m|    $(filter %.y,$(SRC)))     |[0m
                  [40m|test: $(OBJ)                  |[0m
                  [40m|  $(CC) -o $@ $(OBJ)          |[0m
                  [40m+------------------------------+[0m
    [40mBeachten  Sie, dass beide Zuordnungen Zuordnungen fur unmit-[0m
    [40mtelbare Auswertung sind. Ware die  erste  keine,  wurde  das[0m
    [40mShell-Kommando  immer  zweimal  ausgefuhrt  werden. Ware die[0m
    [40mzweite keine, wurden die aufwendigen Ersetzungen  mindestens[0m
    [40mzweimal, moglicherweise sogar viermal durchgefuhrt werden.[0m

    [40mAls  Daumenregel  gilt:  Benutzen  Sie immer Zuordnungen fur[0m
    [40munmittelbare Auswertung, es sei denn  Sie  wunschen  bewusst[0m
    [40meine verzogerte Auswertung.[0m

    [1m[40m5.3.  Include-Dateien[0m

    [40mViele Makefiles fuhren denselben Textbearbeitungsvorgang (z.[0m
    [40mB. die o. g.  Filter)  bei  jedem  einzelnen  Make-Durchlauf[0m
    [40merneut  durch;  das  Ergebnis  dieser Prozeduren andert sich[0m
    [40mjedoch selten. Wenn es  auch  praktisch  ist,  ist  es  doch[0m
    [40meffizienter,  die Ergebnisse der Textbearbeitung einer Datei[0m
    [40mzu speichern und diese Datei in das Makefile einzufugen.[0m

    [1m[40m5.4.  Abhangigkeiten[0m

    [40mSeien Sie nicht geizig mit Include-Dateien.  Man  kann  sie,[0m
    [40mverglichen mit $(shell), mit relativ wenig Aufwand lesen und[0m
    [40msie beintrachtigen auch die Effizienz nur wenig.[0m

    [40mUm  ein  Beispiel  dafur  zu  zeigen,  ist  es  erst  einmal[0m
    [40mnotwendig,  eine  nutzliche  Eigenschaft  des  GNU-Makes  zu[0m
    [40mbeschreiben: Wenn Make das Makefile gelesen hat  und  einige[0m
    [40mihrer   Include-Dateien   sind   nicht  mehr  aktuell  (oder[0m
    [40mexistieren noch nicht), werden  sie  neu  erzeugt  und  Make[0m
    [40mbeginnt  noch  einmal.  Das  fuhrt dazu, dass Make jetzt mit[0m
    [40maktuellen  Include-Dateien  arbeitet.  Diese  Funktion  kann[0m
    [40mgenutzt  werden, um ein automatische Berechnung der Include-[0m
    [40mDateiabhangigkeiten fur C-Quellen zu realisieren. Die  nahe-[0m
    [40mliegendste  Art,  es  auszufuhren,  hat jedoch einen kleinen[0m



    Ulrike Amoore         31 December 2013               Page 18





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mFehler.[0m

                    [40m+--------------------------+[0m
                    [40m|SRC := $(wildcard *.c)    |[0m
                    [40m|OBJ := $(SRC:.c=.o)       |[0m
                    [40m|test: $(OBJ)              |[0m
                    [40m|  $(CC) -o $@ $(OBJ)      |[0m
                    [40m|include dependencies      |[0m
                    [40m|dependencies: $(SRC)      |[0m
                    [40m|  depend.sh $(CFLAGS) \   |[0m
                    [40m|    $(SRC) > $@           |[0m
                    [40m+--------------------------+[0m
    [40mDas depend.sh-Skript druckt seine Zeilen in folgender Weise:[0m

         [4m[40mDatei[24m.o: [4mDatei[24m.c [4mInclude[24m.h ...[0m

    [40mDie  einfachste  Art, das umzusetzen, ist, GCC zu verwenden,[0m
    [40maber Sie brauchen eine entsprechendes AWK-Skript oder C-Pro-[0m
    [40mgramm, wenn Sie einen anderen Compiler verwenden:[0m

                    [40m+--------------------------+[0m
                    [40m|#!/bin/sh                 |[0m
                    [40m|gcc -MM -MG "$@"          |[0m
                    [40m+--------------------------+[0m
    [40mDiese   Methode,   C-Includeabhangikeiten  aufzufinden,  hat[0m
    [40mmehrere ernste Mangel, aber der verbreiteteste  Mangel  ist,[0m
    [40mdass die Abhangigkeitendatei selbst nicht von den C-Include-[0m
    [40mDateien abhangig ist.  Das  bedeutet,  dass  sie  nicht  neu[0m
    [40merzeugt  wird,  wenn sich Include-Dateien verandern. Es gibt[0m
    [40mim  DAG  keine  Kante   zwischen   einem   Knotenpunkt   der[0m
    [40mAbhangigkeiten  und  einem  Knotenpunkt der Include-Dateien.[0m
    [40mWenn sich eine Include-Datei andert, weil  sie  eine  andere[0m
    [40mDatei   aufnimmt   (verschachtelte   Include),   werden  die[0m
    [40mAbhangigkeiten nicht  neu  bestimmt  und  die  C-Datei  wird[0m
    [40mmoglicherweise  nicht  neu  ubersetzt,  wodurch das Programm[0m
    [40mnicht korrekt neu gebaut wird.[0m

    [40mDas ist ein klassischer Fall von [4mzu[24m [4mwenig[24m [4mbauen[24m. Das Problem[0m
    [40mwird  dadurch verursacht, dass man Make unzulangliche Infor-[0m
    [40mmationen gibt und es dadurch veranlasst, einen  unzureichen-[0m
    [40mden DAG zu erstellen und das falsche Ergebnis zu liefern.[0m

    [40mDie traditionelle Losung ist, zu viel zu bauen:[0m














    Peter Miller          31 December 2013               Page 19





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m                +--------------------------+[0m
                    [40m|SRC := $(wildcard *.c)    |[0m
                    [40m|OBJ := $(SRC:.c=.o)       |[0m
                    [40m|test: $(OBJ)              |[0m
                    [40m|  $(CC) -o $@ $(OBJ)      |[0m
                    [40m|include dependencies      |[0m
                    [40m|.PHONY: dependencies      |[0m
                    [40m|dependencies: $(SRC)      |[0m
                    [40m|  depend.sh $(CFLAGS) \   |[0m
                    [40m|    $(SRC) > $@           |[0m
                    [40m+--------------------------+[0m
    [40mJetzt  werden selbst, wenn das Projekt aktualisiert ist, die[0m
    [40mAbhangigkeiten neu ermittelt. Wenn Projekte  gro  sind,  ist[0m
    [40mdas  eine  erhebliche  Zeitverschwendung  und kann einer der[0m
    [40mHauptgrunde dafur sein, dass Make  sehr  lange  braucht,  um[0m
    [40mherauszufinden, dass nichts zu tun ist.[0m

    [40mEs  gibt  ein  zweites  Problem: Wenn sich irgendeine der C-[0m
    [40mDateien verandert, werden  wieder  fur  alle  C-Dateien  die[0m
    [40mIncludeabhangigkeiten  neu  berechnet. Das ist genauso wenig[0m
    [40meffizient, als hatte man  ein  Makefile,  das  folgendermaen[0m
    [40maussieht:[0m

                    [40m+--------------------------+[0m
                    [40m|prog: $(SRC)              |[0m
                    [40m|  $(CC) -o $@ $(SRC)      |[0m
                    [40m+--------------------------+[0m
    [40mIn  exakter  Entsprechung  zum C-Fall benotigt man hier eine[0m
    [40mZwischenform. Dieser verleiht man gewohnlich ein  .d-Suffix.[0m
    [40mDank  der Tatsache, dass man in einer Include-Anweisung mehr[0m
    [40mals eine Datei benennen kann, existiert keine  Notwendigkeit[0m
    [40malle .d-Dateien zu verknupfen:[0m

                  [40m+------------------------------+[0m
                  [40m|SRC := $(wildcard *.c)        |[0m
                  [40m|OBJ := $(SRC:.c=.o)           |[0m
                  [40m|test: $(OBJ)                  |[0m
                  [40m|  $(CC) -o $@ $(OBJ)          |[0m
                  [40m|include $(OBJ:.o=.d)          |[0m
                  [40m|%.d: %.c                      |[0m
                  [40m|  depend.sh $(CFLAGS) $* > $@ |[0m
                  [40m+------------------------------+[0m

    [40mDiese  Form  erfordert  noch  eine  Korrektur: Genau wie die[0m
    [40mObjektdateien (.o) hangen die Abhangigkeitsdateien (.d)  von[0m
    [40mden Quelldateien und den Include-Dateien ab.[0m

         [4m[40mDatei[24m.d [4mDatei[24m.o: [4mDatei[24m.c [4mInclude[24m.h[0m

    [40mDas bedeutet, dass man wieder an dem depend.sh-Skript herum-[0m
    [40mbasteln muss:[0m






    Ulrike Amoore         31 December 2013               Page 20





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m            +-----------------------------------+[0m
                [40m|#!/bin/sh                          |[0m
                [40m|gcc -MM -MG "$@" |                 |[0m
                [40m|sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' |[0m
                [40m+-----------------------------------+[0m

    [40mDurch dieses Vorgehen bei der Bestimmung der  Abhangigkeiten[0m
    [40mder  Include-Dateien erhoht sich die Anzahl der Dateien, die[0m
    [40mdas Makfile beinhaltet, im Gegensatz zur herkommlichen Meth-[0m
    [40mode.   Dateien  zu  offnen ist jedoch weniger aufwendig, als[0m
    [40mjedesmal wieder alle Abhangigkeiten zu ermitteln.  Normaler-[0m
    [40mweise bearbeitet ein Entwickler ein oder zwei Dateien, bevor[0m
    [40mer ein Re-Build durchfuhrt; bei dieser  Methode  wird  genau[0m
    [40mdie  betroffene  Abhangigkeitsdatei  wiederhergestellt (oder[0m
    [40mmehr  als  eine,  wenn  Sie  eine  Include-Datei  bearbeitet[0m
    [40mhaben). Unterm Strich erfordert diese Vorgehensweise weniger[0m
    [40mRechenarbeit durch die CPU und weniger Zeitaufwand.[0m

    [40mMuss  bei  einem  Build  nichts  gemacht  werden,  tut  Make[0m
    [40mtatsachlich  nichts und findet das auch sehr schnell heraus.[0m

    [40mDie beschriebene Technik nimmt jedoch an, dass  Ihr  Projekt[0m
    [40mvollstandig  in  ein  Verzeichnis  hineinpasst.  Das ist bei[0m
    [40mgroen Projekten gewohnlich nicht der Fall.  Also  muss  noch[0m
    [40meinmal an dem depend.sh-Skript herumgebastelt werden:[0m

                   [40m+-----------------------------+[0m
                   [40m|#!/bin/sh                    |[0m
                   [40m|DIR="$1"                     |[0m
                   [40m|shift 1                      |[0m
                   [40m|case "$DIR" in               |[0m
                   [40m|"" | ".")                    |[0m
                   [40m|gcc -MM -MG "$@" |           |[0m
                   [40m|sed -e 's@^\(.*\)\.o:@\1.d \ |[0m
                   [40m|  \1.o:@'                    |[0m
                   [40m|;;                           |[0m
                   [40m|*)                           |[0m
                   [40m|gcc -MM -MG "$@" |           |[0m
                   [40m|sed -e "s@^\(.*\)\.o:@$DIR/\ |[0m
                   [40m|\1.d $DIR/\1.o:@"            |[0m
                   [40m|;;                           |[0m
                   [40m|esac                         |[0m
                   [40m+-----------------------------+[0m
    [40mUnd die Regel muss auch geandert werden, damit das Verzeich-[0m
    [40mnis, wie das Skript annimmt, als erster Parameter  ubergeben[0m
    [40mwird.[0m

                    [40m+---------------------------+[0m
                    [40m|%.d: %.c                   |[0m
                    [40m|  depend.sh `dirname $*` \ |[0m
                    [40m|    $(CFLAGS) $* > $@      |[0m
                    [40m+---------------------------+[0m
    [40mBitte  beachten  Sie,  dass die Namen der .d-Dateien relativ[0m
    [40mzum Verzeichnis der obersten Ebene sind. Man kann  sie  auch[0m



    Peter Miller          31 December 2013               Page 21





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mso  schreiben,  dass sie von jeder Ebene aus benutzt werden,[0m
    [40maber das geht uber den Rahmen dieses Artikels hinaus.[0m

    [1m[40m5.5.  Multiplikator[0m

    [40mAlle in diesem Kapitel  beschriebenen  Ineffizienzen  hangen[0m
    [40mzusammen.  Wenn  Sie 100 Makefile-Interpretationen fur jedes[0m
    [40mModul einmal durchfuhren, kann es sehr  lange  dauern,  1000[0m
    [40mQuelldateien  zu  uberprufen; ebenso wenn die Interpretation[0m
    [40mkomplexe  Bearbeitungsprozesse   erfordert   oder   unnotige[0m
    [40mArbeiten  ausfuhrt,  oder  beides. Das Ganzprojekt-Make muss[0m
    [40mauf der  andere  Seite  nur  ein  einziges  Makefile  inter-[0m
    [40mpretieren.[0m

    [1m[40m6.  Projekte im Vergleich zu Sandkasten[0m

    [40mDas  oben  Besprochene setzt voraus, das ein Projekt sich im[0m
    [40mRahmen eines einzigen Verzeichnisbaums befindet und das  ist[0m
    [40min der Regel der Idealfall. Die Arbeitswirklichkeit in groen[0m
    [40mSoftwareprojekten fuhrt dagegen oft zu bizarren und  wunder-[0m
    [40mvollen  Verzeichnisstrukturen,  damit die Entwickler in ver-[0m
    [40mschiedenen Bereichen  des  Projekts  arbeiten  konnen,  ohne[0m
    [40mvollstandige  Kopien  des  Projekts  zu  benotigen und damit[0m
    [40mwertvollen Speicherplatz zu verschwenden.[0m

    [40mSie konnen das hier vorgeschlagene Ganzprojekt-Make  unprak-[0m
    [40mtisch  finden,  weil  es  nicht zu den entwickelten Methoden[0m
    [40mIhres Entwicklungsprozesses passt.[0m

    [40mDas hier vorgestellte Ganzprojekt-Make hat  eine  Auswirkung[0m
    [40mauf  die Entwicklungsmethoden: Es schafft eine sauberere und[0m
    [40meinfachere Produktionsumgebung fur  Ihre  Entwickler.  Indem[0m
    [40mman  die  VPATH-Funktion  von Make anwendet, ist es moglich,[0m
    [40mdass Sie nur jene Dateien, die  Sie  bearbeiten  mussen,  in[0m
    [40mIhren  privaten Arbeitsbereich, oft auch Sandkasten genannt,[0m
    [40mkopieren.[0m

    [40mDie einfachste Weise, zu erklaren, was VPATH tut, ist,  eine[0m
    [40mAnalogie  zu  dem Suchpfad fur Include-Dateien herzustellen,[0m
    [40mindem man -I-Pfadoptionen fur den C-Compiler benutzt.  Diese[0m
    [40mOptionen  beschreiben,  wo  man  nach  Dateien  suchen muss,[0m
    [40mgenauso wie VPATH-Make anweist, wo es  nach  Dateien  suchen[0m
    [40mmuss.[0m

    [40mDurch  die Verwendung von VPATH wird es moglich, die sich im[0m
    [40mSandkasten befindenden Dateien oben  auf  der  Master-Source[0m
    [40mdes  Projekts  [4maufzustapeln[24m.  Auf  diese  Weise bekommen die[0m
    [40mDateien, die sich im Sandkasten befinden, Vorrang. Make ver-[0m
    [40mwendet  jedoch  den  gesamten  Dateienverband,  um ein Build[0m
    [40mdurchzufuhren.[0m







    Ulrike Amoore         31 December 2013               Page 22





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m[0m[47m[0m[40m                  +          +[0m
                     [40m+[4m[0m[4mM[24m[40m+[4m[0m[4master[24m [4mSour[24m[40m+[4m[0m[4mc[24m[40m+[4m[0m[4me[0m
                     [40m+   [0mmain.c [40m+   [4m[0m[4mCombined[24m [4mView[0m
                    [40m+   [0mparse.y[40m+       [0mmain.c
                     [4m[47mSand-Box[24m    [40m+     [0mparse.y
                      [47mmain.c    [40m++   [0mvariable.c
                                [40m+[0m
                    [47mvariable.c [40m+[0m


    [40mIn dieser Umgebung hat der Sandkasten dieselbe  Baumstruktur[0m
    [40mwie  die  Master-Source (Stammdatenquelle) des Projekts. Das[0m
    [40mermoglicht den  Entwicklern,  gefahrlos  modulubergreifenden[0m
    [40mKode   zu   verandern   z.   B.   bei   der  Anderung  einer[0m
    [40mModulschnittstelle.[0m

    [40mEs ermoglicht auerdem, den Sandkasten physicalisch  von  der[0m
    [40mMaster-Source  zu trennen, ihn z. B auf einem anderen Laufw-[0m
    [40merk oder in Ihrem privaten Arbeitsbereich anzulegen und  der[0m
    [40mMaster-Source  des  Projekts einen schreibgeschutzten Status[0m
    [40mzu verleihen, sofern  Sie  ein  strenges  Check-in-Verfahren[0m
    [40mhaben (oder sich zulegen wollen).[0m

    [40mBitte beachten Sie: Sie mussen nicht nur ihrem Entwicklungs-[0m
    [40mMakefilec eine VPATH-Reihe hinzufugen, sondern auch die  -I-[0m
    [40mOptionen  dem  CFLAGS-Makro,  damit der C-Compiler denselben[0m
    [40mPfad wie Make  benutzt.  Das  kann  man  einfach  mit  einem[0m
    [40m3-Zeilen-Makefile  in Ihrem Arbeitsbereich durchfuhren - Sie[0m
    [40mdefinieren erst ein Makro, dann VPATH und  fugen  schlielich[0m
    [40mdas Makefile der Master-Source des Projekts ein.[0m

    [1m[40m6.1.  VPATH-Semantik[0m

    [40mUm  das eben Erlauterte anzuwenden, mussen Sie GNU-Make 3.76[0m
    [40moder eine neuere Version verwenden.  Fur  fruhere  GNU-Make-[0m
    [40mVersionen  benotigen  Sie  Paul  Smith's  VPATH+  Patch. Den[0m
    [40mkonnen Sie bei  ftp://ftp.wellfleet.com/netman/psmith/gmake/[0m
    [40mbeziehen.[0m

    [40mDie POSIX-Semantiken von VPATH sind unzulanglich genauso wie[0m
    [40mviele existierende Make-Ausfuhrungen.  Vielleicht  uberlegen[0m
    [40mSie sich, GNU-Make zu installieren.[0m

    [1m[40m7.  Das Gesamtbild[0m

    [40mIn diesem Kapitel werden alle auf den vorangegangenen Seiten[0m
    [40merorterten Aspekte zusammengefugt  und  das  Beispielprojekt[0m
    [40mmit  seinen  getrennten  Modulen  wird vorgestellt, aber mit[0m
    [40meinem Gesamtprojekt-Makefile. Die Verzeichnisstruktur unter-[0m
    [40mscheidet  sich  wenig  von  der  rekursiven,  auer  dass die[0m
    [40mtieferliegenden Makefiles  durch  modulspezifische  Include-[0m
    [40mDateien ersetzt werden:[0m





    Peter Miller          31 December 2013               Page 23





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m                      +++[0m
                          [40m++[4mP[24m+[4mr[24m|[4moject[0m
                           [40m++++Maanktefile[0m
                           [40m|++ +|module.mk[0m
                           [40m| - +|main.c[0m
                           [40m++++b+ee[0m
                           [40m| + +|module.mk[0m
                           [40m| + +|parse.y[0m
                           [40m+ +|depend.sh[0m


    [40mDas Makefile sieht folgendermaen aus:[0m

          [40m+-----------------------------------------------+[0m
          [40m|MODULES := ant bee                             |[0m
          [40m|# look for include files in                    |[0m
          [40m|#   each of the modules                        |[0m
          [40m|CFLAGS += $(patsubst %,-I%,\                   |[0m
          [40m|  $(MODULES))                                  |[0m
          [40m|# extra libraries if required                  |[0m
          [40m|LIBS :=                                        |[0m
          [40m|# each module will add to this                 |[0m
          [40m|SRC :=                                         |[0m
          [40m|# include the description for                  |[0m
          [40m|#   each module                                |[0m
          [40m|include $(patsubst %,\                         |[0m
          [40m|    %/module.mk,$(MODULES))                    |[0m
          [40m|# determine the object files                   |[0m
          [40m|OBJ :=                    \                    |[0m
          [40m|  $(patsubst %.c,%.o,     \                    |[0m
          [40m|    $(filter %.c,$(SRC))) \                    |[0m
          [40m|  $(patsubst %.y,%.o,     \                    |[0m
          [40m|    $(filter %.y,$(SRC)))                      |[0m
          [40m|# link the program                             |[0m
          [40m|prog: $(OBJ)                                   |[0m
          [40m|  $(CC) -o $@ $(OBJ) $(LIBS)                   |[0m
          [40m|# include the C include                        |[0m
          [40m|#   dependencies                               |[0m
          [40m|include $(OBJ:.o=.d)                           |[0m
          [40m|# calculate C include                          |[0m
          [40m|#   dependencies                               |[0m
          [40m|%.d: %.c                                       |[0m
          [40m|  depend.sh `dirname $*.c` $(CFLAGS) $*.c > $@ |[0m
          [40m+-----------------------------------------------+[0m
    [40mDas  erscheint sehr lang, aber es enthalt alle ublichen Ele-[0m
    [40mmente an einer Stelle, so dass die  Make-Include-Dateien  in[0m
    [40mden einzelnen Modulen sehr kurz sein konnen.[0m

    [40mDie ant/module.mk Datei sieht folgendermaen aus:[0m

                    [40m+--------------------------+[0m
                    [40m|SRC += ant/main.c         |[0m
                    [40m+--------------------------+[0m
    [40mDie bee/module.mk Datei sieht so aus:[0m



    Ulrike Amoore         31 December 2013               Page 24





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m                +--------------------------+[0m
                    [40m|SRC += bee/parse.y        |[0m
                    [40m|LIBS += -ly               |[0m
                    [40m|%.c %.h: %.y              |[0m
                    [40m|  $(YACC) -d $*.y         |[0m
                    [40m|  mv y.tab.c $*.c         |[0m
                    [40m|  mv y.tab.h $*.h         |[0m
                    [40m+--------------------------+[0m

    [40mBeachten  Sie  bitte,  dass  die  Built-in-Regeln fur die C-[0m
    [40mDateien verwendet werden, aber wir benotigen ein  spezielles[0m
    [40myacc-Verfahren, um die erzeugte .h-Datei zu bekommen.[0m

    [40mDie Einsparungen in diesem Beispiel wirken unerheblich, weil[0m
    [40mdas Makefile der obersten Ebene so gro ist. Aber stellen Sie[0m
    [40msich  vor, es handele sich um 100 Module, jedes mit ein paar[0m
    [40mfunktionellen, modulspezifischen Zeilen. Insgesamt  erreicht[0m
    [40mman  oft, ohne an Modularitat zu verlieren, einen geringeren[0m
    [40mZeitaufwand als bei Verwendung eines rekursiven Makes.[0m

    [40mDer entsprechende DAG des Makefiles sieht, nachdem man  alle[0m
    [40mEinfugungen vorgenommen hat, folgendermaen aus:[0m
    [40m[47m[40m[0m
                                [40mprog[0m



                          [47mmain.o   parse.o[0m
                            [40mmain.d|  parse.d|[0m

                      [40mmain.c   parse.h  parse.c[0m



                                   [40mparse.y[0m



    [40mDie      Knotenpunkte      und      Kanten      fur      die[0m
    [40mInklude-Dateiabhangikeitsdateien sind  ebenfalls  vorhanden,[0m
    [40mda  sie  wichtig  sind,  damit  Make fehlerlos funktionieren[0m
    [40mkann.[0m

    [1m[40m7.1.  Nebeneffekte[0m

    [40mEs gibt eine Reihe wunschenswerter  Nebeneffekte,  wenn  man[0m
    [40mein einziges Makefile verwendet.[0m

    +o[40m Die  -j-Option  des GNU-Makes fur parallel laufende Builds[0m
      [40mfunktioniert  besser  als  vorher.  Sie  kann  sogar  mehr[0m
      [40mvoneinander  unabhangige  Vorgange  zugleich ausfuhren und[0m
      [40mleidet nicht mehr an subtilen Fehlern.[0m





    Peter Miller          31 December 2013               Page 25





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    +o[40m Die -k-Option des allgemeinen Makes, die dafur sorgt, dass[0m
      [40mMake  selbst  angesichts  von  Fehlern so weit wie moglich[0m
      [40mweiter arbeitet, funktioniert ebenfalls besser als vorher.[0m
      [40mSie findet sogar mehr Material, mit dem sie weiterarbeiten[0m
      [40mkann.[0m

    [1m[40m8.  Literaturstudie[0m

    [40mWie ist es moglich das wir 20 Jahre lang Make falsch  einge-[0m
    [40msetzt  haben?  Wie  ist  es  moglich, dass das Verhalten von[0m
    [40mMake,  das  wir  bisher  seiner  begrenzten   Funktionalitat[0m
    [40mzugeschrieben haben, sich nun als falsche Anwendung von Make[0m
    [40mherausstellt?[0m

    [40mDer Autor begann uber  die  Ideen,  die  in  diesem  Artikel[0m
    [40mvorgestellt  werden,  nachzudenken,  als  er  sich mit einer[0m
    [40mReihe halicher Build-Probleme in ganzlich  unterschiedlichen[0m
    [40mProjekten  aber  mit gemeinsamen Symptomen konfrontiert sah.[0m
    [40mIndem er von den einzelnen Projekten Abstand  nahm  und  die[0m
    [40mGemeinsamkeiten  der  Probleme  eingehend untersuchte, wurde[0m
    [40mihm moglich, eine Regelmaigkeit zu erkennen. Die meisten von[0m
    [40muns  sind zu sehr mit den Flickarbeiten fur eine fehlerfreie[0m
    [40mFunktion des mangelhaften Builds beschaftigt, als  dass  sie[0m
    [40mZeit   finden  wurden,  die  Sache  einmal  mit  Distanz  zu[0m
    [40mbegutachten    und    sich    einen    Gesamteindruck    der[0m
    [40mSchwierigkeiten  zu  verschaffen.  Besonders  dann, wenn das[0m
    [40mfragliche Produkt offensichtlich arbeitet und  das  seit  20[0m
    [40mJahren.[0m

    [40mEs ist interssant, dass die Probleme des rekursiven Makes in[0m
    [40mden einschlagigen Buchern, auf  die  sich  Unixprogrammierer[0m
    [40mverlassen, wenn sie prazisen praktischen Rat benotigen, kaum[0m
    [40merwahnt werden.[0m

    [1m[40m8.1.  Das Original[0m

    [40mDas originale Make-Handbuch [feld78] enthalt keinen  Hinweis[0m
    [40mauf  rekursives  Make,  und  erst recht keine Erorterung der[0m
    [40mrelativen  Vorteile  des  Ganzprojekt-Makes  gegenuber   dem[0m
    [40mrekursiven Make.[0m

    [40mEs  uberrascht  nicht,  dass das Originalhandbuch rekursives[0m
    [40mMake nicht erwahnte. Damals passten Unix-Pojekte  gewohnlich[0m
    [40min eine einziges Verzeichnis.[0m

    [40mDas ist vielleicht auch ein Grund, warum sich das "ein Make-[0m
    [40mfile in jedem Verzeichnis"-Konzept  so  in  der  kollektiven[0m
    [40mUnix-Entwicklungsdenkweise festsetzte.[0m

    [1m[40m8.2.  GNU-Make[0m

    [40mDas GNU-Make-Handbuch [stal93] beschaftigt sich auf mehreren[0m
    [40mSeiten mit  dem  rekursiven  Make;  die  Erlauterung  seiner[0m
    [40mVorzuge   oder   der  Technik  ist  auf  folgende  Bemerkung[0m



    Ulrike Amoore         31 December 2013               Page 26





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40mreduziert:[0m

         [40m"Diese Technik ist nutzlich,  wenn  Sie  getrennte[0m
         [40mMakefiles fur verschiedene Teilsysteme, die zusam-[0m
         [40mmen ein groeres System bilden, anlegen wollen."[0m

    [40mKein Wort  uber  die  Schwierigkeiten,  auf  die  Sie  stoen[0m
    [40mkonnten.[0m

    [1m[40m8.3.  Projektverwaltung mit Makefiles[0m

    [40mDas  Nutshell-Make-Handbuch  [talb91]  preist  das rekursive[0m
    [40mMake besonders als dem Ganzprojekt-Make uberlegen an:[0m

         [40mDer "sauberste" Weg, ein Build zu erstellen,  ist,[0m
         [40mindem  man  in  jedem  Verzeichnis ein gesondertes[0m
         [40mMakefile anlegt und sie durch  ein  Haupt-Makefile[0m
         [40mverbindet,  das  eine rekursive Make-Funktion her-[0m
         [40mvorruft. Wenn diese Technik auch umstandlich  ist,[0m
         [40mist  sie  doch  leichter  zu  verwalten  als  eine[0m
         [40meinzige, riesenhafte Datei, die mehrere  Verzeich-[0m
         [40mnisse abdeckt."  (Seite 65)[0m

    [40mDas  widerspricht genau dem Rat, den das Buch nur zwei Para-[0m
    [40mgraphen weiter vorne erteilt:[0m

         [40m"Make ist am glucklichsten,  wenn  Sie  all  seine[0m
         [40mDateien in einem Verzeichnis lassen" (Seite 64)[0m

    [40mAber  das Buch versaumt es, den Widerspruch in diesen beiden[0m
    [40mAussagen zu erortern, und fahrt stattdessen fort,  eine  der[0m
    [40mherkommlichen  Moglichkeiten zu beschreiben, mit der man die[0m
    [40mSymptome   eines   durch   rekursives   Make    verursachten[0m
    [40munvollstandigen DAGs zu umgehen versucht.[0m

    [40mDieses Buch bietet einen Anhaltspunkt, warum rekursives Make[0m
    [40mseit so vielen Jahren in dieser Weise verwendet  wurde.  Sie[0m
    [40msehen,  wie  die  beiden  o.  g.  Aussagen das Konzept eines[0m
    [40mVerzeichnisses mit dem Konzept eines Makefiles  verwechseln.[0m

    [40mDieser  Artikel  legt  eine  einfache Anderung der Denkweise[0m
    [40mnahe: In Verzeichnisbaumen, egal  wie  verzweigt  sie  sind,[0m
    [40mwerden  Dateien gespeichert; Makefiles dagegen sind dazu da,[0m
    [40mdie Beziehungen dieser Dateien untereinander zu beschreiben,[0m
    [40mgleichgultig wieviele Dateien es sind.[0m

    [1m[40m8.4.  BSD-Make[0m

    [40mDie  Anleitung  fur  BSD-Make [debo88] erwahnt das rekursive[0m
    [40mMake  uberhaupt  nicht,  aber  sie  ist  eines  der  wenigen[0m
    [40mHandbucher,  das,  wenn  auch  sehr  kurz,  tatsachlich  die[0m
    [40mBeziehung zwischen Makefile und DAG beschreibt  (Seite  30).[0m
    [40mDaher stammt auch dieses wunderbare Zitat:[0m




    Peter Miller          31 December 2013               Page 27





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m     "Falls Make nicht das macht, was Sie erwarten, ist[0m
         [40mdie Wahrscheinlichkeit sehr gro, dass das Makefile[0m
         [40mfalsch ist."  (Seite 10)[0m

    [40mDas  ist  eine  kurze  und  pragnante Zusammenfassung dieses[0m
    [40mArtikels.[0m

    [1m[40m9.  Zusammenfassung[0m

    [40mDieser Artikel erlautert  einige  miteinander  in  Beziehung[0m
    [40mstehende  Probleme und zeigt, dass es sich nicht, wie allge-[0m
    [40mmein angenommen, um Make anhaftende Unzulanglichkeiten  han-[0m
    [40mdelt,  sondern  dass  sie  eine  Folge davon sind, dass Make[0m
    [40mfalsche Informationen eingegben wurden.  Hier  arbeitet  das[0m
    [40malte "Garbage in, Garbage out"-Prinzip (wo Mull hineinkommt,[0m
    [40mkommt Mull heraus). Der Fehler besteht darin, dass  man  das[0m
    [40mMakefile  in  unvollstandige  Teilstucke  zerlegt, denn Make[0m
    [40mkann nur mit einem vollstandigen DAG fehlerfrei arbeiten.[0m

    [40mDas  erfordert  ein  Umdenken.  In  Verzeichnisbaume  werden[0m
    [40mlediglich  Dateien gespeichert, in Makefiles hingegen werden[0m
    [40mHinweise auf die  Informationen  uber  die  Beziehungen  der[0m
    [40mDateien  untereinander  gespeichert.  Bringen  Sie das nicht[0m
    [40mdurcheinander, denn es ist genauso wichtig  die  Beziehungen[0m
    [40mzwischen    Dateien    in    verschiedenen    Verzeichnissen[0m
    [40mwiederzugeben, wie die Beziehungen zwischen Dateien im  gle-[0m
    [40michen Verzeichniss. Daraus folgt, dass es genau ein Makefile[0m
    [40mfur ein Projekt geben sollte, aber der Groteil der Beschrei-[0m
    [40mbung  kann  man durch Verwendung von Make-Include-Dateien in[0m
    [40mden einzelnen Verzeichnissen, die die Teilmenge der Projekt-[0m
    [40mdateien  in den jeweiligen Verzeichnissen beschreiben, hand-[0m
    [40mhaben. Dieses Vorgehen ist genauso  modular,  als  ware  ein[0m
    [40mMakefile in jedem Verzeichnis.[0m

    [40mEs  wurde  gezeigt, dass bei Verwendung des Ganzprojekt-Make[0m
    [40meine Entwicklungsproduktion und eine  Vollproduktion  gleich[0m
    [40mkurze  Laufzeiten  haben. Angesichts der gleichen Laufzeiten[0m
    [40mwiegen die  durch  die  genaueren  Abhangigkeiten  erzielten[0m
    [40mVorteile  umso  schwerer  und  bewirken, dass dieser Prozess[0m
    [40mtatsachlich schneller und genauer lauft, als wenn das rekur-[0m
    [40msive Make angewendet wurde.[0m

    [1m[40m9.1.  Projektubergreifende Abhangigkeiten[0m

    [40mIn Unternehmen mit einer starken Neigung zur Mehrfachverwen-[0m
    [40mdung kann die Verwirklichung  eines  Ganzprojekt-Makes  eine[0m
    [40mHerausforderung  darstellen.  Sich dieser Herausforderung zu[0m
    [40mstellen, mag erfordern, dass man sich  einen  Gesamteindruck[0m
    [40mder Situation verschafft.[0m

    +o[40m Es kann sein, dass ein Modul von zwei Programmen gemeinsam[0m
      [40mverwendet wird, weil die  Programme  nahe  verwandt  sind.[0m
      [40mNaturlich  gehoren  die  zwei  Programme und das gemeinsam[0m
      [40mgenutzte Modul zu demselben Projekt (das Modul  kann  auch[0m



    Ulrike Amoore         31 December 2013               Page 28





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m  unabhangig   sein,   die   Programme  jedoch  nicht).  Die[0m
      [40mAbhangigkeiten mussen ausdrucklich  angegeben  werden  und[0m
      [40mAnderungen  des  Moduls  ziehen nach sich, dass beide Pro-[0m
      [40mgramme entsprechend neu ubersetzt und neu gebunden  werden[0m
      [40mmussen.  Vereinigt man sie alle in einem einzigen Projekt,[0m
      [40mkann das Ganzprojekt-Make dies leisten.[0m

    +o[40m Es ist moglich, dass ein Modul von zwei Projekten  gemein-[0m
      [40msam  genutzt  wird,  weil  ihr  Wirkungsbereich ineinander[0m
      [40mgreift. Moglicherweise ist Ihr  Projekt  groer,  als  Ihre[0m
      [40mgegenwartige   Verzeichnisstuktur   aufnehmen   kann.  Die[0m
      [40mAbhangigkeiten mussen ausdrucklich  angegeben  werden  und[0m
      [40mAnderungen  am  Modul ziehen nach sich, dass beide Pojekte[0m
      [40mentsprechend neu ubersetzt und neu gebunden werden mussen.[0m
      [40mVereinigt man sie alle in einem einzigen Projekt, kann das[0m
      [40mGanzprojekt-Make dies leisten.[0m

    +o[40m Es ist normal, die Kanten zwischen Ihrem Projekt und ihrem[0m
      [40mBetriebssystem   oder   dritten  installierten  Werkzeugen[0m
      [40mwegzulassen. Das ist so normal, dass sie in den  Makefiles[0m
      [40min  diesem  Artikel  und  bei den vordefinierten Regeln im[0m
      [40mMake-Programm ignoriert werden. Module, die  von  mehreren[0m
      [40mProjekten gemeinsam genutzt werden, konnten in diese Kate-[0m
      [40mgorie fallen. Werden sie geandert, bauen Sie Ihre Projekte[0m
      [40mextra neu oder beziehen die Anderungen stillschweigend bei[0m
      [40mder nachsten Produktion mit ein. In  beiden  Fallen  geben[0m
      [40mSie  die  Abhangigkeiten  nicht  ausdrucklich  an  und das[0m
      [40mGanzprojekt-Make findet keine Anwendung.[0m

    +o[40m Es ist der Wiederverwendung moglicherweise dienlich,  wenn[0m
      [40mdas  Modul als Schablone verwendet und Abweichnungen zwis-[0m
      [40mchen den Projekten als normal  angesehen  werden.  Kopiert[0m
      [40mman   des   Modul   fur  jedes  Projekt,  konnte  man  die[0m
      [40mAbhangigkeiten ausdrucklich angeben. Es hat  jedoch  einen[0m
      [40mzusatzlichen  Aufwand  zur  Folge, wenn an dem gemeinsamen[0m
      [40mTeil Anderungen erforderlich werden.[0m

    [40mIn einer von  Mehrfachverwendung  stark  gepragten  Umgebung[0m
    [40mwird  das Strukturieren von Abhangigkeiten zu einer Ubung in[0m
    [40mRisikomanagement.  Welche  Gefahr  besteht,  dass   fehlende[0m
    [40mStucke  des  DAGs Ihr Pojekt schadigen?  Wie wichtig ist es,[0m
    [40mneu zu bauen, wenn ein Modul sich  verandert?  Welches  sind[0m
    [40mdie  Folgen,  wenn es nicht automatisch neu produziert wird?[0m
    [40mWoher wissen Sie ,  wann  ein  Neubau  notwendig  ist,  wenn[0m
    [40mAbhangigkeiten nicht ausdrucklich genannt sind? Welches sind[0m
    [40mdie Konsequenzen, wenn man vergisst, neu zu bauen? ...[0m

    [1m[40m9.2.  Die Rendite[0m

    [40mEinige der Techniken, die in diesem Artikel beschrieben wur-[0m
    [40mden,  beschleunigen  ihren Buildvorgang sogar dann, wenn Sie[0m
    [40mrekursives Make beibehalten. Aber das ist nicht das Anliegen[0m
    [40mdieses Artikels, eher ein nutzlicher Umweg. Die Hauptaussage[0m
    [40mist,  dass  Sie  korrektere  Produktionen   Ihres   Projekts[0m



    Peter Miller          31 December 2013               Page 29





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40merhalten,  wenn  Sie das Ganzprojekt-Make anstatt des rekur-[0m
    [40msiven Makes anwenden.[0m

    +o[40m Make bedarf nicht mehr und oft sogar weniger Zeit, um her-[0m
      [40mauszufinden, das es nichts zu tun braucht.[0m

    +o[40m Die  gesamte  Eingabe fur Make ist nicht umfangreicher und[0m
      [40mkomplexer, oft sogar weniger umfangreich und weniger  kom-[0m
      [40mplex.[0m

    +o[40m Im  Ganzen  sind  die  Eingabedaten fur Make nicht weniger[0m
      [40mmodular, als bei Anwendung des rekursiven Makes.[0m

    +o[40m Die Pflege des Makefiles ist nicht aufwendiger, oft  sogar[0m
      [40mgeringer.[0m

    [40mDie  angeblichen  Nachteile der Anwendung eines Ganzprojekt-[0m
    [40mMakes  gegenuber  dem  rekursiven  Make   sind   oft   nicht[0m
    [40muberpruft.   Wieviel   Zeit   wird   damit  verbracht,  her-[0m
    [40mauszufinden,  warum  Make  etwas  Unerwartetes  getan   hat?[0m
    [40mWieviel  Zeit  wird  damit  verbracht,  an dem Build-Prozess[0m
    [40mherumzubasteln? Diese Tatigkeiten werden  oft  als  normaler[0m
    [40mEntwicklungsaufwand angesehen.[0m

    [40mDie  Projektproduktion  ist eine wesentliche Tatigkeit. Wenn[0m
    [40msie schlecht funktioniert, werden auch die Entwicklung,  die[0m
    [40mFehlerbehebung  und  das  Testen in Mitleidenschaft gezogen.[0m
    [40mDie Projektproduktion sollte so einfach sein, dass  sie  der[0m
    [40mneuste  Mitarbeiter  -  ohne eine noch so kurze schriftliche[0m
    [40mAnleitung - sofort durchfuhren kann. Sie sollte  so  einfach[0m
    [40msein,   dass  sie  so  gut  wie  keinen  Entwicklungsaufwand[0m
    [40merfordert. Ist Ihr Produktionsprozess so einfach?[0m

    [1m[40m10.  Literaturverweise[0m


         [1m[40mdebo88: [22mAdam de Boor (1988).  [4mPMake[24m [4m-[24m [4mA[24m [4mTutorial[24m.  Uni-[0m
    [40mversity of California, Berkeley[0m

         [1m[40mfeld78: [22mStuart I. Feldman (1978).  [4mMake[24m [4m-[24m [4mA[24m [4mProgram[24m [4mfor[0m
    [4m[40mMaintaining[24m [4mComputer[24m [4mPrograms[24m.  Bell Laboratories  Computing[0m
    [40mScience Technical Report 57[0m

         [1m[40mstal93:  [22mRichard M. Stallman and Roland McGrath (1993).[0m
    [4m[40mGNU[24m [4mMake:[24m [4mA[24m [4mProgram[24m [4mfor[24m [4mDirecting[24m [4mRecompilation[24m.  Free Soft-[0m
    [40mware Foundation, Inc.[0m

         [1m[40mtalb91:  [22mSteve  Talbott (1991).  [4mManaging[24m [4mProjects[24m [4mwith[0m
    [4m[40mMake,[24m [4m2nd[24m [4mEd[24m.  O'Reilly & Associates, Inc.[0m








    Ulrike Amoore         31 December 2013               Page 30





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    [40m                +--------------------------+[0m
                    [40m|Miller,   P.A.    (1998), |[0m
                    [40m|[4mRecursive[24m [4mMake[24m [4mConsidered[24m |[0m
                    [40m|[4mHarmful[24m, AUUGN Journal of |[0m
                    [40m|AUUG   Inc.,  19(1),  pp. |[0m
                    [40m|14-25.                    |[0m
                    [40m+--------------------------+[0m
    [40mSee http://www.cmmagazin.de December 2002 issue for the HTML[0m
    [40mversion of the transaltion.[0m

    [1m[40m11.  Uber den Autor[0m

    [40mPeter Miller hat viele Jahre lang in der Software R&D Indus-[0m
    [40mtrie gearbeitet, vor allem auf UNIX-Systemen. In dieser Zeit[0m
    [40mschrieb er Werkzeuge wie Aegis (ein System des Software Con-[0m
    [40mfiguration Management) und Cook (eine weitere Make-Version),[0m
    [40mbeide  kann man frei uber das Internet beziehen. Die Betreu-[0m
    [40mung bei der Verwendung dieser Werkzeuge auf vielen  Internet[0m
    [40mSites  ermoglichte  den  Einblick,  der  zu  diesem  Artikel[0m
    [40mfuhrte.[0m

    [40mWenn Sie Interesse am Bezug der freien Software  des  Autors[0m
    [40mhaben,   besuchen  Sie  bitte:  http://www.canb.auug.org.au-[0m
    [40m/~millerp/[0m

































    Peter Miller          31 December 2013               Page 31


