build systems

12 views
Skip to first unread message

Attila Lendvai

unread,
Feb 24, 2021, 2:54:50 PM2/24/21
to compiler-seminar-budapest
Dani,

ez lehet, h egy kicsit magasabb perspektiva, mint amire te gondoltal, de ez (is) egy jo iras azon a blog-on:


- attila
PGP: 5D5F 45C7 DFCD 0A39


Daniel Berenyi

unread,
Feb 27, 2021, 1:38:22 PM2/27/21
to Attila Lendvai, compiler-seminar-budapest
Hát, igen, ez az írás valóban érdekes és messzemenő, de talán túlságosan is, és talán nem rögtön azzal indítanék h a build dolgokat is a nyelvbe / compilerbe integrálom:)

Az eredeti kérdésem az lett volna, hogy szerintetek hol választódik el a fordító és a build rendszer szerepköre. Sajnos én csak a C++ és cmake részt ismerem valamennyire, a többi nyelv megoldásairól nincs elég ismeretem.
Írnátok dolgokat, ami szerintetek releváns ehhez a témakörhöz, kérdéshez?

D.

--
Azért kapta ezt az üzenetet, mert feliratkozott a Google Csoportok „compiler-seminar-budapest” csoportjára.
Az erről a csoportról és az ahhoz kapcsolódó e-mailekről való leiratkozáshoz küldjön egy e-amailt a(z) compiler-seminar-b...@googlegroups.com címre.
Ha szeretné megtekinteni ezt a beszélgetést az interneten, látogasson el ide: https://groups.google.com/d/msgid/compiler-seminar-budapest/gVZO8_GijEcZ5Ar1lJykRR-sJ2jTOZOok_n7UMh-QbEKkkN05R0HhM5s5VDhJIPSo895Hu6fF9h22p9o-dkFqs8QAh_eGS9pcmAmOzUqkoM%3D%40lendvai.name.

Gábor Horváth

unread,
Feb 27, 2021, 1:53:25 PM2/27/21
to Daniel Berenyi, Attila Lendvai, compiler-seminar-budapest
Sziasztok!

Sajnos a build dolgokat nem tudod a nyelvbe/compilerbe integralni altalaban. A realitas az, hogy nagyobb ipari szoftverek gyakran tobb nyelvet hasznalnak, pl egy Python alkalmazas hasznalhat C-ben irt modulokat stb. Ha egy jo build rendszer tamogat tobb nyelvu projektet, akkor az eredendoen nem lehet a nyelvbe epitve, mert akkor minden nyelvnek kompatibilisnek kellene lennie minden massal build szempontbol.  Ez szerintem ad egy jo valaszt is ra, hogy miert es hol valik el a fordito es a build rendszer szerepkore.

Emellett, egy jo build rendszer:
* Enged futtatni statikus analizist, akar olyan toolokat is amiknek semmi koze a forditokhoz
* Enged futtatni dinamikus analizist, code coverage merest, teszteket, stb
* Deploy, install, installer keszites, stb
* Resource-ok kezelese (pl ikonok, lokalizacios string tablak stb)
* Felmerul a kerdes, h a dependency kezeles mennyiben a build rendszer feladatkore, mennyiben kulon toole
* Ha tobb fordito van egy nyelvhez, mas mas flagekkel, akkor jo ha a build rendszer tud efelett absztrahalni, pl a build rendszerben be tudjam allitani fordito fuggetlenul, h magas warning szintet akarok, es ne kelljen minden fordito flagjait kulon ismernem, megis forduljon veluk a projekt
* Reprodukalhato binarisok bitrol bitre

Valoszinuleg a fentiekbol nem feltetlenul akarsz mindent a nyelvbe/compilerbe belerakni.

Udv,
Gabor

Kéri Kálmán

unread,
Feb 27, 2021, 2:49:17 PM2/27/21
to Gábor Horváth, Daniel Berenyi, Attila Lendvai, compiler-seminar-budapest
Sziasztok!

Nekem az a szempont jutott eszembe, amire Gábor is utalt, hogy mennyit kell tudnia a fordítónak a fordítási egységek közötti függőségről. Ez kapcsolatban van azzal, hogy az adott nyelv le tudja-e írni a függőségeket, és ha igen, milyen topológiát enged meg.

