"Hello World!" g++:lla

Aloitetaan jo tutuksi tulleella Hello World! -ohjelmalla. Ota esim. atk-keskuksen silmu.st.jyu.fi-koneeseen ssh-yhteys ja kirjoita johonkin sopivaan hakemistoon seuraava koodi (voit käyttää editorina picoa tai emacsia tai mitä ikinä haluatkin):

#include <iostream>

using namespace std;

int main(void)
{
  cout << "Hello World!\n"; 
  return 0;
}
Talleta esim. nimelle hello.cpp. Kääntäminen tapahtuu seuraavalla käskyllä:
g++ hello.cpp -o hello
... ja ajaminen näin:
./hello
Eli yksinkertaisimmillaan annetaan kääntämiskäsky (g++), käännettävä koodi (hello.cpp) ja nimi tuotokselle (-o hello). Tässä esimerkissä on kuitenkin ns. pistetty mutkat suoriksi, joten seuraavaksi ollaan vähän tarkempia.

kassa2.cpp g++:lla / gcc:llä

Ensimmäiseksi siirrä kassa2.cpp ( N:\kurssit\cpp\moniste\demo\c-ohj\kassa\kassa2.cpp) sekä mjonot.c, mjonot.h, mjonotpp.h ja streampr.h (N:\kurssit\cpp\ali\) jälleen esim. silmu-koneelle johonkin hakemistoon. (Huom! Siirrettäessä tiedostoja Windows-ympäristöstä Unix-ympäristöön erilaiset rivinvaihtomerkit saattavat aiheuttaa ongelmia.)

Käännetään mjonot.c. Siirry (ellet jo ole) siihen hakemistoon, jossa tiedostot ovat ja kirjoita käsky

gcc -c -Wall mjonot.c -o mjonot.o
Huomaa, että nyt käytettiin kääntäjää gcc, joka on sekä C- että C++-kääntäjä. g++ kääntää vain C++:aa, joten sitä ei voi mjonot.c:n kääntämíseen käyttää.

Optio -c kertoo, että tiedosto(t) halutaan ainoastaan kääntää, mutta ei linkittää ajettavaksi ohjelmaksi. (Äskeisessä tilanteessa niin ei voisikaan tehdä, mieti miksi! Jos haluat, voit kokeilla käskyä ilman -c optiota.) Käytettäessä optiota -Wall saadaan varoitukset käyttöön. Optiolla -o voi kertoa mille nimelle tiedosto käännetään. Oletus on sama nimi tarkentimella .o eli tässä tapauksessa -o olisi voitu jättää poiskin.

Käännetään seuraavaksi itse kassa2.cpp:

g++ -c -Wall kassa2.cpp 
Huomaa varoitukset! Voit kokeilla myös ilman -Wall optiota. g++:n sijaan tämä voitaisiin kääntää myös gcc:llä, mutta C++:aa käännettäessä kannattaa kuitenkin käyttää g++:aa sopivien oletusten vuoksi.

Seuraavaksi linkitetään:

g++ mjonot.o kassa2.o -o kassa
Jälleen -o:lla voidaan kertoa mikä output-tiedostolle (nyt siis ajettava ohjelma) halutaan nimeksi. g++ olettaa .o-loppuisten tiedostojen olevan valmiiksi käännettyjä, jolloin se ei yritä enää kääntää, vaan ainoastaan linkittää. Nyt ohjelma on valmis ajettavaksi (tosin se on keskeneräinen):
./kassa

Mutta mitä jos käännettävänä on hyvin suuri ohjelmisto, jossa on kymmeniä tiedostoja? Pitkän kääntämiskäskyn kirjoittaminen jokaisen muutoksen jälkeen tuntuu hullulta. Niin sitä ei tehdäkään, vaan avuksi otetaan makefile ja make-käsky. Makefilessa kuvataan mitkä kaikki tiedostot ohjelmaan kuuluvat ja kuinka ne käännetään. Makefilen avulla make-käsky osaa sitten kääntää koko ohjelman, ja huolehtii samalla myös siitä, että turhia käännöksiä ei tehdä, eli että ei käännetä niitä kooditiedostoja joihin ei ole tehty muutoksia (vrt. files.txt ja DemoWWW!). Tässä tapauksessa makefile näyttäisi suunnilleen tältä:


# kassa2.mak
# kassa2.cpp:n makefile
# "risuaidalla" alkavat rivit ovat kommenttia

kassa : kassa2.o mjonot.o
	g++ -Wall kassa2.o mjonot.o -o kassa
kassa2.o : kassa2.cpp
	g++ -c -Wall kassa2.cpp -o kassa2.o
mjonot.o : mjonot.c
	gcc -c -Wall mjonot.c -o mjonot.o
clean :
	rm kassa kassa2.o mjonot.o core
Huom! Sisennykset on tehtävä tab-näppäimellä! Ensimmäinen rivi (kommenttien jälkeen) kertoo, että tiedosto kassa riippuu kassa2.o:sta ja mjonot.o:sta ja seuraava rivi kertoo, kuinka kassa tehdään ko. tiedostoista. Vastaavasti seuraavat neljä riviä. Ohjelman kääntäminen tämän tiedoston avulla tapahtuu seuraavalla käskyllä (olettaen että em. tiedosto talletettu nimelle kassa2.mak):
make -f kassa2.mak
Makefilen clean-osa kertoo, miten "siivotaan" eli poistetaan prosessissa syntyneet tiedostot (siis objekti-tiedosto, ajettava tiedosto ja mahdollisesti ohjelman kaatuessa syntynyt core-tiedosto), käsky on tällöin
make -f kassa2.mak clean
Kirjoita kyseinen tiedosto ja kokeile! Tee sitten kassa2.cpp:ssä olevat tehtävät, käytä kääntämiseen make-käskyä.

P.S. Jos tiedostoja on hyvin paljon, edellä kuvatun tapainen makefile käy kömpelöksi: riveistä tulee todella pitkiä, tai samanlaisia rivejä tulee paljon. Makefilessa käytetäänkin yleensä muuttujia ja makroja yksinkertaistamaan esitystä.

P.P.S. Fiksu huomaa, että koska makefileen tarvitsi kirjoittaa itse kääntämiskomennot, make ei liity ainoastaan C/C++-kääntämiseen, vaan sitä voisi yhtä hyvin käyttää vaikka Fortran-koodiin. Itse asiassa make ja makefile käyvät työkaluiksi mihin tahansa tilanteeseen, jossa tiedostot riippuvat toisistaan ja niitä päivitetään jollakin tavalla. Lisätietoja esim. http://www.gnu.org/manual/make-3.79.1/html_node/make_toc.html