make, fuggosegek

 ( apal | 2009. augusztus 8., szombat - 23:28 )

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":

  1. 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: *)
  2. 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
  3. 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ás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

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.

Aha, koszi, ezt megnezem!

A.

cmake FTW! :)

Koszi, megnezem. man -Tps cmake >cmake.1.ps ... csak 160 oldal, apro betukkel ;)

http://cmake.org/cmake/help/cmake2.6docs.html sokkal attekinthetobb.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Sokat tud, de szerintem neked pl egy ilyen elég is lesz a jelenlegi problémádhoz. :)