A C a legegyszerűbb ilyen szempontból. A fordító mit sem tud a függőségekről és szeparáltan kezeli a fordítási egységeket. A header fájlok függőségeit az előfordító dolgozza fel, ami akár külön szoftver is lehetne, ahogy az is volt eredetileg. Pascalban emlékeim szerint minden forrásfájl egy unit, és a unitok körpályamentes függőségi gráfot alkotnak. A fordító postorder bejárással olyan mélyre megy a gráfban, amíg lefordított unitot talál, aminek a dátuma frissebb, mint a forrásé. Vagyis átveszi a make szerepét.
A Java a legbonyolultabb, ahol a forrásfájlok szabadon körbehivatkozhatják egymást. Itt esély sincs rá, hogy a make-re bízzuk a függőségek felderítését, mert általában nincs olyan helyes sorrend, amikor egyszerre csak egy fordítási egységgel kell foglalkozni. A fordító dolga, hogy felderítse a köröket, és az összes érintett fordítási egységet párhuzamosan fordítsa. Nagyjából ezt a három variánst ismerem.

Üdv,
K.

Daniel Berenyi

unread,
Mar 1, 2021, 2:42:18 PM3/1/21
to Kéri Kálmán, Gábor Horváth, Attila Lendvai, compiler-seminar-budapest
Szóval az ngnghm-es írás szemléletével nézve Gábor pontjait, nekem azaz érzésem támad, hogyha az ember nyelvében van metaprogeramozás és/vagy staging, akkor a Gábor által írt pontok/lépések igazából csak bulit-inek ezen a meta szinten, akár mint forrás fálj, akár mint leforditott artifakt, stb. Ha ezek néven nevezhetőek és az őket manipuláló built-inek megvannak, akkor tényleg kifejezhetőnek tűnik az egész build rendszer a nyelvben magában.

Kérdés, hogy mik a nem triviális dolgok.
Az egyik, ami az eszembe jut, hogy a fordítás maga innentől nem pure, hanem stateful, és ezt a state-t valahol tárolni kell és odaadni a fordító meghívásakor.

A dependency-s dolgot nem értem pontosan, hogy miért bonyolult. Van egy gráfunk és bejárjuk. A definíciók feloldását meg postponolni kell addig, ameddig minden függőség modul szinten értelmezve lett, hogy melyikben van a keresett név feloldása. Vagy ez nem ilyen egyszerű és nem látok valamit? A többi nyelvek bénázásai talán inkább régről magukkal hordozott limitációk eredményei, nem?

Még várok arra, hogy a rust build rendszeréről írjatok valamit (Lehel Gábor?), mert talán az a legfrissebb ilyesmi...

Illetve ezen a ponton talán két dolog is van, amit dependencynek lehet hívni, minimális eltéréssel: az egyik simán az, hogy van a sok forrás fájl, és hivatkoznak egymásra, a másik meg, hogy egyes forrásfájlok és modulok egész könyvtárakként jönnek kívülről, és ezeknek vannak verzióik, és kezelni kell azt, hogy a mi progamunk milyen verziókra dependál. Nem tudom ez mennyire ugyan az, nem ugyan az. Pl. a cargo kezeli a függőségek verzióit, a cmake magától könnyen nem annyira, ha jól tudom.

üdv,
D.

Gábor Horváth

unread,
Mar 1, 2021, 2:56:11 PM3/1/21
to Daniel Berenyi, Kéri Kálmán, Attila Lendvai, compiler-seminar-budapest
Egyetertek azzal, hogy meg lehet oldani a nyelv reszekent mindent, de nem vagyok benne biztos, hogy kellene-e ezt csinalni. Az egyik problema, hogy amint egy altalanos celu programozasi nyelvunk van, barmit megtehetunk az adott nyelvben, ami potencialisan nehezebben megertehtove teszi a build rendszert. Nehany ujabb megkozelites (pl Meson) direkt nem turing teljes. A masik problema, hogy ha minden nyelvnek van egy sajat beepitett build rendszere, akkor egy 5 nyelven irt projektben 5 buildrendszer  (potencialisan 5 alatt a 2) kulonbozo interakcioi kellene, hogy kompatibilisek legyenek egymassal. Persze a gyakorlatban most is hasonlo a helyzet (hogy egymast hivogatjak kulonbozo build rendszerek), de ez nem mindig idealis. 

