C++ i Unix 1 TDT4102 NTNU 1 Innledning av Åsmund Ervik, jan. 2011 Dette dokumentet skal veilede deg gjennom å skrive og kompilere programmer i C++ på NTNUs sentrale Unix/Linux-server 1. Dette vil gi deg en bedre innsikt i hva kompilering egentlig er, og du vil kunne jobbe nesten overalt uten å måtte installere Visual Studio. Du slipper også å bruke tid på å lære dette når du egentlig skulle skrevet masteroppgave! Er det noen seriøse mennesker som bruker Unix, eller er dette bare et leketøy for geeks? Dette spørsmålet er kanskje naturlig siden de fleste datamaskiner du har vært borti kjører Windows. Men hvis du tar en titt på listen over verdens 500 raskeste datamaskiner, www.top500.org, vil du oppdage at 99% kjører Unix (november 2010). Datagrafikken fra de fleste Hollywood-filmer stammer også fra Unix-systemer. 2 I den andre enden av skalaen finner vi Android-systemet på mange smart-telefoner, som også er en Unix-variant. Dette er bare noen eksempler, og de fleste vil iløpet av sitt arbeidsliv komme borti med Unix. Hvis du allerede vet hvordan man skriver og kompilerer programmer i Unix, kan du gå til avsnittet om makefiles (8) og lære noe kult der. 2 Fremgangsmåte Hvilken fremgangsmåte du kan bruke avhenger litt av forutsetningene. Dersom du har Windows, og du har mulighet til å montere hjemmeområdet ditt 3, er det hele ganske enkelt. Da kan du skrive koden din ved hjelp av Notepad++ eller lignende, og så kompilere den. Se avsnitt 3, 5 og så 7. Dersom må jobbe uten hjemmeområdet ditt, må du skrive programmet ditt direkte på Unix-serveren. Det er litt mer arbeid, men ikke mye. Følg da instruksene i avsnitt 3, 5, 6, og så 7. Til slutt, hvis du selv har en maskin med Unix (Linux) eller Mac OSX, trenger du ikke logge deg inn på NTNU-serveren. Da kan du kjøre alt lokalt, men du må kanskje installere noen ting. Se avsnitt 4 for installering av ting, og så avsnitt 5 og 7. 3 Windows - installering For å kunne logge deg inn på NTNU-serveren, trenger du et program som heter Putty. Det kan du laste ned fra www.putty.org. Følger du lenken, og blar litt ned, finner du mange filer. Her trenger du bare å laste ned putty.exe. Når du har lastet ned denne filen, kan du åpne den. Her trengs ingen installasjon! I programmet som starter opp, skriver du login.stud.ntnu.no. Så velger du Translation i menyen til venstre, og skriver inn UTF-8. Så trykker du på open. Nå blir du spurt om brukernavn og passord, og så er du inne! 1 fra nå av bruker vi samlebetegnelsen Unix til å bety Linux, Unix, Solaris, etc. 2 et eksempel er Avatar, som ble rendret på et cluster bestående av over 4000 Linux-servere med totalt 40 000 kjerner og 104 000 GB RAM... Dette var fortsatt kun den 193. raskeste maskinen i verden da den ble bygd. 3 se artikkelen på Orakel-nettsiden. Merk at Windows 7 må benytte \\felles.ntnu.no\home\student istedet for den gamle adressen. 1
C++ i Unix 2 TDT4102 NTNU 4 Linux eller Mac OSX - installering For å kunne kjøre på din egen maskin, er det to ting du trenger: en teksteditor og en kompilator. En grei teksteditor er kanskje ferdig installert; på Linux finnes nok enten Kate eller Gedit, mens på Mac OSX kan du laste ned TextWrangler som er en grei, gratis teksteditor. Når det gjelder kompilator er det greiest på Linux. Forsøk å skrive inn g++ i kommandolinjen. Dersom du får g++: no input files, er alt vel, og du kan åpne en terminal og gå videre til neste avsnitt. Dersom du får command not found: g++ må du installere kompilatoren. På Ubuntu heter pakken build-essential, generelt så finner du fram ved å søke på g++ i pakkebehandleren din. Så kan du åpne en terminal, fortsette med neste avsnitt. På Mac OSX må du installere XCode. Det er en ganske svær pakke, så det anbefales at du installerer det fra CD-en som fulgte med maskinen din. 4 Når du har gjort det, kan du åpne en terminal (under Applications->Utilities), og fortsette med neste avsnitt. 5 Back to basics Først av alt må du lære å navigere i filsystemet på Unix. Her finnes det ingen utforsker, og tastaturet er din beste venn. Mappen du starter i er hjemmeområdet ditt, eller hjemmemappen din hvis du sitter på Linux eller Mac. Utfør følgende oppgave: Skriv ls og så enter(ls, ikke 1s). Du får opp en liste med filer og mapper på hjemmeområdet ditt. Lag en ny mappe : mkdir NyMappe (enter) Gå inn i den nye mappen: cd NyMappe (enter) Sjekk innholdet i mappen: ls (mappen er tom) Lag enda en ny mappe: mkdir MappeInniMappe Kopier denne: cp MappeInniMappe MappeInniMappe2 Sjekk innholdet i mappen: ls Gå ut av mappen igjen: cd.. Sjekk at du er på hjemmeområdet ditt igjen (ls) Finn stien til hjemme-mappen din: pwd. Denne ser nok ut som /home/homeo/ol/oleper, eller /home/oleper på Linux/Mac. Slett mappen du lagde: rm -r NyMappe (sletter også alle filer i mappen). Denne kommandoen bør brukes med forsiktighet - her finnes det ingen søppelbøtte slik at du kan angre! 4 Hvorfor du må installere 4GB for å kunne bruke en kompilator som er et par MB stor, får du spørre Steve Jobs om. 2
C++ i Unix 3 TDT4102 NTNU Hvis du lurer mer på hvordan en kommando virker, kan du skrive f.eks. ls --help eller man ls. Den første er mer kortfattet enn den siste. For å komme ut av man trykker du q. Nå kan du nok til å komme deg rundt i filsystemet. Da er det bare å finne frem til mappen der du vil lagre programmet ditt! Dersom du har montert hjemmeområdet ditt, eller har Linux/Mac, må du finne fram til den filen som du lagrer med teksteditoren din. Hvis du lagrer filen med etternavnet.cpp, vil du sannsynligvis få fargekoding automatisk. Husk å lagre filen før du prøver å kompilere den! Husk at du kan sjekke innholdet i mappen du er i med kommandoen ls. Hvis filen du vil kompilere ikke står i den listen som kommer opp, må du navigere til riktig mappe. Du må også lagre etter hver endring du har gjort! 6 Å skrive et program uten tilgang til hjemmeområdet (Hopp over dette avsnittet dersom du har montert hjemmeområdet ditt, eller bruker Linux/Mac.) For å skrive et program, trenger vi en teksteditor. Har du en personlig favoritt, bruker du den. Hvis ikke, anbefales Vim. Denne editoren er du garantert å finne på alle Unix-systemer og på Mac OS X, og kan installeres på Windows. La oss skrive et dokument! Finn en mappe (eller lag en ny) der du skal ha dokumentet ditt. Start et nytt dokument med vim minkode.cpp. Nå får du opp en blank fil. Neste gang du skal åpne dette dokumentet bruker du samme kommando. Nå trykker du tasten i. Da står det --INSERT-- nederst til venstre, og du kan skrive i vei. Skriv f.eks. #include <iostream>. Du kan bruke piltastene til å bevege deg rundt i dokumentet - musen virker ikke (enda). La oss lukke og lagre dokumentet: trykk på escape (esc). Skriv så :w (enter). Nå er filen din lagret. Skriv så :q (enter) - nå lukket du dokumentet. (:wq gjør begge to i en kommando). Hvis du vil lukke uten å lagre, bruker du :q!. Fra før er du vant til at koden din blir fargekodet etter hvert som du skriver. Dette, og litt mer, skal vi fikse. Gå helt ut til hjemmemappen din. Skriv vim.vimrc. Denne filen styrer oppførselen til Vim. Skriv inn følgende: syntax enable colorscheme delek set mouse=a set number Så kan du lagre og lukke filen. Gå tilbake til C++-filen din, og åpne den (vim minkode.cpp). Nå skal du ha fine farger, linjenummer, og du kan bruke musen! Klipping og liming må også læres litt. Trykk først (esc), og merk en del av koden din - denne skal vi kopiere. Trykk så y (for yank ). Klikk på et nytt sted i koden, og trykk p (for paste ). Hvis du vil klippe, bruk x istedet for y. 3
C++ i Unix 4 TDT4102 NTNU Det kan hende at noe gikk litt galt når du klippet og limet. Da kan du trykke u (for undo ) for å angre. Har du angret for langt, kan du bruke Ctrl-r (for redo ). Har du kopiert fra et annet program (f.eks. nettleseren din), må du bruke Shift+Ins for å lime inn. Da må du først være i --INSERT-- modus (trykk i). (Ins- tasten ligger ved siden av Del.) Etter du har klippet og limt, må du trykke tasten i for å kunne skrive mer. Vim skiller mellom insert-modus (når du har trykket i) der du kan skrive ting, og vanlig modus, der du kan klippe, lime og utføre kommandoer som f.eks. lagring. Du vet at du er i insert-modus hvis det står --INSERT-- nederst til venstre. Vim er en utrolig fleksibel editor. Det er mye mer å lære, og et kjapt google-søk på Vim detdulurerpå vil nok gi deg svaret. 7 Kompilering Skriv ferdig filen minkode.cpp - legg in Hello World eller noe annet enkelt. Nå skal vi kompilere denne filen! Da er det kjekt å vite at kompilatoren heter g++. Å kompilere filen din er så enkelt som å skrive g++ minkode.cpp (enter). Prøv det! Pass på at du er i mappen der minkode.cpp er lagret. Hvis du ikke får noen beskjeder, gikk alt bra! Eventuelt får du beskjed om hva som er feil, og må fikse det. Hvis alt gikk bra, har det blitt opprettet en fil som heter a.out (sjekk med ls). Denne filen er programmet ditt! Du kan kjøre programmet ditt med./a.out (enter). Hvis du vil ha et bedre navn enn a.out kan du skrive g++ minkode.cpp -o mittprogram.out når du kompilerer. Du kan også bruke g++ -Wall minkode.cpp for å få flere feilmeldinger, noe som er lurt. Dersom du trenger mer effektiv kode, kan du optimalisere med g++ -O3 minkode.cpp, men det tar litt lengre tid å kompilere (merk at det er O som i bokstaven, ikke tallet 0). Du kan også kombinere disse alternativene hvis du vil. Da har du lært det du trenger for å jobbe med C++ på en Unix-server! Dersom dette var enkelt for deg, og du har lyst til å lære flere kule ting, kan du se på neste avsnitt (som er frivillig). Uansett bør du se på siste side, der det ligger en flott huskelapp! 8 Makefile (for de interesserte) De som har lyst til å lære mer, vil lære mye kult mens vi går igjennom det fantastiske verktøyet makefile. Makefile er nyttig når du har mange header- filer, biblioteker og.cpp-filer. Ved å lære om dette vil du samtidig lære mye mer om hvordan kompilering virker og de forskjellige stadiene i kompileringen. Når du kompilerte med g++ minkode.cpp skjedde det en hel masse! For å ha nytte av makefiles, må vi først ta en liten tur gjennom dette. 8.1 Kompilering: behind the scenes Først gikk preprosessoren gjennom filen din og så etter linjer som starter med #. Når den kom over f.eks. #include <iostream>, fant den frem biblioteket iostream og kopierte header-filen til iostream inn i koden din. 4
C++ i Unix 5 TDT4102 NTNU Så var det den egentlige kompilatoren sin tur. Denne tok filen den fikk fra preprosessoren, og gjorde den om til en objekt-fil, som nesten er et ferdig program. Men header-filen henviser ofte til en annen.cpp-fil. Da må også denne kompileres! Når det er snakk om biblioteker som iostream, er.cpp-filene allerede gjort om til.o-filer 5, men hvis du har din egen header-fil, må også de andre.cpp-filene dine kompileres. Til slutt gir kompilatoren fra seg en eller flere.o-filer. Disse filene gis videre til linkeren. Linkeren setter sammen.o-filene til den endelige filen, som er en.out-fil på Unix. 6 Da har du endelig fått filen din! 8.2 Make - en forbedring! Hvorfor skulle vi så bry oss om dette? Jo, når vi jobber med et stort prosjekt, med både biblioteker og selv-lagde header-filer, kan det fort ta veldig lang tid å kompilere. Du har vel knapt opplevd at kompilering tar tid, men hvis du laster ned kildekoden til Firefox og skal kompilere den, kan du gå og ta deg en kaffekopp eller tre imens. Når man skal endre på koden i Firefox (eller et annet stort program) blir det jo litt prøving og feiling, og hvis hver kompilering tar flere minutter, har vi et problem. En makefile holder oversikt med hvilke filer som avhenger av hva. Den tar også vare på.o-filene fra kompileringen, slik at når en liten del av programmet endres, må bare den lille delen kompileres til en ny.o-fil, før linkeren setter sammen det ferdige resultatet. Linkeren arbeider raskt, så dette sparer mye tid! La oss ta et eksempel: Vi har filen hovedfil.cpp med header hovedfil.h som inkluderer kvadrat.h og trekant.h, som igjen har kvadrat.cpp og trekant.cpp. I tillegg inkluderer kvadrat.cpp header-filen firkant.h som peker til firkant.cpp. Da er makefile som under (denne filen må hete makefile ). Når vi skal bruke denne filen, kjører vi bare kommandoen make fra mappen der filene våre ligger lagret. De siste to linjene gjør at vi kan skrive make clean for å fjerne alle.o-filer og resultatet av kompileringen fra mappen, nyttig f.eks. når en kompilering har feilet. all : program.out 2 program.out : hovedfil.o kvadrat.o trekant.o 4 g++ -Wall hovedfil.o kvadrat.o trekant.o -o program.out 6 hovedfil.o : hovedfil.cpp hovedfil.h kvadrat.h trekant.h g++ -Wall -c hovedfil.cpp 8 kvadrat.o : kvadrat.cpp kvadrat.h firkant.h 10 g++ -Wall -c kvadrat.cpp 12 trekant.o : trekant.cpp trekant.h g++ -Wall -c trekant.cpp 14 firkant.o : firkant.cpp firkant.h 16 g++ -Wall -c firkant.cpp 18 clean : 5 strengt tatt til.so-filer, der s står for shared, altså delte objekt-filer 6 den ferdige filen kan faktisk ha hva som helst som etternavn - Unix bryr seg ikke så veldig om filetternavn 5
C++ i Unix 6 TDT4102 NTNU \rm *.o *~ program.out Forklaring til eksempelet: Foran hver kolon står et target. Dette er filen som blir produsert av de følgende linjene. Etter kolon står de filene som target-filen er avhengig av. På neste linje kommer en kommando som lager target-filen. Det er viktig at det kommer en <TAB> foran hver slik linje. Når vi bruker g++ -c fil.cpp vil kompilatoren gi oss en.o-fil. Ikke bland dette med g++ fil.cpp -o fil.out, der -o gir navnet på output-filen. all gjør at vi kan kjøre makefilen med bare kommandoen make, istedet for make program.out. clean er et såkalt dummy-target, dvs. at ingen fil blir skapt. Kommandoen på linjen etter sletter alle.o-filer, og alle filer som slutter med, dette er midlertidige filer. Den sletter også output av kompileringen. Dette er praktisk når vi vil rydde opp, med kommandoen make clean, f.eks. etter en kompilering som ble avbrutt. Hva skjer nå dersom vi endrer filen trekant.cpp? Da vil make oppdage dette, og konkludere med at den må kjøre linje 12-13 i filen over på nytt igjen. Når den har gjort dette, er alle.o-filene klare, og make vil da kjøre linje 3-4 som lager det ferdige programmet. Vi slapp altså unna med å bare gjøre 1/4 av kompileringene! 8.3 Avansert make Du kan lage mye mer avanserte makefiles. Hvis du bruker makefiles mye, kan makroer være nyttige. Ved å skrive f.eks. OBJS = hovedfil.o kvadrat.o trekant.o kan du bruke det korte navnet $(OBJS) på linje 4 på forrige side. Merk at slike instrukser må stå først i makefile. Noen makroer er innebygde - $(CC) er alltid navnet på kompilatoren. En annen fin ting er å utnytte de forhåndsdefinerte reglene - make vet hva den skal gjøre i enkle situasjoner, den vet f.eks. at den må bruke g++ -c trekant.cpp for å lage trekant.o. Ved hjelp av dette og de to makroene vi har nevnt, kan vi skrive den samme makefilen slik: OBJS = hovedfil.o kvadrat.o trekant.o 2 CC = g++ all : program.out 4 program.out : $(OBJS) $(CC) $(OBJS) -o program.out 6 hovedfil.o : hovedfil.h kvadrat.h trekant.h kvadrat.o : kvadrat.h firkant.h 8 trekant.o : trekant.h firkant.o : firkant.h Var ikke det litt enklere? Nå som du har drøy peiling på makefiles, bør du prøve det på en øving! Du får mest utbytte av å gjøre det med en øving der du skal inkludere flere filer. 6
C++ i Unix 7 TDT4102 NTNU Huskelapp Helt til slutt har vi en huskelapp med kommandoer som du trenger i din daglige Unix-bruk: Navigasjon Åpne mappe fol: cd fol Gå ut av mappen: cd.. Se innholdet i mappe: ls Kopiere noe: cp noe noenytt Opprette mappe fol: mkdir fol Slette mappe fol: rm -r fol Sti til mappen du er i: pwd Tekstredigering med Vim (uten hjemmeområde) Åpne (nytt) dokument dok: vim dok Gå inn i INSERT-modus: i Gå ut av INSERT-modus: Esc Lagre: :w (husk Esc først) Lukk: :q Lukk uten lagre: :q! Kopier: (Esc) (marker tekst) y Klipp ut: x istedet for y Lim inn: (Esc) (klikk) p Kompilering Kompiler filen kode.cpp: Gi output navnet program.out: Skriv ut advarsler: Optimaliser kode: Har du husket å navigere til riktig Har du husket å lagre? g++ kode.cpp g++ kode.cpp -o program.out g++ -Wall kode.cpp g++ -O2 kode.cpp mappe? 7