






                   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
         Analyse 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           3 January 2004                 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+o+dule2
                             +-++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;  All  rights
    reserved.
    German translation Copyright (C) 2002  CM-Magazin.



    Ulrike Amoore          3 January 2004                 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           3 January 2004                 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          3 January 2004                 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:
                     
                                prog



                          main.o   parse.o


                      main.c   parse.h  parse.c



    Aufgrund der Pfeile, die die  Ordnung  der  Beziehungen  der
    Dateien  zueinander  ausdrucken,  handelt  es  sich um einen
    azyklischen  Graphen.  Wenn  es  den  Pfeilen  zufolge  eine
    kreisformige Abhangigkeit gabe, lage ein Fehler vor.

    Beachten  Sie  bitte,  dass  die  Objektdateien (.o) von den
    Include-Dateien (.h) abhangig sind,  obwohl  es  die  Quell-
    dateien  (.c) sind, die das Einfugen vornehmen. Das hat fol-
    genden Grund: Wird eine  Include-Datei  geandert,  sind  die
    Objektdateien nicht mehr aktuell, nicht die Quelldateien.

    Der  zweite  Schritt  des Make-Prozesses ist eine Postorder-
    Traversierung des DAG. Das  bedeutet,  dass  die  abhangigen
    Knotenpunkte  zuerst besucht werden. Die eigentliche Reihen-
    folge der Traversierung ist nicht festgelegt, aber die meis-
    ten  Make-Anwendungen gehen von oben nach unten und bei Kan-
    ten unter demselben Knotenpunkt von links  nach  rechts  und



    Peter Miller           3 January 2004                 Page 5





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    die  meisten  Projekte  verlassen  sich  stillschweigend auf
    dieses Verhalten. Die  zuletzt  geanderten  Versionen  aller
    Dateien  werden  untersucht  und  eine  weiter oben liegende
    Datei wird als nicht mehr aktuell  eingestuft,  wenn  irgen-
    deine  der darunterliegenden Dateien, von denen sie abhangig
    ist, junger ist. Wenn eine Datei als nicht mehr akuell klas-
    sifiziert  wurde,  wird die zu der entsprechenden Graphkante
    gehorende  Aktion  ausgefuhrt  (in  dem  oben   aufgefuhrten
    Beispiel  ware das ein Kompilations- oder ein Bindeprozess).

    Die Anwendung von rekursivem Make beeinflusst  beide  Phasen
    der  Make-Operation: Es veranlasst Make, einen ungenauen DAG
    zu erstellen und es zwingt Make, den DAG  in  einer  unange-
    brachten Reihenfolge zu traversieren.

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

    Um  die  Auswirkungen  des  rekursiven Makes zu untersuchen,
    teilen wir das obige Beispiel  in  zwei  Module  ein.  Jedes
    Modul  hat  sein  eigenes  Makefile und ein Makefile fur die
    oberste Ebene, deren Aufgabe es ist, jedes  der  Modul-Make-
    files aufzurufen.

    Dieses  Beispiel  ist absichtlich konstruiert und zwar durch
    und  durch.  Aber  jede  Modularitat  in  Projekten  ist  in
    gewisser  Weise ein Konstrukt. Bedenken Sie: Bei vielen Pro-
    jekten ebnet der Linker am Ende alles wieder ein.

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

    Das Makefile der obersten Ebene  sieht  oft  sehr  wie  eine
    Shell-Befehlsdatei aus:

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






    Ulrike Amoore          3 January 2004                 Page 6





    CM Magazin, Dec-2002          Probleme durch rekursives Make


                  +------------------------------+
                  |all: main.o                   |
                  |main.o: main.c ../bee/parse.h |
                  |  $(CC) -I../bee -c main.c    |
                  +------------------------------+
    und der entsprechende DAG sieht so aus:
                         
                               main.o



                          main.c    parse.h

    Das bee/Makefile sieht so aus:

                   +----------------------------+
                   |OBJ = ../ant/main.o parse.o |
                   |all: prog                   |
                   |prog: (OBJ)                 |
                   |  $(CC) -o $@ $(OBJ)        |
                   |parse.o: parse.c parse.h    |
                   |  $(CC) -c parse.c          |
                   +----------------------------+
    und der entsprechende DAG sieht so aus:
                       
                              prog



                        main.o    parse.o


                             parse.h  parse.c



    Schauen  Sie  sich die DAGs genau an. Sie stellen fest, dass
    keiner von ihnen komplett ist. Beiden DAGs fehlen Knoten und
    Kanten.  Wenn  die  vollstandige Produktion von der obersten
    Ebene ausgefuhrt wird, funktioniert alles.

    Aber was passiert, wenn eine kleine Anderung eintritt?   Was
    wurde  passieren, wenn parse.c und parse.h von einer parse.y
    Yacc Grammatik erzeugt wurden? Dann wurden  folgende  Zeilen
    dem bee/Makefile hinzugefugt:

                    +--------------------------+
                    |parse.c parse.h: parse.y  |
                    |  $(YACC) -d parse.y      |
                    |  mv y.tab.c parse.c      |
                    |  mv y.tab.h parse.h      |
                    +--------------------------+
    Und die entsprechenden Veranderungen des DAGs sahen so aus:




    Peter Miller           3 January 2004                 Page 7





    CM Magazin, Dec-2002          Probleme durch rekursives Make


                       
                              prog



                        main.o    parse.o


                             parse.h  parse.c



                                  parse.y



    Diese Veranderung hat eine einfache Folge: Wenn parse.y edi-
    tiert wird, wird main.o nicht correct aufgebaut.  Das  ruhrt
    daher,  dass  der  DAG fur ant nur einige der Abhangigkeiten
    von main.o kennt, wahrend der DAG fur bee  sogar  keine  von
    ihnen kennt.

    Um  zu verstehen, warum das passiert, ist es notwendig, sich
    die Aktionen, die Make von der obersten  Ebene  aus  untern-
    immt, anzuschauen. Nehmen Sie einmal an, dass das Projekt in
    sich konsistent ist. Jetzt editieren Sie  parse.y,  so  dass
    die    generierte   parse.h   nicht-triviale   Veranderungen
    aufweist. Wenn nun das Haupt-Make aufgerufen wird, wird erst
    ant  und  dann  bee  besucht. Aber ant/main.o ist noch nicht
    rekompiliert, weil bee/parse.h noch nicht regeneriert  wurde
    und  deshalb  noch  nicht  anzeigt,  dass  main.o nicht mehr
    aktuell ist. Das ist auch immer noch nicht  der  Fall,  wenn
    das  rekursive  Make  bee besucht, wobei parse.c und parse.h
    und zuletzt parse.o rekonstruiert werden. Wenn das  Programm
    gelinkt  wird,  sind  main.o  und parse.o in erheblichem Mae
    nicht kompatibel. D. h. das Programm funktioniert nicht.

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

    Es gibt drei  herkommliche  Korrekturmoglichkeiten  fur  die
    oben beschriebene Storung.

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

    Die  erste  ist, die Anordnung der Module in dem Haupt-Make-
    file von Hand zu berichtigen. Die  Frage  ist,  warum  diese
    Korrektur uberhaupt notwendig ist. Schlielich soll Make eine
    Expertensystem sein. Hat Make irgendeinen Fehler  oder  ging
    etwas anderes schief?

    Zur  Beantwortung  dieser  Frage muss man nicht den Graphen,
    sondern  die  Anordnung  der   Traversierung   des   Graphen
    anschauen.  Um  fehlerlos  zu  arbeiten, muss Make eine Pos-
    torder-Traversierung vornehmen, aber dadurch, dass  der  DAG



    Ulrike Amoore          3 January 2004                 Page 8





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    in  zwei Teile geteilt wurde, war es Make nicht mehr moglich
    den Graphen in der notwendigen Reihenfolge zu traversieren -
    stattdessen   wurde   von   dem   Projekt  eine  Reihenfolge
    vorgeschrieben. Eine Reihenfolge, die, wenn man  den  Origi-
    nalgraphen betrachtet, schlichtweg falsch ist. Indem man das
    Haupt-Makefile korrigiert, stellt man eine Reihenfolge  her,
    die  der,  die  Make  hatte  benutzen  konnen,  ahnlich ist.
    Solange, bis die nachste Abhangigkeit hinzugefugt wird...

    Bitte beachten Sie, dass paralleles Build  (make  -j)  viele
    der  bei  der  manuellen Umstrukturierung gemachten Annahmen
    stillschweigend auer Kraft setzt, wodurch diese Losung nutz-
    los  wird.  Auerdem  fuhren alle untergeordneten Makes eben-
    falls mehrere Aktionen gleichzeitig aus.

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

    Bei der zweiten herkommlichen Losung lasst  man  das  Haupt-
    Makefile  mehrere  Male  durchlaufen.  Das sieht ungefahr so
    aus:

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

    Dadurch wird die Produktionszeit verdoppelt.  Aber  das  ist
    nicht  alles:  Es  gibt keine Garantie, dass zwei Durchlaufe
    ausreichen! Die Hochstzahl der Durchlaufe ist  nicht  einmal
    proportional  zu der Anzahl der Module, sondern proportional
    zu der Anzahl der Graphkanten, die Modulgrenzen kreuzen.

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

    Wir haben schon ein Beispiel  gesehen,  bei  dem  rekursives
    Make  zu  wenig baute, aber ein anderes verbreitetes Problem
    ist, dass zu viel gebaut wird. Bei der dritten herkommlichen
    Losung  fugt  man  dem  ant/Makefile  sogar noch mehr Zeilen
    hinzu:

                    +--------------------------+
                    |.PHONY: ../bee/parse.h    |
                    |../bee/parse.h:           |
                    |    cd ../bee; \          |
                    |    make clean; \         |
                    |    make all              |
                    +--------------------------+




    Peter Miller           3 January 2004                 Page 9





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Das bedeutet, dass immer wenn main.o  gebaut  wird,  parse.h
    als nicht aktuell betrachtet wird. Alle Inhalte von bee wer-
    den jedesmal von neuem gebaut  einschlielich  parse.h.  Auch
    main.o  wird  immer  wieder neu gebaut, selbst wenn alles in
    sich konsistent war.

    Beachten Sie bitte, dass bei dieser Losung make -j (paralle-
    les    Build)    viele    der    angenommenen    Anordnungen
    stillschweigend auer Kraft setzt, wodurch diese Losung nutz-
    los  wird,  weil  alle der untergeordneten Makes ihre Builds
    gleichzeitig durchfuhren(clean und dann all), wobei sie sich
    standig gegenseitig storen.

    [1m4.  Vorsorge[0m

    Die  obige  Analyse  basiert auf einer einfachen Aktion: Der
    DAG wurde kunstlich  in  unvollstandige  Stucke  unterteilt.
    Diese  Unterteilung hat all die Probleme, die man von rekur-
    siv verwendetem Make kennt, zur Folge.

    Hat Make es nicht richtig verstanden? Nein,  das  ist  nicht
    der  Grund.  Hier  liegt  ein Fall des uralten GIGO-Prinzips
    (Garbage in, Garbage out) vor: Wo man Mull hereintut,  kommt
    Mull heraus. Unvollstandige Makefiles sind fehlerhafte Make-
    files.

    Wenn Sie diese Probleme vermeiden wollen, zerlegen  Sie  den
    DAG  nicht  in einzelne Teile. Verwenden sie stattdessen ein
    einziges Makefile fur das ganze Projekt.  Die  Rekursion  an
    sich ist nicht schadlich, sondern das verstummelte Makefile,
    das man fur die Rekursion verwendet, ist falsch. Es ist kein
    Fehler von Make, dass das rekursive Make nicht funktioniert;
    es macht das bestmogliche aus den mangelhaften Eingabeinfor-
    mationen.

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

    Das sind stichhaltige Einwande und oft ziehen  Make-Benutzer
    aus  ihnen den Schluss, dass es keinerlei kurz- oder langer-
    fristigen Nutzen fur sie bringen wurde, ihren  Build-Prozess
    einmal zu uberarbeiten. Diese Schlussfolgerung ist auf uber-
    holten,  falschen  Annahmen  gegrundet,  die   sich   jedoch
    hartnackig halten.

    In  den  nachsten  Abschnitten wird der Reihe nach auf jeden
    dieser Einwande eingegangen.




    Ulrike Amoore          3 January 2004                Page 10





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Ware die vollstandige Produktionsbeschreibung fur das  ganze
    Projekt  in  einem  einzigen  Makefile  untergebracht, wurde
    dieser Satz sicherlich zutreffen. Aber  moderne  Make-Imple-
    mentierungen  kennen  Include-Anweisungen. Dadurch, dass ein
    entscheidendes Fragment jedes Moduls einschlossen wird,  ist
    die Gesamtgroe des Makefiles und seiner Includes nicht unbe-
    dingt groer als die des beim rekursiven Vorgehen verwendeten
    Makefiles.

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

    Ein Haupt-Makefile, das eine Referenz auf ein Fragment jedes
    Moduls enthalt, ist nicht komplexer als das beim  rekursiven
    Make verwendete. Da der DAG nicht zerstuckelt ist, ist diese
    Art Makefile sogar  weniger  komplex  und  damit  besser  zu
    warten,  einfach weil weniger Korrekturen notwendig sind, um
    seine Funktionstuchtigkeit zu erhalten.

    Rekursive Makefiles beinhalten  eine  Menge  Wiederholungen.
    Bei  vielen  Projekten wird dieses Problem durch die Verwen-
    dung von Include-Dateien gelost. Wenn man ein einziges Make-
    file  fur  das  Projekt  benutzt, fallt der Bedarf an diesen
    "allgemeinen" Include-Dateien weg - das  eine  Makefile  ist
    der allgemeine Teil.

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

    Man  muss  lediglich  den Verzeichnisteil an einer Reihe von
    Stellen in die Dateinamen einfugen. Das ist notwendig,  weil
    Make  vom Verzeichnis der obersten Ebene ausgefuhrt wird; in
    dem aktuellen Verzeichnis erscheint  die  Datei  nicht.  Man
    muss sich nicht darum kummern, wo die Ausgabedatei ausdruck-
    lich in einer Regel genannt wird.

    GCC erlaubt im Zusammenhang mit der -c-Option eine -o-Option
    und  GNU-Make  wei das. Daraus folgt eine implizite Kompila-
    tionsregel, die die  Ausgabedatei  an  die  richtige  Stelle
    setzt.  Altere  und weniger intelligente Compiler lassen die
    -o-Option mit der -c-Option jedoch vielleicht nicht  zu  und
    lassen  die  Objektdatei  im  Verzeichnis der obersten Ebene
    zuruck  (d.  h.  im  falschen  Verzeichnis).  Es  gibt  drei
    Moglichkeiten,  wie  Sie  diesen  Fehler korrigieren konnen:
    Entweder Sie beschaffen sich GNU-Make  und  GCC,  sie  uber-
    schreiben die Build-Regel durch eine korrekt funktionierende
    oder Sie beschweren sich bei ihrem Handler.

    Auch  K&R;  C-Compiler  beginnen  den  in  Anfuhrungszeichen
    notierten  Includepfad (#include "filename.h") vom aktuellen
    Verzeichnis aus. Das bedeutet, dass sie nicht das ausfuhren,
    was Sie wollen. ANSI C-konforme C-Compiler aber beginnen den
    in Anfuhrungszeichen notierten Includepfad von dem Verzeich-
    nis  aus,  in  dem die Quelldatei erscheint; hier sind keine



    Peter Miller           3 January 2004                Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Veranderungen der Quelle notwendig. Falls Sie keinen ANSI C-
    konformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht
    ziehen, so bald wie moglich einen GCC auf  Ihrem  System  zu
    installieren.

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

    Die  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum
    beschaftigt. Sie bearbeiten ein  oder  zwei  Dateien  lassen
    dann  Make durchlaufen, was ihre Veranderungen ubersezt, und
    probieren sie aus. Diesen Arbeitsschritt fuhren sie  taglich
    Dutzende  oder  Hunderte  Male aus. Es ware absurd, wenn sie
    gezwungen waren jedesmal das ganze Projekt zu bauen.

    Entwickler habe immer die Option, ein besonderes Zielprodukt
    fur  Make  zu  definieren. Das gilt immer, wir verlassen uns
    lediglich gewohnlich  auf  das  im  Makefile  des  aktuellen
    Verzeichnisses    vorgegebene    Zielprodukt,    um   unsere
    Befehlszeile zu verkurzen. Man  kann  also  auch  mit  einem
    Ganzprojekt-Makefile  sein  kleines Teilprodukt bauen, indem
    man einfach ein bestimmtes Zielprodukt definiert und,  falls
    die Befehlszeile zu lang wird, ein Pseudonym verwendet.

    Es  stellt  sich  aber auch die Frage, ob es immer so absurd
    ist, das ganze Projekt zu bauen. Wenn z. B.  eine  in  einem
    Modul  vorgenommene Anderung in anderen Modulen Auswirkungen
    hat, weil eine Abhangigkeit existiert,  die  dem  Entwickler
    nicht  bewusst ist (aber dem Makefile ist sie bewusst), ware
    es dann nicht besser, wenn der Entwickler das so schnell wie
    moglich  herausfindet?   Solche Abhangigkeiten werden gefun-
    den, weil der DAG  vollstandiger  ist  als  beim  rekursiven
    Vorgehen.

    In  den  seltensten  Fallen  sind Entwickler erfahrene, alte
    Hasen, die jede einzelne der Millionen von Zeilen  Kode  des
    Produktes   auswendig   kennen.  Meistens  haben  sie  einen
    zeitlich begrenzten Vertrag oder  sie  sind  jungere  Mitar-
    beiter.  Sie  wollen  naturlich nicht, dass Auswirkungen wie
    die eben beschriebene entdeckt werden, nachdem Ihre Anderun-
    gen  in  den  Hauptkode  einfugt  wurden, sondern wurden sie
    gerne ganz in Ruhe  in  ihrem  lokalen  Arbeitsbereich  ent-
    decken, weit weg vom Hauptkode.

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








    Ulrike Amoore          3 January 2004                Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Diese Aussage kann man fur eine von zwei Situationen machen:
    1.  Die  Durchfuhrung des Make eines ganzen Projekts dauert,
    obwohl alles aktualisiert ist, unvermeidlich sehr lange.  2.
    Diese  unvermeidbaren  Verzogerungen sind unakzeptabel, wenn
    der Entwickler die eine Datei, die er verandert hat, schnell
    kompilieren und linken will.

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

    Stellen  Sie  sich  ein  hypothetisches Projekt vor mit 1000
    Quelldateien (.c), von denen jede  ihre  Aufrufschnittstelle
    hat,  welche in der zugehorigen Include-Datei (.h) mit Defi-
    nitionen,   Typvereinbarungen   und   Funktionsdeklarationen
    definiert ist. Diese 1000 Quelldateien beinhalten ihre eige-
    nen Interfacedefinitionen und zusatzlich die  Interfacedefi-
    nitionen  aller  Module, die sie aufrufen konnen. Diese 1000
    Quelldateien werden in  1000  Objektdateien  ubersetzt,  die
    wiederum  zu einem ausfuhrbaren Programm gebunden werden. In
    diesem System gibt es  etwa  3000  Dateien,  uber  die  Make
    informiert  werden muss. Auerdem muss Make uber die Include-
    abhangigkeiten informiert werden und man  muss  untersuchen,
    ob implizite Regeln (z. B. .y - .c) anwendbar sind.

    Um  den  DAG  zu erstellen, muss Make fur 3000 Dateien deren
    Anderungsdatum ermitteln und  auerdem  noch  fur  etwa  2000
    zusatzliche   Dateien,  abhangig  davon,  welche  impliziten
    Regeln Ihr Make kennt und welche  Ihr  Makefile  nicht  aus-
    geschaltet  hat. Auf dem bescheidenen 66MHz i486 des Authors
    dauert das etwa 10 Sekunden;  auf  systemeigenen  Laufwerken
    auf  schnelleren Hardwarebasen geht es sogar noch schneller.
    Mit NFS uber 10MB Ehernet dauert es ebenfalls etwa 10 Sekun-
    den, gleichgultig, von welcher Hardwarebasis die Aktion aus-
    gefuhrt wird.

    Das ist eine erstaunliche Statistik. Stellen Sie sich einmal
    vor,  dass  Sie  ihn  der  Lage  sind, eine einzige von 1000
    Quelldateien in nur 10 Sekunden - zuzuglich der Zeit fur das
    Kompilieren selbst - zu kompilieren.

    Die  Dateien auf 100 Module zu verteilen und den Prozess als
    ein rekursives Make durchzufuhren, dauert immerhin 25 Sekun-
    den.  Die  wiederholte  Prozesserzeugung fur die untergeord-
    neten  Make-Aufrufe  nehmen  eine  relativ  lange  Zeit   in
    Anspruch.

    Aber  warten  Sie  einen  Moment!  Bei  realen Projekten mit
    weniger als 1000 Dateien dauert es sehr viel langer  als  25
    Sekunden  bis  Make herausgefunden hat, das es nichts zu tun
    hat. Fur manche Projekte ware es ein  Fortschritt,  wenn  es
    nur  25  Minuten dauerte. Dieses Beispiel zeigt uns, dass es
    nicht die Anzahl der Dateien ist, die bremst (das dauert nur
    10   Sekunden),  und  es  ist  auch  nicht  die  wiederholte



    Peter Miller           3 January 2004                Page 13





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Prozesserzeugung fur die untergeordneten  Make-Aufrufe  (die
    dauert  nur  15 Sekunden).  Was aber nimmt dann so viel Zeit
    in Anspruch?

    Bei  traditionellen  Losungen  des  durch  rekursives   Make
    enstandenen Problems werden die untergeordneten Make-Aufrufe
    oft uber das hier beschriebene  Minimum  erhoht:  z.  B.  um
    vielfaltige  Wiederholungen  (3.3.2.)  durchzufuhren oder um
    Modulgrenzen   uberschreitende    Abhangigkeiten    (3.3.3.)
    ubermaig  abzudecken. Das kann lange Zeit dauern, besonders,
    wenn beides zusammenkommt. Aber es ist nicht fur die  beson-
    ders langen Produktionszeiten verantwortlich. Was nimmt also
    noch soviel Zeit in Anspruch?

    Die Komplexitat des Makefiles  ist  so  zeitaufwendig.  Mehr
    daruber im Kapitel [4mEffiziente[24m [4mMakefiles[24m.

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

    Wenn  es - wie bei dem Beispiel mit den 100 Dateien - nur 10
    Sekunden dauert, herauszufinden welche Datei  neu  ubersetzt
    werden  muss,  wird  die  Produktivitat der Entwickler nicht
    bedeutend  eingeschrankt,  wenn  sie  ein   Ganzprojekt-Make
    durchfuhren   anstatt  eines  modulspezifischen  Makes.  Der
    Vorteil  fur  das  Projekt  ist,  dass  der  modulzentrierte
    Entwickler  in  entscheidenden  Momenten  (und  nur  in  den
    entscheidenden) daran erinnert wird, dass seine Arbeit  auch
    weitgehendere Auswirkungen hat.

    Die  standige  Verwendung  von C-Include-Dateien, die genaue
    Interface-Definitionen  (einschlielich  Funktionsprototypen)
    enthalten,  wurde  in  vielen  Fallen zu Ubersetzungsfehlern
    fuhren, was wiederum  ein  fehlerhaftes  Produkt  zur  Folge
    hatte.  Werden  Builds  fur  das ganze Projekt durchgefuhrt,
    entdecken Entwickler solche Fehler  sehr  fruh  im  Entwick-
    lungsprozess  und  sind  in  der  Lage Fehlerbehebungen dann
    vorzunehmen, wenn sie den geringsten Aufwand verursachen.

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

    Das ist der interessanteste Einwand.  Irgenwann  einmal  vor
    langer  e C-Compiler aber beginnen den
    in Anfuhrungszeichen notierten Includepfad von dem Verzeich-
    nis  aus,  in  dem die Quelldatei erscheint; hier sind keine



    Peter Miller           3 January 2004                Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Veranderungen der Quelle notwendig. Falls Sie keinen ANSI C-
    konformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht
    ziehen, so bald wie moglich einen GCC auf  Ihrem  System  zu
    installieren.

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

    Die  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum
    beschaftigt. Sie bearbeiten ein  oder  zwei  Dateien  lassen
    dann  Make durchlaufen, was ihre Veranderungen ubersezt, und
    probieren sie aus. Diesen Arbeitsschritt fuhren sie  taglich
    Dutzende  oder  Hunderte  Male aus. Es ware absurd, wenn sie
    gezwungen waren jedesmal das ganze Projekt zu bauen.

    Entwickler habe immer die Option, ein besonderes Zielprodukt
    fur  Make  zu  definieren. Das gilt immer, wir verlassen uns
    lediglich gewohnlich  auf  das  im  Makefile  des  aktuellen
    Verzeichnisses    vorgegebene    Zielprodukt,    um   unsere
    Befehlszeile zu verkurzen. Man  kann  also  auch  mit  einem
    Ganzprojekt-Makefile  sein  kleines Teilprodukt bauen, indem
    man einfach ein bestimmtes Zielprodukt definiert und,  falls
    die Befehlszeile zu lang wird, ein Pseudonym verwendet.

    Es  stellt  sich  aber auch die Frage, ob es immer so absurd
    ist, das ganze Projekt zu bauen. Wenn z. B.  eine  in  einem
    Modul  vorgenommene Anderung in anderen Modulen Auswirkungen
    hat, weil eine Abhangigkeit existiert,  die  dem  Entwickler
    nicht  bewusst ist (aber dem Makefile ist sie bewusst), ware
    es dann nicht besser, wenn der Entwickler das so schnell wie
    moglich  herausfindet?   Solche Abhangigkeiten werden gefun-
    den, weil der DAG  vollstandiger  ist  als  beim  rekursiven
    Vorgehen.

    In  den  seltensten  Fallen  sind Entwickler erfahrene, alte
    Hasen, die jede einzelne der Millionen von Zeilen  Kode  des
    Produktes   auswendig   kennen.  Meistens  haben  sie  einen
    zeitlich begrenzten Vertrag oder  sie  sind  jungere  Mitar-
    beiter.  Sie  wollen  naturlich nicht, dass Auswirkungen wie
    die eben beschriebene entdeckt werden, nachdem Ihre Anderun-
    gen  in  den  Hauptkode  einfugt  wurden, sondern wurden sie
    gerne ganz in Ruhe  in  ihrem  lokalen  Arbeitsbereich  ent-
    decken, weit weg vom Hauptkode.

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








    Ulrike Amoore          3 January 2004                Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Diese Aussage kann man fur eine von zwei Situationen machen:
    1.  Die  Durchfuhrung des Make eines ganzen Projekts dauert,
    obwohl alles aktualisiert ist, unvermeidlich sehr lange.  2.
    Diese  unvermeidbaren  Verzogerungen sind unakzeptabel, wenn
    der Entwickler die eine Datei, die er verandert hat, schnell
    kompilieren und linken will.

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

    Stellen  Sie  sich  ein  hypothetisches Projekt vor mit 1000
    Quelldateien (.c), von denen jede  ihre  Aufrufschnittstelle
    hat,  welche in der zugehorigen Include-Datei (.h) mit Defi-
    nitionen,   Typvereinbarungen   und   Funktionsdeklarationen
    definiert ist. Diese 1000 Quelldateien beinhalten ihre eige-
    nen Interfacedefinitionen und zusatzlich die  Interfacedefi-
    nitionen  aller  Module, die sie aufrufen konnen. Diese 1000
    Quelldateien werden in  1000  Objektdateien  ubersetzt,  die
    wiederum  zu einem ausfuhrbaren Programm gebunden werden. In
    diesem System gibt es  etwa  3000  Dateien,  uber  die  Make
    informiert  werden muss. Auerdem muss Make uber die Include-
    abhangigkeiten informiert werden und man  muss  untersuchen,
    ob implizite Regeln (z. B. .y - .c) anwendbar sind.

    Um  den  DAG  zu erstellen, muss Make fur 3000 Dateien deren
    Anderungsdatum ermitteln und  auerdem  noch  fur  etwa  2000
    zusatzliche   Dateien,  abhangig  davon,  welche  impliziten
    Regeln Ihr Make kennt und welche  Ihr  Makefile  nicht  aus-
    geschaltet  hat. Auf dem bescheidenen 66MHz i486 des Authors
    dauert das etwa 10 Sekunden;  auf  systemeigenen  Laufwerken
    auf  schnelleren Hardwarebasen geht es sogar noch schneller.
    Mit NFS uber 10MB Ehernet dauert es ebenfalls etwa 10 Sekun-
    den, gleichgultig, von welcher Hardwarebasis die Aktion aus-
    gefuhrt wird.

    Das ist eine erstaunliche Statistik. Stellen Sie sich einmal
    vor,  dass  Sie  ihn  der  Lage  sind, eine einzige von 1000
    Quelldateien in nur 10 Sekunden - zuzuglich der Zeit fur das
    Kompilieren selbst - zu kompilieren.

    Die  Dateien auf 100 Module zu verteilen und den Prozess als
    ein rekursives Make durchzufuhren, dauert immerhin 25 Sekun-
    den.  Die  wiederholte  Prozesserzeugung fur die untergeord-
    neten  Make-Aufrufe  nehmen  eine  relativ  lange  Zeit   in
    Anspruch.

    Aber  warten  Sie  einen  Moment!  Bei  realen Projekten mit
    weniger als 1000 Dateien dauert es sehr viel langer  als  25
    Sekunden  bis  Make herausgefunden hat, das es nichts zu tun
    hat. Fur manche Projekte ware es ein  Fortschritt,  wenn  es
    nur  25  Minuten dauerte. Dieses Beispiel zeigt uns, dass es
    nicht die Anzahl der Dateien ist, die bremst (das dauert nur
    10   Sekunden),  und  es  ist  auch  nicht  die  wiederholte



    Peter Miller           3 January 2004                Page 13





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Prozesserzeugung fur die untergeordneten  Make-Aufrufe  (die
    dauert  nur  15 Sekunden).  Was aber nimmt dann so viel Zeit
    in Anspruch?

    Bei  traditionellen  Losungen  des  durch  rekursives   Make
    enstandenen Problems werden die untergeordneten Make-Aufrufe
    oft uber das hier beschriebene  Minimum  erhoht:  z.  B.  um
    vielfaltige  Wiederholungen  (3.3.2.)  durchzufuhren oder um
    Modulgrenzen   uberschreitende    Abhangigkeiten    (3.3.3.)
    ubermaig  abzudecken. Das kann lange Zeit dauern, besonders,
    wenn beides zusammenkommt. Aber es ist nicht fur die  beson-
    ders langen Produktionszeiten verantwortlich. Was nimmt also
    noch soviel Zeit in Anspruch?

    Die Komplexitat des Makefiles  ist  so  zeitaufwendig.  Mehr
    daruber im Kapitel [4mEffiziente[24m [4mMakefiles[24m.

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

    Wenn  es - wie bei dem Beispiel mit den 100 Dateien - nur 10
    Sekunden dauert, herauszufinden welche Datei  neu  ubersetzt
    werden  muss,  wird  die  Produktivitat der Entwickler nicht
    bedeutend  eingeschrankt,  wenn  sie  ein   Ganzprojekt-Make
    durchfuhren   anstatt  eines  modulspezifischen  Makes.  Der
    Vorteil  fur  das  Projekt  ist,  dass  der  modulzentrierte
    Entwickler  in  entscheidenden  Momenten  (und  nur  in  den
    entscheidenden) daran erinnert wird, dass seine Arbeit  auch
    weitgehendere Auswirkungen hat.

    Die  standige  Verwendung  von C-Include-Dateien, die genaue
    Interface-Definitionen  (einschlielich  Funktionsprototypen)
    enthalten,  wurde  in  vielen  Fallen zu Ubersetzungsfehlern
    fuhren, was wiederum  ein  fehlerhaftes  Produkt  zur  Folge
    hatte.  Werden  Builds  fur  das ganze Projekt durchgefuhrt,
    entdecken Entwickler solche Fehler  sehr  fruh  im  Entwick-
    lungsprozess  und  sind  in  der  Lage Fehlerbehebungen dann
    vorzunehmen, wenn sie den geringsten Aufwand verursachen.

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

    Das ist der interessanteste Einwand.  Irgenwann  einmal  vor
    langer  e C-Compiler aber beginnen den
    in Anfuhrungszeichen notierten Includepfad von dem Verzeich-
    nis  aus,  in  dem die Quelldatei erscheint; hier sind keine



    Peter Miller           3 January 2004                Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Veranderungen der Quelle notwendig. Falls Sie keinen ANSI C-
    konformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht
    ziehen, so bald wie moglich einen GCC auf  Ihrem  System  zu
    installieren.

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

    Die  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum
    beschaftigt. Sie bearbeiten ein  oder  zwei  Dateien  lassen
    dann  Make durchlaufen, was ihre Veranderungen ubersezt, und
    probieren sie aus. Diesen Arbeitsschritt fuhren sie  taglich
    Dutzende  oder  Hunderte  Male aus. Es ware absurd, wenn sie
    gezwungen waren jedesmal das ganze Projekt zu bauen.

    Entwickler habe immer die Option, ein besonderes Zielprodukt
    fur  Make  zu  definieren. Das gilt immer, wir verlassen uns
    lediglich gewohnlich  auf  das  im  Makefile  des  aktuellen
    Verzeichnisses    vorgegebene    Zielprodukt,    um   unsere
    Befehlszeile zu verkurzen. Man  kann  also  auch  mit  einem
    Ganzprojekt-Makefile  sein  kleines Teilprodukt bauen, indem
    man einfach ein bestimmtes Zielprodukt definiert und,  falls
    die Befehlszeile zu lang wird, ein Pseudonym verwendet.

    Es  stellt  sich  aber auch die Frage, ob es immer so absurd
    ist, das ganze Projekt zu bauen. Wenn z. B.  eine  in  einem
    Modul  vorgenommene Anderung in anderen Modulen Auswirkungen
    hat, weil eine Abhangigkeit existiert,  die  dem  Entwickler
    nicht  bewusst ist (aber dem Makefile ist sie bewusst), ware
    es dann nicht besser, wenn der Entwickler das so schnell wie
    moglich  herausfindet?   Solche Abhangigkeiten werden gefun-
    den, weil der DAG  vollstandiger  ist  als  beim  rekursiven
    Vorgehen.

    In  den  seltensten  Fallen  sind Entwickler erfahrene, alte
    Hasen, die jede einzelne der Millionen von Zeilen  Kode  des
    Produktes   auswendig   kennen.  Meistens  haben  sie  einen
    zeitlich begrenzten Vertrag oder  sie  sind  jungere  Mitar-
    beiter.  Sie  wollen  naturlich nicht, dass Auswirkungen wie
    die eben beschriebene entdeckt werden, nachdem Ihre Anderun-
    gen  in  den  Hauptkode  einfugt  wurden, sondern wurden sie
    gerne ganz in Ruhe  in  ihrem  lokalen  Arbeitsbereich  ent-
    decken, weit weg vom Hauptkode.

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








    Ulrike Amoore          3 January 2004                Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Diese Aussage kann man fur eine von zwei Situationen machen:
    1.  Die  Durchfuhrung des Make eines ganzen Projekts dauert,
    obwohl alles aktualisiert ist, unvermeidlich sehr lange.  2.
    Diese  unvermeidbaren  Verzogerungen sind unakzeptabel, wenn
    der Entwickler die eine Datei, die er verandert hat, schnell
    kompilieren und linken will.

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

    Stellen  Sie  sich  ein  hypothetisches Projekt vor mit 1000
    Quelldateien (.c), von denen jede  ihre  Aufrufschnittstelle
    hat,  welche in der zugehorigen Include-Datei (.h) mit Defi-
    nitionen,   Typvereinbarungen   und   Funktionsdeklarationen
    definiert ist. Diese 1000 Quelldateien beinhalten ihre eige-
    nen Interfacedefinitionen und zusatzlich die  Interfacedefi-
    nitionen  aller  Module, die sie aufrufen konnen. Diese 1000
    Quelldateien werden in  1000  Objektdateien  ubersetzt,  die
    wiederum  zu einem ausfuhrbaren Programm gebunden werden. In
    diesem System gibt es  etwa  3000  Dateien,  uber  die  Make
    informiert  werden muss. Auerdem muss Make uber die Include-
    abhangigkeiten informiert werden und man  muss  untersuchen,
    ob implizite Regeln (z. B. .y - .c) anwendbar sind.

    Um  den  DAG  zu erstellen, muss Make fur 3000 Dateien deren
    Anderungsdatum ermitteln und  auerdem  noch  fur  etwa  2000
    zusatzliche   Dateien,  abhangig  davon,  welche  impliziten
    Regeln Ihr Make kennt und welche  Ihr  Makefile  nicht  aus-
    geschaltet  hat. Auf dem bescheidenen 66MHz i486 des Authors
    dauert das etwa 10 Sekunden;  auf  systemeigenen  Laufwerken
    auf  schnelleren Hardwarebasen geht es sogar noch schneller.
    Mit NFS uber 10MB Ehernet dauert es ebenfalls etwa 10 Sekun-
    den, gleichgultig, von welcher Hardwarebasis die Aktion aus-
    gefuhrt wird.

    Das ist eine erstaunliche Statistik. Stellen Sie sich einmal
    vor,  dass  Sie  ihn  der  Lage  sind, eine einzige von 1000
    Quelldateien in nur 10 Sekunden - zuzuglich der Zeit fur das
    Kompilieren selbst - zu kompilieren.

    Die  Dateien auf 100 Module zu verteilen und den Prozess als
    ein rekursives Make durchzufuhren, dauert immerhin 25 Sekun-
    den.  Die  wiederholte  Prozesserzeugung fur die untergeord-
    neten  Make-Aufrufe  nehmen  eine  relativ  lange  Zeit   in
    Anspruch.

    Aber  warten  Sie  einen  Moment!  Bei  realen Projekten mit
    weniger als 1000 Dateien dauert es sehr viel langer  als  25
    Sekunden  bis  Make herausgefunden hat, das es nichts zu tun
    hat. Fur manche Projekte ware es ein  Fortschritt,  wenn  es
    nur  25  Minuten dauerte. Dieses Beispiel zeigt uns, dass es
    nicht die Anzahl der Dateien ist, die bremst (das dauert nur
    10   Sekunden),  und  es  ist  auch  nicht  die  wiederholte



    Peter Miller           3 January 2004                Page 13





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Prozesserzeugung fur die untergeordneten  Make-Aufrufe  (die
    dauert  nur  15 Sekunden).  Was aber nimmt dann so viel Zeit
    in Anspruch?

    Bei  traditionellen  Losungen  des  durch  rekursives   Make
    enstandenen Problems werden die untergeordneten Make-Aufrufe
    oft uber das hier beschriebene  Minimum  erhoht:  z.  B.  um
    vielfaltige  Wiederholungen  (3.3.2.)  durchzufuhren oder um
    Modulgrenzen   uberschreitende    Abhangigkeiten    (3.3.3.)
    ubermaig  abzudecken. Das kann lange Zeit dauern, besonders,
    wenn beides zusammenkommt. Aber es ist nicht fur die  beson-
    ders langen Produktionszeiten verantwortlich. Was nimmt also
    noch soviel Zeit in Anspruch?

    Die Komplexitat des Makefiles  ist  so  zeitaufwendig.  Mehr
    daruber im Kapitel [4mEffiziente[24m [4mMakefiles[24m.

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

    Wenn  es - wie bei dem Beispiel mit den 100 Dateien - nur 10
    Sekunden dauert, herauszufinden welche Datei  neu  ubersetzt
    werden  muss,  wird  die  Produktivitat der Entwickler nicht
    bedeutend  eingeschrankt,  wenn  sie  ein   Ganzprojekt-Make
    durchfuhren   anstatt  eines  modulspezifischen  Makes.  Der
    Vorteil  fur  das  Projekt  ist,  dass  der  modulzentrierte
    Entwickler  in  entscheidenden  Momenten  (und  nur  in  den
    entscheidenden) daran erinnert wird, dass seine Arbeit  auch
    weitgehendere Auswirkungen hat.

    Die  standige  Verwendung  von C-Include-Dateien, die genaue
    Interface-Definitionen  (einschlielich  Funktionsprototypen)
    enthalten,  wurde  in  vielen  Fallen zu Ubersetzungsfehlern
    fuhren, was wiederum  ein  fehlerhaftes  Produkt  zur  Folge
    hatte.  Werden  Builds  fur  das ganze Projekt durchgefuhrt,
    entdecken Entwickler solche Fehler  sehr  fruh  im  Entwick-
    lungsprozess  und  sind  in  der  Lage Fehlerbehebungen dann
    vorzunehmen, wenn sie den geringsten Aufwand verursachen.

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

    Das ist der interessanteste Einwand.  Irgenwann  einmal  vor
    langer  e C-Compiler aber beginnen den
    in Anfuhrungszeichen notierten Includepfad von dem Verzeich-
    nis  aus,  in  dem die Quelldatei erscheint; hier sind keine



    Peter Miller           3 January 2004                Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Veranderungen der Quelle notwendig. Falls Sie keinen ANSI C-
    konformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht
    ziehen, so bald wie moglich einen GCC auf  Ihrem  System  zu
    installieren.

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

    Die  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum
    beschaftigt. Sie bearbeiten ein  oder  zwei  Dateien  lassen
    dann  Make durchlaufen, was ihre Veranderungen ubersezt, und
    probieren sie aus. Diesen Arbeitsschritt fuhren sie  taglich
    Dutzende  oder  Hunderte  Male aus. Es ware absurd, wenn sie
    gezwungen waren jedesmal das ganze Projekt zu bauen.

    Entwickler habe immer die Option, ein besonderes Zielprodukt
    fur  Make  zu  definieren. Das gilt immer, wir verlassen uns
    lediglich gewohnlich  auf  das  im  Makefile  des  aktuellen
    Verzeichnisses    vorgegebene    Zielprodukt,    um   unsere
    Befehlszeile zu verkurzen. Man  kann  also  auch  mit  einem
    Ganzprojekt-Makefile  sein  kleines Teilprodukt bauen, indem
    man einfach ein bestimmtes Zielprodukt definiert und,  falls
    die Befehlszeile zu lang wird, ein Pseudonym verwendet.

    Es  stellt  sich  aber auch die Frage, ob es immer so absurd
    ist, das ganze Projekt zu bauen. Wenn z. B.  eine  in  einem
    Modul  vorgenommene Anderung in anderen Modulen Auswirkungen
    hat, weil eine Abhangigkeit existiert,  die  dem  Entwickler
    nicht  bewusst ist (aber dem Makefile ist sie bewusst), ware
    es dann nicht besser, wenn der Entwickler das so schnell wie
    moglich  herausfindet?   Solche Abhangigkeiten werden gefun-
    den, weil der DAG  vollstandiger  ist  als  beim  rekursiven
    Vorgehen.

    In  den  seltensten  Fallen  sind Entwickler erfahrene, alte
    Hasen, die jede einzelne der Millionen von Zeilen  Kode  des
    Produktes   auswendig   kennen.  Meistens  haben  sie  einen
    zeitlich begrenzten Vertrag oder  sie  sind  jungere  Mitar-
    beiter.  Sie  wollen  naturlich nicht, dass Auswirkungen wie
    die eben beschriebene entdeckt werden, nachdem Ihre Anderun-
    gen  in  den  Hauptkode  einfugt  wurden, sondern wurden sie
    gerne ganz in Ruhe  in  ihrem  lokalen  Arbeitsbereich  ent-
    decken, weit weg vom Hauptkode.

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








    Ulrike Amoore          3 January 2004                Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Diese Aussage kann man fur eine von zwei Situationen machen:
    1.  Die  Durchfuhrung des Make eines ganzen Projekts dauert,
    obwohl alles aktualisiert ist, unvermeidlich sehr lange.  2.
    Diese  unvermeidbaren  Verzogerungen sind unakzeptabel, wenn
    der Entwickler die eine Datei, die er verandert hat, schnell
    kompilieren und linken will.

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

    Stellen  Sie  sich  ein  hypothetisches Projekt vor mit 1000
    Quelldateien (.c), von denen jede  ihre  Aufrufschnittstelle
    hat,  welche in der zugehorigen Include-Datei (.h) mit Defi-
    nitionen,   Typvereinbarungen   und   Funktionsdeklarationen
    definiert ist. Diese 1000 Quelldateien beinhalten ihre eige-
    nen Interfacedefinitionen und zusatzlich die  Interfacedefi-
    nitionen  aller  Module, die sie aufrufen konnen. Diese 1000
    Quelldateien werden in  1000  Objektdateien  ubersetzt,  die
    wiederum  zu einem ausfuhrbaren Programm gebunden werden. In
    diesem System gibt es  etwa  3000  Dateien,  uber  die  Make
    informiert  werden muss. Auerdem muss Make uber die Include-
    abhangigkeiten informiert werden und man  muss  untersuchen,
    ob implizite Regeln (z. B. .y - .c) anwendbar sind.

    Um  den  DAG  zu erstellen, muss Make fur 3000 Dateien deren
    Anderungsdatum ermitteln und  auerdem  noch  fur  etwa  2000
    zusatzliche   Dateien,  abhangig  davon,  welche  impliziten
    Regeln Ihr Make kennt und welche  Ihr  Makefile  nicht  aus-
    geschaltet  hat. Auf dem bescheidenen 66MHz i486 des Authors
    dauert das etwa 10 Sekunden;  auf  systemeigenen  Laufwerken
    auf  schnelleren Hardwarebasen geht es sogar noch schneller.
    Mit NFS uber 10MB Ehernet dauert es ebenfalls etwa 10 Sekun-
    den, gleichgultig, von welcher Hardwarebasis die Aktion aus-
    gefuhrt wird.

    Das ist eine erstaunliche Statistik. Stellen Sie sich einmal
    vor,  dass  Sie  ihn  der  Lage  sind, eine einzige von 1000
    Quelldateien in nur 10 Sekunden - zuzuglich der Zeit fur das
    Kompilieren selbst - zu kompilieren.

    Die  Dateien auf 100 Module zu verteilen und den Prozess als
    ein rekursives Make durchzufuhren, dauert immerhin 25 Sekun-
    den.  Die  wiederholte  Prozesserzeugung fur die untergeord-
    neten  Make-Aufrufe  nehmen  eine  relativ  lange  Zeit   in
    Anspruch.

    Aber  warten  Sie  einen  Moment!  Bei  realen Projekten mit
    weniger als 1000 Dateien dauert es sehr viel langer  als  25
    Sekunden  bis  Make herausgefunden hat, das es nichts zu tun
    hat. Fur manche Projekte ware es ein  Fortschritt,  wenn  es
    nur  25  Minuten dauerte. Dieses Beispiel zeigt uns, dass es
    nicht die Anzahl der Dateien ist, die bremst (das dauert nur
    10   Sekunden),  und  es  ist  auch  nicht  die  wiederholte



    Peter Miller           3 January 2004                Page 13





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Prozesserzeugung fur die untergeordneten  Make-Aufrufe  (die
    dauert  nur  15 Sekunden).  Was aber nimmt dann so viel Zeit
    in Anspruch?

    Bei  traditionellen  Losungen  des  durch  rekursives   Make
    enstandenen Problems werden die untergeordneten Make-Aufrufe
    oft uber das hier beschriebene  Minimum  erhoht:  z.  B.  um
    vielfaltige  Wiederholungen  (3.3.2.)  durchzufuhren oder um
    Modulgrenzen   uberschreitende    Abhangigkeiten    (3.3.3.)
    ubermaig  abzudecken. Das kann lange Zeit dauern, besonders,
    wenn beides zusammenkommt. Aber es ist nicht fur die  beson-
    ders langen Produktionszeiten verantwortlich. Was nimmt also
    noch soviel Zeit in Anspruch?

    Die Komplexitat des Makefiles  ist  so  zeitaufwendig.  Mehr
    daruber im Kapitel [4mEffiziente[24m [4mMakefiles[24m.

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

    Wenn  es - wie bei dem Beispiel mit den 100 Dateien - nur 10
    Sekunden dauert, herauszufinden welche Datei  neu  ubersetzt
    werden  muss,  wird  die  Produktivitat der Entwickler nicht
    bedeutend  eingeschrankt,  wenn  sie  ein   Ganzprojekt-Make
    durchfuhren   anstatt  eines  modulspezifischen  Makes.  Der
    Vorteil  fur  das  Projekt  ist,  dass  der  modulzentrierte
    Entwickler  in  entscheidenden  Momenten  (und  nur  in  den
    entscheidenden) daran erinnert wird, dass seine Arbeit  auch
    weitgehendere Auswirkungen hat.

    Die  standige  Verwendung  von C-Include-Dateien, die genaue
    Interface-Definitionen  (einschlielich  Funktionsprototypen)
    enthalten,  wurde  in  vielen  Fallen zu Ubersetzungsfehlern
    fuhren, was wiederum  ein  fehlerhaftes  Produkt  zur  Folge
    hatte.  Werden  Builds  fur  das ganze Projekt durchgefuhrt,
    entdecken Entwickler solche Fehler  sehr  fruh  im  Entwick-
    lungsprozess  und  sind  in  der  Lage Fehlerbehebungen dann
    vorzunehmen, wenn sie den geringsten Aufwand verursachen.

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

    Das ist der interessanteste Einwand.  Irgenwann  einmal  vor
    langer  e C-Compiler aber beginnen den
    in Anfuhrungszeichen notierten Includepfad von dem Verzeich-
    nis  aus,  in  dem die Quelldatei erscheint; hier sind keine



    Peter Miller           3 January 2004                Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Veranderungen der Quelle notwendig. Falls Sie keinen ANSI C-
    konformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht
    ziehen, so bald wie moglich einen GCC auf  Ihrem  System  zu
    installieren.

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

    Die  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum
    beschaftigt. Sie bearbeiten ein  oder  zwei  Dateien  lassen
    dann  Make durchlaufen, was ihre Veranderungen ubersezt, und
    probieren sie aus. Diesen Arbeitsschritt fuhren sie  taglich
    Dutzende  oder  Hunderte  Male aus. Es ware absurd, wenn sie
    gezwungen waren jedesmal das ganze Projekt zu bauen.

    Entwickler habe immer die Option, ein besonderes Zielprodukt
    fur  Make  zu  definieren. Das gilt immer, wir verlassen uns
    lediglich gewohnlich  auf  das  im  Makefile  des  aktuellen
    Verzeichnisses    vorgegebene    Zielprodukt,    um   unsere
    Befehlszeile zu verkurzen. Man  kann  also  auch  mit  einem
    Ganzprojekt-Makefile  sein  kleines Teilprodukt bauen, indem
    man einfach ein bestimmtes Zielprodukt definiert und,  falls
    die Befehlszeile zu lang wird, ein Pseudonym verwendet.

    Es  stellt  sich  aber auch die Frage, ob es immer so absurd
    ist, das ganze Projekt zu bauen. Wenn z. B.  eine  in  einem
    Modul  vorgenommene Anderung in anderen Modulen Auswirkungen
    hat, weil eine Abhangigkeit existiert,  die  dem  Entwickler
    nicht  bewusst ist (aber dem Makefile ist sie bewusst), ware
    es dann nicht besser, wenn der Entwickler das so schnell wie
    moglich  herausfindet?   Solche Abhangigkeiten werden gefun-
    den, weil der DAG  vollstandiger  ist  als  beim  rekursiven
    Vorgehen.

    In  den  seltensten  Fallen  sind Entwickler erfahrene, alte
    Hasen, die jede einzelne der Millionen von Zeilen  Kode  des
    Produktes   auswendig   kennen.  Meistens  haben  sie  einen
    zeitlich begrenzten Vertrag oder  sie  sind  jungere  Mitar-
    beiter.  Sie  wollen  naturlich nicht, dass Auswirkungen wie
    die eben beschriebene entdeckt werden, nachdem Ihre Anderun-
    gen  in  den  Hauptkode  einfugt  wurden, sondern wurden sie
    gerne ganz in Ruhe  in  ihrem  lokalen  Arbeitsbereich  ent-
    decken, weit weg vom Hauptkode.

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








    Ulrike Amoore          3 January 2004                Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Diese Aussage kann man fur eine von zwei Situationen machen:
    1.  Die  Durchfuhrung des Make eines ganzen Projekts dauert,
    obwohl alles aktualisiert ist, unvermeidlich sehr lange.  2.
    Diese  unvermeidbaren  Verzogerungen sind unakzeptabel, wenn
    der Entwickler die eine Datei, die er verandert hat, schnell
    kompilieren und linken will.

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

    Stellen  Sie  sich  ein  hypothetisches Projekt vor mit 1000
    Quelldateien (.c), von denen jede  ihre  Aufrufschnittstelle
    hat,  welche in der zugehorigen Include-Datei (.h) mit Defi-
    nitionen,   Typvereinbarungen   und   Funktionsdeklarationen
    definiert ist. Diese 1000 Quelldateien beinhalten ihre eige-
    nen Interfacedefinitionen und zusatzlich die  Interfacedefi-
    nitionen  aller  Module, die sie aufrufen konnen. Diese 1000
    Quelldateien werden in  1000  Objektdateien  ubersetzt,  die
    wiederum  zu einem ausfuhrbaren Programm gebunden werden. In
    diesem System gibt es  etwa  3000  Dateien,  uber  die  Make
    informiert  werden muss. Auerdem muss Make uber die Include-
    abhangigkeiten informiert werden und man  muss  untersuchen,
    ob implizite Regeln (z. B. .y - .c) anwendbar sind.

    Um  den  DAG  zu erstellen, muss Make fur 3000 Dateien deren
    Anderungsdatum ermitteln und  auerdem  noch  fur  etwa  2000
    zusatzliche   Dateien,  abhangig  davon,  welche  impliziten
    Regeln Ihr Make kennt und welche  Ihr  Makefile  nicht  aus-
    geschaltet  hat. Auf dem bescheidenen 66MHz i486 des Authors
    dauert das etwa 10 Sekunden;  auf  systemeigenen  Laufwerken
    auf  schnelleren Hardwarebasen geht es sogar noch schneller.
    Mit NFS uber 10MB Ehernet dauert es ebenfalls etwa 10 Sekun-
    den, gleichgultig, von welcher Hardwarebasis die Aktion aus-
    gefuhrt wird.

    Das ist eine erstaunliche Statistik. Stellen Sie sich einmal
    vor,  dass  Sie  ihn  der  Lage  sind, eine einzige von 1000
    Quelldateien in nur 10 Sekunden - zuzuglich der Zeit fur das
    Kompilieren selbst - zu kompilieren.

    Die  Dateien auf 100 Module zu verteilen und den Prozess als
    ein rekursives Make durchzufuhren, dauert immerhin 25 Sekun-
    den.  Die  wiederholte  Prozesserzeugung fur die untergeord-
    neten  Make-Aufrufe  nehmen  eine  relativ  lange  Zeit   in
    Anspruch.

    Aber  warten  Sie  einen  Moment!  Bei  realen Projekten mit
    weniger als 1000 Dateien dauert es sehr viel langer  als  25
    Sekunden  bis  Make herausgefunden hat, das es nichts zu tun
    hat. Fur manche Projekte ware es ein  Fortschritt,  wenn  es
    nur  25  Minuten dauerte. Dieses Beispiel zeigt uns, dass es
    nicht die Anzahl der Dateien ist, die bremst (das dauert nur
    10   Sekunden),  und  es  ist  auch  nicht  die  wiederholte



    Peter Miller           3 January 2004                Page 13





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Prozesserzeugung fur die untergeordneten  Make-Aufrufe  (die
    dauert  nur  15 Sekunden).  Was aber nimmt dann so viel Zeit
    in Anspruch?

    Bei  traditionellen  Losungen  des  durch  rekursives   Make
    enstandenen Problems werden die untergeordneten Make-Aufrufe
    oft uber das hier beschriebene  Minimum  erhoht:  z.  B.  um
    vielfaltige  Wiederholungen  (3.3.2.)  durchzufuhren oder um
    Modulgrenzen   uberschreitende    Abhangigkeiten    (3.3.3.)
    ubermaig  abzudecken. Das kann lange Zeit dauern, besonders,
    wenn beides zusammenkommt. Aber es ist nicht fur die  beson-
    ders langen Produktionszeiten verantwortlich. Was nimmt also
    noch soviel Zeit in Anspruch?

    Die Komplexitat des Makefiles  ist  so  zeitaufwendig.  Mehr
    daruber im Kapitel [4mEffiziente[24m [4mMakefiles[24m.

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

    Wenn  es - wie bei dem Beispiel mit den 100 Dateien - nur 10
    Sekunden dauert, herauszufinden welche Datei  neu  ubersetzt
    werden  muss,  wird  die  Produktivitat der Entwickler nicht
    bedeutend  eingeschrankt,  wenn  sie  ein   Ganzprojekt-Make
    durchfuhren   anstatt  eines  modulspezifischen  Makes.  Der
    Vorteil  fur  das  Projekt  ist,  dass  der  modulzentrierte
    Entwickler  in  entscheidenden  Momenten  (und  nur  in  den
    entscheidenden) daran erinnert wird, dass seine Arbeit  auch
    weitgehendere Auswirkungen hat.

    Die  standige  Verwendung  von C-Include-Dateien, die genaue
    Interface-Definitionen  (einschlielich  Funktionsprototypen)
    enthalten,  wurde  in  vielen  Fallen zu Ubersetzungsfehlern
    fuhren, was wiederum  ein  fehlerhaftes  Produkt  zur  Folge
    hatte.  Werden  Builds  fur  das ganze Projekt durchgefuhrt,
    entdecken Entwickler solche Fehler  sehr  fruh  im  Entwick-
    lungsprozess  und  sind  in  der  Lage Fehlerbehebungen dann
    vorzunehmen, wenn sie den geringsten Aufwand verursachen.

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

    Das ist der interessanteste Einwand.  Irgenwann  einmal  vor
    langer  e C-Compiler aber beginnen den
    in Anfuhrungszeichen notierten Includepfad von dem Verzeich-
    nis  aus,  in  dem die Quelldatei erscheint; hier sind keine



    Peter Miller           3 January 2004                Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Veranderungen der Quelle notwendig. Falls Sie keinen ANSI C-
    konformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht
    ziehen, so bald wie moglich einen GCC auf  Ihrem  System  zu
    installieren.

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

    Die  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum
    beschaftigt. Sie bearbeiten ein  oder  zwei  Dateien  lassen
    dann  Make durchlaufen, was ihre Veranderungen ubersezt, und
    probieren sie aus. Diesen Arbeitsschritt fuhren sie  taglich
    Dutzende  oder  Hunderte  Male aus. Es ware absurd, wenn sie
    gezwungen waren jedesmal das ganze Projekt zu bauen.

    Entwickler habe immer die Option, ein besonderes Zielprodukt
    fur  Make  zu  definieren. Das gilt immer, wir verlassen uns
    lediglich gewohnlich  auf  das  im  Makefile  des  aktuellen
    Verzeichnisses    vorgegebene    Zielprodukt,    um   unsere
    Befehlszeile zu verkurzen. Man  kann  also  auch  mit  einem
    Ganzprojekt-Makefile  sein  kleines Teilprodukt bauen, indem
    man einfach ein bestimmtes Zielprodukt definiert und,  falls
    die Befehlszeile zu lang wird, ein Pseudonym verwendet.

    Es  stellt  sich  aber auch die Frage, ob es immer so absurd
    ist, das ganze Projekt zu bauen. Wenn z. B.  eine  in  einem
    Modul  vorgenommene Anderung in anderen Modulen Auswirkungen
    hat, weil eine Abhangigkeit existiert,  die  dem  Entwickler
    nicht  bewusst ist (aber dem Makefile ist sie bewusst), ware
    es dann nicht besser, wenn der Entwickler das so schnell wie
    moglich  herausfindet?   Solche Abhangigkeiten werden gefun-
    den, weil der DAG  vollstandiger  ist  als  beim  rekursiven
    Vorgehen.

    In  den  seltensten  Fallen  sind Entwickler erfahrene, alte
    Hasen, die jede einzelne der Millionen von Zeilen  Kode  des
    Produktes   auswendig   kennen.  Meistens  haben  sie  einen
    zeitlich begrenzten Vertrag oder  sie  sind  jungere  Mitar-
    beiter.  Sie  wollen  naturlich nicht, dass Auswirkungen wie
    die eben beschriebene entdeckt werden, nachdem Ihre Anderun-
    gen  in  den  Hauptkode  einfugt  wurden, sondern wurden sie
    gerne ganz in Ruhe  in  ihrem  lokalen  Arbeitsbereich  ent-
    decken, weit weg vom Hauptkode.

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








    Ulrike Amoore          3 January 2004                Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Diese Aussage kann man fur eine von zwei Situationen machen:
    1.  Die  Durchfuhrung des Make eines ganzen Projekts dauert,
    obwohl alles aktualisiert ist, unvermeidlich sehr lange.  2.
    Diese  unvermeidbaren  Verzogerungen sind unakzeptabel, wenn
    der Entwickler die eine Datei, die er verandert hat, schnell
    kompilieren und linken will.

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

    Stellen  Sie  sich  ein  hypothetisches Projekt vor mit 1000
    Quelldateien (.c), von denen jede  ihre  Aufrufschnittstelle
    hat,  welche in der zugehorigen Include-Datei (.h) mit Defi-
    nitionen,   Typvereinbarungen   und   Funktionsdeklarationen
    definiert ist. Diese 1000 Quelldateien beinhalten ihre eige-
    nen Interfacedefinitionen und zusatzlich die  Interfacedefi-
    nitionen  aller  Module, die sie aufrufen konnen. Diese 1000
    Quelldateien werden in  1000  Objektdateien  ubersetzt,  die
    wiederum  zu einem ausfuhrbaren Programm gebunden werden. In
    diesem System gibt es  etwa  3000  Dateien,  uber  die  Make
    informiert  werden muss. Auerdem muss Make uber die Include-
    abhangigkeiten informiert werden und man  muss  untersuchen,
    ob implizite Regeln (z. B. .y - .c) anwendbar sind.

    Um  den  DAG  zu erstellen, muss Make fur 3000 Dateien deren
    Anderungsdatum ermitteln und  auerdem  noch  fur  etwa  2000
    zusatzliche   Dateien,  abhangig  davon,  welche  impliziten
    Regeln Ihr Make kennt und welche  Ihr  Makefile  nicht  aus-
    geschaltet  hat. Auf dem bescheidenen 66MHz i486 des Authors
    dauert das etwa 10 Sekunden;  auf  systemeigenen  Laufwerken
    auf  schnelleren Hardwarebasen geht es sogar noch schneller.
    Mit NFS uber 10MB Ehernet dauert es ebenfalls etwa 10 Sekun-
    den, gleichgultig, von welcher Hardwarebasis die Aktion aus-
    gefuhrt wird.

    Das ist eine erstaunliche Statistik. Stellen Sie sich einmal
    vor,  dass  Sie  ihn  der  Lage  sind, eine einzige von 1000
    Quelldateien in nur 10 Sekunden - zuzuglich der Zeit fur das
    Kompilieren selbst - zu kompilieren.

    Die  Dateien auf 100 Module zu verteilen und den Prozess als
    ein rekursives Make durchzufuhren, dauert immerhin 25 Sekun-
    den.  Die  wiederholte  Prozesserzeugung fur die untergeord-
    neten  Make-Aufrufe  nehmen  eine  relativ  lange  Zeit   in
    Anspruch.

    Aber  warten  Sie  einen  Moment!  Bei  realen Projekten mit
    weniger als 1000 Dateien dauert es sehr viel langer  als  25
    Sekunden  bis  Make herausgefunden hat, das es nichts zu tun
    hat. Fur manche Projekte ware es ein  Fortschritt,  wenn  es
    nur  25  Minuten dauerte. Dieses Beispiel zeigt uns, dass es
    nicht die Anzahl der Dateien ist, die bremst (das dauert nur
    10   Sekunden),  und  es  ist  auch  nicht  die  wiederholte



    Peter Miller           3 January 2004                Page 13





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Prozesserzeugung fur die untergeordneten  Make-Aufrufe  (die
    dauert  nur  15 Sekunden).  Was aber nimmt dann so viel Zeit
    in Anspruch?

    Bei  traditionellen  Losungen  des  durch  rekursives   Make
    enstandenen Problems werden die untergeordneten Make-Aufrufe
    oft uber das hier beschriebene  Minimum  erhoht:  z.  B.  um
    vielfaltige  Wiederholungen  (3.3.2.)  durchzufuhren oder um
    Modulgrenzen   uberschreitende    Abhangigkeiten    (3.3.3.)
    ubermaig  abzudecken. Das kann lange Zeit dauern, besonders,
    wenn beides zusammenkommt. Aber es ist nicht fur die  beson-
    ders langen Produktionszeiten verantwortlich. Was nimmt also
    noch soviel Zeit in Anspruch?

    Die Komplexitat des Makefiles  ist  so  zeitaufwendig.  Mehr
    daruber im Kapitel [4mEffiziente[24m [4mMakefiles[24m.

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

    Wenn  es - wie bei dem Beispiel mit den 100 Dateien - nur 10
    Sekunden dauert, herauszufinden welche Datei  neu  ubersetzt
    werden  muss,  wird  die  Produktivitat der Entwickler nicht
    bedeutend  eingeschrankt,  wenn  sie  ein   Ganzprojekt-Make
    durchfuhren   anstatt  eines  modulspezifischen  Makes.  Der
    Vorteil  fur  das  Projekt  ist,  dass  der  modulzentrierte
    Entwickler  in  entscheidenden  Momenten  (und  nur  in  den
    entscheidenden) daran erinnert wird, dass seine Arbeit  auch
    weitgehendere Auswirkungen hat.

    Die  standige  Verwendung  von C-Include-Dateien, die genaue
    Interface-Definitionen  (einschlielich  Funktionsprototypen)
    enthalten,  wurde  in  vielen  Fallen zu Ubersetzungsfehlern
    fuhren, was wiederum  ein  fehlerhaftes  Produkt  zur  Folge
    hatte.  Werden  Builds  fur  das ganze Projekt durchgefuhrt,
    entdecken Entwickler solche Fehler  sehr  fruh  im  Entwick-
    lungsprozess  und  sind  in  der  Lage Fehlerbehebungen dann
    vorzunehmen, wenn sie den geringsten Aufwand verursachen.

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

    Das ist der interessanteste Einwand.  Irgenwann  einmal  vor
    langer  e C-Compiler aber beginnen den
    in Anfuhrungszeichen notierten Includepfad von dem Verzeich-
    nis  aus,  in  dem die Quelldatei erscheint; hier sind keine



    Peter Miller           3 January 2004                Page 11





    CM Magazin, Dec-2002          Probleme durch rekursives Make


    Veranderungen der Quelle notwendig. Falls Sie keinen ANSI C-
    konformen  C-Compiler  besitzen,  sollten  Sie  in  Betracht
    ziehen, so bald wie moglich einen GCC auf  Ihrem  System  zu
    installieren.

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

    Die  meiste  Zeit  sind  Entwickler  mitten  im  Projektbaum
    beschaftigt. Sie bearbeiten ein  oder  zwei  Dateien  lassen
    dann  Make durchlaufen, was ihre Veranderungen ubersezt, und
    probieren sie aus. Diesen Arbeitsschritt fuhren sie  taglich
    Dutzende  oder  Hunderte  Male aus. Es ware absurd, wenn sie
    gezwungen waren jedesmal das ganze Projekt zu bauen.

    Entwickler habe immer die Option, ein besonderes Zielprodukt
    fur  Make  zu  definieren. Das gilt immer, wir verlassen uns
    lediglich gewohnlich  auf  das  im  Makefile  des  aktuellen
    Verzeichnisses    vorgegebene    Zielprodukt,    um   unsere
    Befehlszeile zu verkurzen. Man  kann  also  auch  mit  einem
    Ganzprojekt-Makefile  sein  kleines Teilprodukt bauen, indem
    man einfach ein bestimmtes Zielprodukt definiert und,  falls
    die Befehlszeile zu lang wird, ein Pseudonym verwendet.

    Es  stellt  sich  aber auch die Frage, ob es immer so absurd
    ist, das ganze Projekt zu bauen. Wenn z. B.  eine  in  einem
    Modul  vorgenommene Anderung in anderen Modulen Auswirkungen
    hat, weil eine Abhangigkeit existiert,  die  dem  Entwickler
    nicht  bewusst ist (aber dem Makefile ist sie bewusst), ware
    es dann nicht besser, wenn der Entwickler das so schnell wie
    moglich  herausfindet?   Solche Abhangigkeiten werden gefun-
    den, weil der DAG  vollstandiger  ist  als  beim  rekursiven
    Vorgehen.

    In  den  seltensten  Fallen  sind Entwickler erfahrene, alte
    Hasen, die jede einzelne der Millionen von Zeilen  Kode  des
    Produktes   auswendig   kennen.  Meistens  haben  sie  einen
    zeitlich begrenzten Vertrag oder  sie  sind  jungere  Mitar-
    beiter.  Sie  wollen  naturlich nicht, dass Auswirkungen wie
    die eben beschriebene entdeckt werden, nachdem Ihre Anderun-
    gen  in  den  Hauptkode  einfugt  wurden, sondern wurden sie
    gerne ganz in Ruhe  in  ihrem  lokalen  Arbeitsbereich  ent-
    decken, weit weg vom Hauptkode.

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








    Ulrike Amoore          3 January 2004                Page 12





    CM Magazin, Dec-2002          Probleme durch rekursives Make


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

    Diese Aussage kann man fur eine von zwei Situationen machen:
    1.  Die  Durchfuhrung des Make eines ganzen Projekts dauert,
    obwohl alles aktualisiert ist, unvermeidlich sehr lange.  2.
    Diese  unvermeidbaren  Verzogerungen sind unakzeptabel, wenn
    der Entwickler die eine Datei, die er verandert hat, schnell
    kompilieren und linken will.

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

    Stellen  Sie  sich  ein  hypothetisches Projekt vor mit 1000
    Quelldateien (.c), von denen jede  ihre  Aufrufschnittstelle
    hat,  welche in der zugehorigen Include-Datei (.h) mit Defi-
    nitionen,   Typvereinbarungen   und   Funktionsdeklarationen
    definiert ist. Diese 1000 Quelldateien beinhalten ihre eige-
    nen Interfacedefinitionen und zusatzlich die  Interfacedefi-
    nitionen  aller  Module, die sie aufrufen konnen. Di