Kéri Kálmán

unread,
Mar 1, 2021, 3:03:44 PM3/1/21
to Daniel Berenyi, Gábor Horváth, Attila Lendvai, compiler-seminar-budapest
A dependency-s dolgot nem értem pontosan, hogy miért bonyolult. 

Csak relatíve bonyolult. Ha már megvan hozzá a kellő apparátus, akkor nem az. Amikor ezzel foglalkoztam, lényegében azt csináltam, amit írsz, de előtte csak a C-szerű megoldást ismertem. A C nyelv megkötéseinek szerintem az volt a célja, hogy lehessen egy menetes fordítást csinálni, ami annak idején a szűkös erőforrások miatt előny lehetett.

Gábor Lehel

unread,
Mar 2, 2021, 5:28:29 AM3/2/21
to Kéri Kálmán, Daniel Berenyi, Gábor Horváth, Attila Lendvai, compiler-seminar-budapest
(Csak mert szóba kerültem: a build systemeket meg a Cargo-t nem vágom különösebben. Ezt a cikket tudom csak ajánlani, mint kötelező olvasmány a témakörben: https://www.microsoft.com/en-us/research/uploads/prod/2020/04/build-systems-jfp.pdf de nem tudom, hogy a most szóban forgó kérdéseket mennyiben érinti.)

Nagy-Egri Máté Ferenc

unread,
Mar 8, 2021, 3:29:14 PM3/8/21
to Gábor Lehel, Kéri Kálmán, Daniel Berenyi, Gábor Horváth, Attila Lendvai, compiler-seminar-budapest

Na, nagy nehezen eljutottam oda, hogy az igen hosszú blog bejegyzést és a teljes beszélgetést (kivéve Lehel Gábor utolsó MS Research anyagát) elolvassam. Mivel a téma közel áll a szívemhez és állatira szeretnék írni valamit ebben a témában, szerettem volna hozzászólni.

 

A blog bejegyzés egész jól körbejárja a témát, de az alatta lévő Disqus diskurzus egy olvasó és a szerző közt is informatív. Magába a nyelvbe integrálni a build systemet szerintem sem éri meg. A turing teljesség (ahogy Meson dícséretesen tartózkodik tőle) kerülése segít abban, hogy a build definition (lettlégyen az bármilyen nyelvben) kizárólag a buildre szorítkozzon. Valóban elveszítünk sok mindent azzal, ha nem a nyelvünkbe integrálva, vagy azzal 100% kölcsönhatni képesen kapjuk meg a build systemet, de rengeteg problémától mentesítjük magunkat. Ahogy Horváth Gábor is mondta, production rendszerek több nyelvet használnak és ezeket valahogy közös nevezőre kell tudni hozni.

 

A blog szerzője szerintem pár dolgot nem vett figyelembe, amit Dani is érintett. Nekem nagyon úgy tűnt, mintha kizárólag disken lévő inputokban és outputokban gondolkozna. (Amikor a Gitet behozza, és a repo fájlnevei és a forrásban hivatkozott „#include”-ok közti megfeleltetésről beszél, ott is a fájlokat valószínűleg végsősoron diskről szedné, ami a később említett „cache”-eléssel érne el.) A tavaly előtti Lambda Days alkalmával volt egy elgondolkodtató előadás a build system vs. build server közti különbségekről. Az óriási előnye a build server megközelítésnek (amit Bazel is képvisel), hogy folyamatosan fut és tud state-et őrizni. Nem kell mindent diskről timestamp-eken alapján betölteni. Egy IDE vonatkozásában főleg óriási előnye van. Gondolok itt arra, ha a build definícióm le van írva, akkor az IDE hozzá tud fűzni taskokat ehhez a taskokból álló aciklikus gráfhoz, például IntelliSense taskokat. Ha megnyitok egy forrásfájlt, akkor hozzáfűzi az ahhoz tartozó IntelliSense feladatokat magas prioritással, elvégre az egy felhasználói kérés, egy exe linkelése várhat. A háttérben futhat statikus analízis és cachelődhet, de ha a felhasználó megnyomja a hozzá tartozó gombot, hogy most érdekli az eredmény, akkor prioritást vált. Mobilokon, Apple M1-en vagy új Intel procikon ahol Big.Little magok vannak a háttér feladatok priorizálhatók a kis magokra, GUI-ról kért feladatok a nagy magokra kerülnének, ilyesmi.

 

A build szerver előnye még, hogy memóriában meg tud tartani olyan adatokat, amiket így nem kell diskről töltögetni folyton. C++ esetében elég bonyolult és erőforrás igényes a preprocess, de akár már a parse-olás is. (Kedvenc adalékom C++ parse-olás szörnyűségeihez az a szörnyű tény, hogy C++ parse-olásához ki kell értékelni / futtatni kell a kódot magát, sokszor akár back-track jelleggel.) A fordításhoz, az IntelliSense-hez, a statikus kód analízishez, Clang tidyhoz, code coverage-hez, stb. mind-mind el kell végezni bizonyos lépéseket, amit ezer és egyszer elvégez minden tool, mert minden két hívás között elfelejt mindent. De mekkora lenne már, ha van egy toolchain-em, amiknek a darabjai beszélik egymás nyelvét, akkor tetszőleges köztes adatstruktúrát meg tudna jegyezni, hogy a többi eszköz újrahasználja. Ez MSVC esetében IPR/XPR lenne (Internal Program Representation a fordító belső állapota, XPR a szerializált formája), Clang esetében nem tudom mi a belső és a szerializált eredménye a parse-nak... De mondhatnám ugyanezt XML-re, ahol EXI a szerializált eredménye a parse-nak, stb.

 

Végső soron a Mesonhoz hasonló, nem-Turing teljes megközelítést kéne követni, Bazel-szerűen nem szigorúan szétválasztva a configure és fordítás lépéseit (egy taskról végrehajtás nélkül nem feltétlen derül ki hány child taskja van), build2-höz hasonlóan a fordításon túlmutatóan tesztelésre és CI-ra is kiterjedően, értelmes IDE integrációt lehetővé tevő módon, MSBuild-hez hasonlóan programmatikusan/CLI/GUI front-enddel egyaránt kellene egy normális build system. Nem lehetetlen (nem is könnyű), csak össze kellene ollózni mindenhonnan a jó dolgokat. Pár momentumot felvillantottam az okfejtésben, és a téma indító blog bejegyzés jó gondolatébresztő a témához és lesz is amit meg kell rágni belőle. (Bár szerintem 1:1-ben gyakorlatban nem használható.)

 

Elég sokat agyaltam már rajta, hogyan kellene nekiállni egy ilyen dolognak, milyen technológiákat lehetne használni útközben (bár a requirementek fontosabbak, mint a megvalósításhoz használt konkrét eszközök) és végső soron mit kéne tudnia. A legeslegfontosabb a bővíthetőség, hogy a build system csak az építőköveket definiálja, amivel aztán belátható munkával lehessen fordítási modellt definiálni és hozzá toolchaineket, akár olyan bonyolultakat is mint az LLVM eszközcsalád. Egy faék egyszerű .plt fájlból .svg/.png/.jpg/… be GnuPlottal fordító egy lépcsős toolchaint viszont egy majom is össze tudjon rakni. Productionben tényleg nagyon sok technológia kavarodik: C/C++, Doxygen, Sphinx, LaTeX, CUDA/HIP, GLSL (glslang), Python, GI typelib, stb. a lista végtelen és kimeríthetetlen. Toolchain definíciónál le kellene szokni a mindent process isolationben futtatásról, mert úgy tényleg csak disken keresztül lehet kommunikálni, ami halál fölösleges. Kényelmes, de erőforrás pazarló.

 

Feladó: Gábor Lehel
Elküldve: 2021. március 2., kedd 11:28
Címzett: Kéri Kálmán
Másolatot kap: Daniel Berenyi; Gábor Horváth; Attila Lendvai; compiler-seminar-budapest
Tárgy: Re: build systems

Reply all
Reply to author
Forward
0 new messages