make, fuggosegek

Fórumok

Sziasztok!

Adott egy program forrasfaja, ezekkel a fileokkal:


./src/mymod/Makefile
./src/mymod/mymod.h
./src/mymod/mymod1.c
./src/mymod/mymod2.c
./src/Makefile
./src/prog.c

A kiosztas egyszeru": a "mymod" konyvtaracska all ket kisebb forrasmodulbol (

mymod1.o

es

mymod2.o

), ebbol csinalunk egy archivot (

mymod.a

), es a

prog.c

ezt az archivot haszna'lna'.

A

./src/Makefile

a kovetkezokeppen nez ki:


SHELL=/bin/sh

CC=@CC@
AR=@AR@
CFLAGS=@CFLAGS@

all: mymod prog

.PHONY: all clean mymod

mymod:
        $(MAKE) -C mymod

prog: prog.c XXXXX
        $(CC) $(CFLAGS) -o prog prog.c mymod/mymod.a

clean:
        $(MAKE) -C mymod clean
        rm -f prog *.a *.o

A problema a kovetkezo":

  • ha nem adom meg a
    prog:

    fuggosegei kozott a

    mymod

    -ot (mint phony target, a konyvtar maga, lasd XXXXX), akkor parhuzamosan (

    make -j

    ) nem lehet leforditani (mivel semmi sem utal ra' hogy a

    mymod/mymod.a

    archivtol fuggene, kiveve lasd: *)

  • ha a
    prog:

    fuggosegei kozott meg van adva a

    mymod

    , akkor lefordul, de egy rakovetkezo" sima

    make

    ujra leforditja a

    prog

    binarist, tokfeleslegesen, akkor is ha az egesz forrasfaba nem piszkalok bele

  • ha a
    prog:

    fuggosegei kozott meg ilyeneket adok meg mint

    mymod/mymod.a

    , akkor meg "no rule to make target mymod/mymod.a" szoveggel elszall a parhuzamos forditas

(*) Mindez annak ellenere, hogy az

all:

target-ben eloszor a

mymod

szerepel es csak utana a

prog

.

Mi lehet itt a gond es/vagy a megoldas? (a gyakorlati alkalmazas persze ennel egy fokkal bonyolultabb, ~200 forrasfile, ~18 konyvtar, ott jott ez elo, de me'g ilyen egyszeru lebutitott peldanal is szepen latszik hogy mi a gond).

koszi, A.

Hozzászólások

Olyannal már molyoltam, hogy több alkönyvtár, mindegyikben saját Makfile és a gyökérben lévő Makefile indításával fordul az egész project - de akkor még nem volt több procis masinám, amin ezt ki tudtam volna használni...
Sz'al a problémát án abban érzem, hogy az érdemi függőségek az alkönyvtárban lévő Makefile-okban vannak, amelyeket - értelemszerűen - a gyökérben lévő Makefile nem ismétel meg, így az azt feldolgozó make program nem is fogja ismerni azokat. Ennek eredménye, hogy ha a gyökérben lévő Makefile több szálon indul el, akkor baj van, mert vagy túl hamar kezd dolgozni a második szál, és már használná az első szál eredményét - ezzel előállt az első eset, a program nem fordítható -, vagy kamu feltételekkel kikényszerítjük a kivárást - akkor előállt a második eset, mert a kényszer hatására ha kell ha nem alapokon mindíg minden újrafordul.

Igazán szép ötletem nincs a dolog megoldására, mert az alkönyvtár Makefelie-jában adott kötöttségeket nagyon csúnya lenne a szülő Makefile-jába betenni - viszont kerülő megoldásra van egy kóbor gondolatom. Ne a gyökérben tolj több szálú fordítást, hanem az alkönyvtárakban. Tehát a
(MAKE) -C XXXX
sorok helyére írj
(MAKE) -j 2 -C XXXX
sorokat. Illetve ha még szebbé akarod tenni, akkor ne vasald be az értéket, hanem az jöjjön egy változóból, ami a Makefile elején kap értéket.

Innen kezdve illene működni a többszálú fordításnak, azzal a megkötéssel, hogy nem a szokásos -j opcióval adod meg, hanem a Makefile-ban egy változóval - és persze a gyökérben nem szabad a fordítást több szálon indítani.

Ha valakinek van szebb/jobb ötlete, arra én is kíváncsi vagyok... Mondjuk illene lennie, mert a kernel is fordítható több szálon és nem ezzel a trükkel van megoldva a függőségek kezelése, tehát ott használható a -j opció.

  • ~18 könyvtárnál nem nagy baj, ha csak a könyvtáron belül párhuzamosít
  • ekkora projektnél miért nem használsz automake-et??
  • mellesleg az automake által generált Makefile is egy szkripttel járja be:
    for subdir in $$list; do \
              echo "Making $$target in $$subdir"; \
              ...
              (cd $$subdir && $(MAKE) $$local_target) \
            done
    

szóval használj automake/autoconf kombót, az majd generál 150k-nyi Makefile-t

Aha, autoconf-ot en is hasznalok, automake-t viszont nem (az nagysagrendekkel bonyolultabb :]). A kerdes szerintem ettol fuggetlen, marmint hogy automake-e vagy sem, azert is jo szerintem hogy a topickezdetbe bekopizott kicsi peldaval tok jol lehet demonstralni a dolgokat. Mondjuk az jo otlet hogy "meg kell nezni hogy az automake mit csinal es azt csinalom en is", es akkor hatha jo lesz.

Kerdes, a `$(MAKE) -C subdir target` mennyire ekvivalens a `(cd subdir && $(MAKE) target)`-tel? A `make -j` szerintem kulon racuppan a `$(MAKE) -C` direktivakra, kulonben nehezen tudnam elkepzelni hogy egyszeruen parhuzamosithato lenne...

A.

Ha már megy az autoconf, nem vészes az automake (AM).

A kérdésre valóban nem válaszoltam (nem is tudok). Ha hobbiból akarod megtanulni, hajrá, és bocs az off-ért, de ha haladni akarsz a projekttel akkor szerintem AM, esetleg ccache.

A párhuzamosítást tekintve meg az AM nem a könyvtárak között párhuzamosít, hanem csak a könyvtáron belül. Ez -j2 kapcsoló, 10 fájl/könyvtár esetén durván 10 * 0,5 * (1 fájl fordítási ideje) mennyiséggel marad el az optimális fordítási időtől, (lásd még subset sum problem vagy részletösszeg feladat :) ) . Talán jobb is, mint ha durvább felbontással, a könyvtárakkal játszana.

Recursive Make Considered Harmful
Én a cikk alapján írtam nagy makefile-t (200+ forrásfájl) aminek illeszkednie kellett egy külsős makefile rendszerbe.
Bár a -j a pont a külsős makefile rendszer miatt nem működött, de szerintem ez megoldás lehet sok problémára.