Zdravo,

Ne secam se da li sam vec objasnio VS problem, tj. moje vidjenje istog i kako bi trebalo pod linux-om da se kompajlira poveci projekat.

Recenica prof. Milićeva je tacna, ako se uradi sledece, sto Dušanu i savetujem:
Gde god da se nadje #include "pera.abc", mozes da se copy paste-uje sadrzaj fajla pera.abc umesto te include direktive.
Dušane, ako to uradis za prvu verziju softvera koja ti nije radila (jednostavnija je, ima manje fajlova, nema biblioteke), videces da ces dobiti jedan veliki main.cpp i tada se stvarno u jednom fajlu nalazi sve sto ti treba. Takav fajl bi trebalo da mozes da kompajliras i u VS.
Mislim da je problem VS to sto pokusava nezavisno da kompajlira neki tamo cpp fajl, pa kuka ako mu nesto fali.
U sustini, dobro bi i za Linux bilo da imamo Makefile koji kompajlira nezavisno fajlove, pa na kraju linkuje. Taj deo smo za pocetak preskocili, pogotovo imajuci u vidu da ne koriste svi Linux. Da bi mogao svaki fajl da se kompajlira nezavisno, bilo bi potrebno da svaki include-uje hpp sa deklaracijama koje mu trebaju.

Pozdrav,
Nenad

On Wed, Mar 9, 2022 at 12:33 AM Marko Vojinovic <vmarko@ipb.ac.rs> wrote:

Pozdrav Dusane,

Nisam do kraja siguran sta te tacno zbunjuje, i verovatno ce Nenad i Jaroslav moci da ti odgovore pametnije od mene, ali evo da probam...

Prvo --- obrati paznju da na pocetku *svakog* .cpp fajla (a ne samo main.cpp fajla!!) include-ujemo ceo triangulator.hpp fajl, koji u sebe include-uje sve ostale .hpp fajlove. To znaci da preprocesor dobije deklaracije *svih* klasa i *svih* f-ja kroz triangulator.hpp (sve je forward-deklarisano u .hpp fajlovima), pre nego sto stigne do bilo kog parceta koda koje zapravo treba kompajlirati. Tako da (nakon preprocesora) kompajler tj. prevodilac ima sve simbole i sva imena vec definisana kad pocne da radi na bilo kom .cpp fajlu. Tako da nema za sta da prijavi gresku, ni za jedan od .cpp fajlova koji kompajlira.

Drugo --- treba da ti bude jasan dizajn naseg koda. Mi pravimo nesto sto se zove "static library", biblioteka rutina koju korisnik treba da linkuje sa svojim main.cpp fajlom u nekom svom kodu, i da poziva gotove f-je koje smo mi napravili. Nas main.cpp radi upravo tako, i sluzi nam za testiranje f-ja biblioteke. Sam main.cpp naravno nije deo biblioteke, ali svi ostali .hpp i .cpp fajlovi jesu.

Biblioteke rutina su potpuno normalna i standardna stvar, i vec ih koristis u svakodnevnom programiranju --- na primer, kada treba nesto da izracunas pomocu trigonometrijskih f-ja ili sl. u svom C++ kodu, ti include-ujes math.h header (ili kako se vec zove) u svoj main.cpp. I onda, nakon kompajliranja tvog fajla, linker automatski ulinkuje u tvoj izvrsni fajl i biblioteku math-library.a (verovatno se zove drugacije, i nije staticka nego neki .dll ili stagod), u kojoj se nalaze prekompajlirani object-fajlovi koji sadrze implementacije za sinus, kosinus, isl --- tebi je dovoljno samo da ih pozoves u svom main.cpp kodu, jer ih je neko drugi vec implementirao i spakovao u biblioteku. Neki zamisljeni krajnji korisnik dakle treba da upotrebljava nasu biblioteku rutina na *potpuno isti* nacin kao sto upotrebljava math.h, string.h, stagod.h...

Detalji i objasnjenja sta su biblioteke rutina (static, shared i dynamic tipovi), kako rade i cemu sluze, mozes da procitas u Program Library HOWTO [1], ako te zanima. HOWTO je pisan za Linux, ali sustina i koncepti su isti i za Windows (mozda se samo drugacije zovu, .dll ili vec kako). U svakom slucaju, rezime je da je staticka biblioteka prosto jedna arhiva (poput .zip fajla) u koju je "zapakovana" gomila kompajliranih object-fajlova u jednu konzistentnu celinu. I onda, kada korisnik pise svoj main.cpp fajl, on prosto moze da include-uje triangulator.hpp (cime za preprocesor i kompajler obezbedi forward-deklaracije svih imena i simbola), zatim kompajlira svoj main.cpp (koji koristi te f-je i simbole), i na kraju u njega ulinkuje nasu biblioteku (triangulator-library.a), cime dobije izvrsni (executable) fajl. I to je sve.

Nas main.cpp fajl to vec sada tako radi (mozes da pogledas build-script.sh da vidis kako g++ pravi biblioteku i kako je ulinkuje sa main.cpp-om...), ali prvi "ozbiljan" primer upotrebe nase biblioteke ce da bude GUI (koji je Jaroslav poceo da pravi) --- to ce na kraju da bude jedan izvrsni fajl, koji ce da otvara prozore po ekranu i da pise i crta po njima, i usput ce da poziva i izvrsava f-je iz nase biblioteke rutina. Jaroslav ce u main.cpp za GUI da include-uje triangulator.hpp, da poziva po potrebi sve f-je iz nase biblioteke (kako mu koja gde treba), i onda ce tokom kompajliranja GUI koda da ulinkuje triangulator-library.a biblioteku (koja je po pretpostavci vec ranije napravljena), cime ce dobiti izvrsni fajl "triangulator-gui.exe". Naravno, moguce je i potrpati zajedno sav kod (i za biblioteku i za GUI) na jedno mesto i kompajlirati sve odjednom. Ali inteligentnije je da imamo dizajn tako da biblioteka rutina bude konceptualno odvojena od GUI-ja. Tako bismo omogucili nekom tre
 cem korisniku da upotrebljava nase f-je u nekom svom izvrsnom programu, a ne iskljucivo kroz nas GUI ili sl.

I na kraju --- ne znam kako Visual Studio tretira ceo kod, sta sa cime linkuje itd., ali mozes u build-script.sh da vidis kako to radi g++, i sta je cilj. Pretpostavljam da VS moze da se podesi da sve nase .cpp fajlove spakuje u jednu biblioteku triangulator-library.dll, koju ce onda moci da ulinkuje prilikom kompajliranja main.cpp fajla i da dobije .exe fajl. VS verovatno nesto slicno radi vec i sada, samo mozda ne pravi taj .dll fajl nego odmah sve object-fajlove (od svakog naseg pojedinacnog .cpp fajla) na kraju zajedno ulinkuje sa main.cpp u izvrsni fajl. Za sada jos uvek nije vazno kako on to tacno izvodi --- kreiranje .dll fajla cemo da rascistimo i organizujemo sve kako treba kad budemo napravili Makefile za ceo projekt, zasad jos mozemo bez toga.

Ok, nadam se da cela ova prica baca malo vise svetla na zamisao i organizaciju celog koda. ;-)

:-)
Marko

[1] https://tldp.org/HOWTO/Program-Library-HOWTO/index.html


Dr. Marko Vojinovic
Group for Gravitation, Particles and Fields
Institute of Physics
University of Belgrade
======================
home page: www.markovojinovic.com
e-mail:    vmarko@ipb.ac.rs



On Tue, 8 Mar 2022, Dusan Cvijetic wrote:

> Pozdrav,
>
> Otvaram ovaj thread jer mi se čini da bi bilo dobro da imamo sva pitanja koja nisu vezana za neki konkretan zadatak na jednom mestu.
>
> Ako se sećate, u početku sam imao problem što kod nije mogao da se prevodi u Visual Studio-u, dok je sasvim dobro radio sa gcc. To je u međuvremenu razrešeno, ali sada mi uopšte nije
> jasno kako se kod za triangulator bilo gde prevodi.
>
> Koliko mi je poznato, prevođenje se vrši iz tri faze: pretprocesor vrši leksičku obradu, zatim se izdvajaju tokeni iz sirovog teksta, koje builder koristi da bi kreirao .obj fajlove. Na
> kraju, linker prolazi kroz .obj fajlove i povezuje deklaracije sa definicjama, ukoliko se nisu nalazile u istom fajlu.
>
> Stil programiranja sa kojim sam se do sad susreo je nalagao da u .hpp fajl u kome koristim neko ime uključim .hpp fajl sa odgovarajućom deklaracijom. Tako bih, recimo, morao da uključim
> colors.hpp direktno u classes.hpp, jer je jedno od polja KSimplex-a lista boja koje ga opisuju. Kada uključim colors.hpp na početku fajla, builder zna deklaraciju klase Color i nema
> problema.
>
> Međutim, mi to ne radimo, već sve deklaracije uključujemo u triangulator.hpp, i zatim to dalje u main.cpp. Nije mi jasno kako builder "zna" deklaraciju klase Color unutar fajla
> classes.hpp.
>
> U knjizi (Milićev, 1995, str. 71) sam našao:
>
>       Zbog potpuno nezavisnog prevođenja jednog fajla (prevodilac "ne vidi" ništa drugo osim onoga što se nalazi u fajlu koji trenutno prevodi), svaki programski fajl treba da
>       sadrži sve što je potrebno za uspešno prevođenje tog fajla. To znači da je potrebno da u svakom fajlu postoje odgovarajuće deklaracije svih imena koja se u fajlu koriste.
>       Svako korišćenje imena bez prethodne deklaracije u fajlu prevodilac prijavljuje kao grešku. /.../ Deklaracije imena navode se u svim fajlovima u kojima se ta imena koriste.
>
>
> Prema gornjem teksu, očekivao bih da prevodilac baci grešku jer mu ime klase Color nije definisano. Ipak, nešto ranije na istoj strani, prof. Milićev je napisao i:
>
>       Prevodilac prevodi svaki programski fajl (skoro) potpuno nezavisno, ne znajući koji sve fajlovi čine program.
>
>
> Pretpostavio sam da rešenje moje nejasnoće leži u ovome (skoro), ali nisam uspeo na internetu da nađem nikakve detalje koji bi mi razjasnili kako radi prevodilac u VS.
>
> Da li bi neko mogao da mi objasni zašto naš kod radi?
>
> Pozdravi,
> Dušan
>
> (1) Milićev, D, Objektno orijentisano programiranje na jeziku C++, Beograd, 1995.
>
>
>
>--
QGHG-it-dev-list mailing list
QGHG-it-dev-list@ipb.ac.rs
http://mail.ipb.ac.rs/mailman/listinfo/qghg-it-dev-list