C++-ohjelman lähdekoodi käännetään kääntäjällä ja linkitetään suoritettavaksi ohjelmaksi. Vaihtoehtoisia kääntäjiä ovat esimerkiksi:
gcc ja
C++-ohjelmille komentoa g++. Windowsissa GCC:tä voi käyttää valmiin
MinGW-työkalupaketin kautta. MinGW ei siis ole erillinen C++-kääntäjä.clang++. Clangia käytetään esimerkiksi
macOS:ssä, Linuxissa ja Windowsissa.cl.
GCC on kokoelman nimi, gcc ja g++ ovat komentoja.
Teknisesti nämä komennot käynnistävät ohjausohjelmat, jotka huolehtivat tarvittavien
työvaiheiden suorittamisesta. Valitsin -c jättää linkityksen tekemättä.
Ilman sitä samalla komennolla voidaan myös kääntää ja linkittää ohjelma.
Myös gcc tunnistaa .cpp-tiedoston C++-lähdekoodiksi,
mutta g++ lisää linkitykseen automaattisesti C++-kirjaston.
Siksi C++-esimerkeissä käytämme komentoa g++.
MinGW ja MinGW-w64 liittyvät Windows-ohjelmien rakentamiseen.
MinGW-w64 on alkuperäisestä MinGW-projektista kehittynyt projekti, joka tarjoaa
Windowsin otsikkotiedostoja, kirjastoja ja työkaluja. Se ei itsessään ole C++-kääntäjä.
Valmis MinGW-työkalupaketti yhdistää nämä esimerkiksi GCC-kääntäjiin ja linkittäjään.
Tällaisessa paketissa g++ käynnistää mukana toimitetun GCC:n C++-kääntäjän.
Arkikielen ”MinGW-kääntäjä” tarkoittaa usein juuri tällaisen paketin mukana tulevaa kääntäjää. Kaikki MinGW-w64:ään perustuvat työkalupaketit eivät kuitenkaan käytä GCC:tä; kääntäjänä voi olla myös Clang.
Lähteet: GCC:n määritelmä, gcc- ja g++-komentojen erot ja MinGW-w64.
Kääntämis- ja linkityskomennot voi suorittaa käsin, mutta Make ja Ninja helpottavat prosessia. Ne seuraavat tiedostojen riippuvuuksia ja suorittavat tarvittavat komennot, kun lähdekoodi muuttuu. Varsinaisen käännöstyön tekee edelleen valittu C++-kääntäjä.
Makefile-tiedostosta.
Makefilen voi kirjoittaa itse tai tuottaa generaattorilla.build.ninja-tiedostosta.
Tämä tiedosto tuotetaan tavallisesti generaattorilla. Ninja on suunniteltu erityisesti
nopeaan, toistuvaan kokoamiseen.Ninja on nykyään laajasti käytetty vaihtoehto Makelle: sitä käytetään esimerkiksi Chromen ja LLVM:n kokoamiseen. Myös Qt suosittelee Ninjaa Qt:n oman lähdekoodin kokoamiseen. Lisätietoa: Ninjan käyttökohteet ja Qt:n kokoamistyökalut.
Kokoamisohjeita ei tarvitse kirjoittaa kokonaan käsin. CMake ja qmake lukevat projektin kuvauksen ja generoivat varsinaisen kokoamistyökalun tarvitsemat tiedostot.
| Generaattori | Projektin kuvaus | Tuotetut kokoamisohjeet |
|---|---|---|
| CMake | CMakeLists.txt | Esimerkiksi Makefile tai build.ninja, valitun generaattorin mukaan. |
| qmake | .pro-tiedosto | Tyypillisesti Makefile. |
CMake voi siis tuottaa ohjeet sekä Makelle että Ninjalle. qmakea käytetään Qt-projekteissa tyypillisesti Makefilen generointiin; tämän sivun Ninja-esimerkissä käytämme CMakea.
CMake on Qt:n suosittelema valinta Qt 6 -projekteihin. Qt 6:n oma kokoamisjärjestelmä perustuu CMakeen. qmake on edelleen tuettu Qt-sovellusten kokoamiseen, joten sitä voi kohdata etenkin vanhemmissa projekteissa. Lisätietoa: Qt 6 -kirjan kokoamisohjeet ja Qt 6:n kokoamisjärjestelmän muutokset.
CMakeLists.txt → CMake → Makefile → Make → kääntäjä ja linkittäjä → ohjelma
→ build.ninja → Ninja → kääntäjä ja linkittäjä → ohjelma
projekti.pro → qmake → Makefile → Make → kääntäjä ja linkittäjä → ohjelma
Seuraavaksi kokoamme saman pienen ohjelman ensin käsin, sitten Makella ja lopuksi CMaken avulla käyttäen Ninjaa tai Makea.
Käytämme kaikissa tämän sivun esimerkeissä samaa pientä C++-ohjelmaa. Tallenna seuraavat kolme tiedostoa samaan hakemistoon.
main.cpp kutsuu utils.cpp-tiedostossa määriteltyä funktiota.
#include <iostream>
#include "utils.h"
int main() {
std::cout << "Tulos: " << kerroKahdella(5) << std::endl;
return 0;
}
utils.cpp sisältää funktion toteutuksen.
#include "utils.h"
int kerroKahdella(int luku) {
return luku * 2;
}
utils.h esittelee funktion, jotta sitä voidaan kutsua main.cpp-tiedostosta.
#ifndef UTILS_H
#define UTILS_H
int kerroKahdella(int luku);
#endif
Kokoaminen koostuu tässä kahdesta vaiheesta: lähdetiedostojen kääntämisestä objektitiedostoiksi
ja objektitiedostojen linkittämisestä ohjelmaksi.
Käytämme g++-komentoa kahdesti: ensin lähdetiedostojen kääntämiseen
ja sitten objektitiedostojen linkittämiseen.
Suorita seuraavat komennot lähdetiedostojen hakemistossa Linuxissa tai WSL:ssä, jossa GCC on asennettuna.
1. Käännä objektitiedostot:
g++ -c main.cpp utils.cpp
Valitsin -c tekee vain käännösvaiheen. Tuloksena syntyvät main.o ja
utils.o. Otsikkotiedosto utils.h luetaan mukaan
#include-direktiiveillä; sitä ei käännetä erilliseksi objektitiedostoksi.
2. Linkitä objektitiedostot:
g++ main.o utils.o -o myapp
Komento käynnistää linkityksen, jossa objektitiedostot ja tarvittavat kirjastot yhdistetään.
Valitsin -o myapp antaa syntyvälle ohjelmalle nimen myapp.
3. Suorita ohjelma:
./myapp
Ohjelma tulostaa:
Tulos: 10
Pienen ohjelman voi myös kääntää ja linkittää yhdellä komennolla:
g++ main.cpp utils.cpp -o myapp
Erillisten objektitiedostojen avulla jokaista lähdetiedostoa ei tarvitse kääntää uudelleen joka muutoksen jälkeen. Seuraavaksi automatisoimme tarvittavien käännösten ja linkityksen suorittamisen.
Make automatisoi kokoamisen Makefileen kirjoitettujen sääntöjen perusteella. Seuraavat komentoriviesimerkit on tarkoitettu Linuxiin tai WSL:ään, jossa GCC ja Make ovat asennettuina.
Makefile on tekstitiedosto, joka kertoo make-työkalulle,
miten projekti pitää koota. Siinä määritellään riippuvuudet, käännöskomennot ja säännöt,
jotka kertovat mitä pitää tehdä, kun tiedosto muuttuu.
target: dependencies
command
Jokainen sääntö koostuu kohteesta (target), sen riippuvuuksista
(dependencies) ja komennosta, joka suoritetaan.
Tärkeää: komennon edessä täytyy olla TAB-merkki.
Tallenna seuraava Makefile lähdetiedostojen hakemistoon. Se automatisoi edellä käsin suoritetut vaiheet.
CXX = g++
#Windowsissa:
#CXX = C:\Qt\Tools\mingw1310_64\bin\g++
CXXFLAGS = -Wall -std=c++17
TARGET = myapp
OBJS = main.o utils.o
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)
$(OBJS): utils.h
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f *.o $(TARGET)
make – kokoaa ohjelman oletuskohteen mukaan (yleensä "all")make clean – poistaa väliaikaiset tiedostot (esim. .o-tiedostot ja lopullisen ohjelman)
CMake on kokoamisjärjestelmien generaattori. Kuvaat projektin lähdetiedostot, kohteet ja asetukset
CMakeLists.txt-tiedostossa, ja CMake tuottaa valitun kokoamistyökalun tarvitsemat tiedostot.
Valinta tehdään generaattorilla, joka annetaan -G-valitsimella.
Tallenna seuraava tiedosto samaan hakemistoon kuin main.cpp, utils.cpp ja utils.h:
cmake_minimum_required(VERSION 3.13)
project(myapp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(myapp main.cpp utils.cpp)
# Kääntäjälle sopivat varoitusasetukset
if(MSVC)
target_compile_options(myapp PRIVATE /W4)
else()
target_compile_options(myapp PRIVATE -Wall)
endif()
Molemmat alla olevat vaihtoehdot käyttävät tätä samaa tiedostoa. Suorita komennot projektin juurihakemistossa. Tarvitset CMake 3.13:n tai uudemman, C++-kääntäjän sekä valitsemasi kokoamistyökalun.
Ubuntussa, Debianissa ja muissa apt-pohjaisissa Linux-jakeluissa Ninjan voi asentaa komennolla:
sudo apt install ninja-build
Ninja on nopeuteen keskittyvä kokoamistyökalu. Sen build.ninja-tiedosto
tuotetaan tavallisesti esimerkiksi CMakella, joten sitä ei tarvitse kirjoittaa käsin.
Varmista, että Ninja ja C++-kääntäjä löytyvät komentorivin ympäristöstä.
Windowsissa MSVC-kääntäjää käytettäessä komennot suoritetaan Visual Studion kehittäjäkomentokehotteessa.
cmake -S . -B build-ninja -G Ninja
cmake --build build-ninja
Ensimmäinen komento generoi build.ninja-tiedoston build-ninja-hakemistoon.
Toinen käynnistää Ninjan. Käytä Makelle ja Ninjalle erillisiä kokoamishakemistoja:
olemassa olevan kokoamishakemiston generaattoria ei voi vaihtaa suoraan.
Voit käynnistää Ninjan myös suoraan. Tämä vastaa edellisen esimerkin toista komentoa:
ninja -C build-ninja
Linuxissa tai WSL:ssä ohjelman voi suorittaa komennolla ./build-ninja/myapp.
Windowsin PowerShellissä vastaava komento on .\build-ninja\myapp.exe.
Ohjelma tulostaa Tulos: 10.
Kun muutat lähdekoodia, suorita kokoamiskomento uudelleen. Ninja kokoaa riippuvuuksien perusteella tarvittavat osat. Kokoamisen tulokset voi siivota komennolla:
cmake --build build-ninja --target clean
cmake --build käyttää kyseiseen kokoamishakemistoon valittua työkalua.
Siksi sitä voi käyttää sekä Make- että Ninja-projekteissa.
Lisätietoa: Ninjan dokumentaatio
ja CMaken Ninja-generaattori.
Sama CMakeLists.txt voi tuottaa myös Makefilen. Linuxissa tai WSL:ssä valitaan Unix Makefiles -generaattori:
cmake -S . -B build-make -G "Unix Makefiles"
cmake --build build-make
Ensimmäinen komento lukee nykyisen hakemiston (-S .) projektin ja generoi Makefilen
build-make-hakemistoon (-B build-make).
Toinen komento käynnistää Maken, joka kokoaa ohjelman.
Windowsin MinGW-ympäristössä vastaava generaattori on MinGW Makefiles.
Sen käyttö edellyttää, että MinGW:n GCC-kääntäjä ja mingw32-make löytyvät komentorivin ympäristöstä.
| Ominaisuus | Make | Ninja |
|---|---|---|
| Kokoamisohjeet | Makefile voidaan kirjoittaa käsin tai generoida. | build.ninja generoidaan tavallisesti esimerkiksi CMakella. |
| Muuttuneiden osien kokoaminen | Kokoaa tarvittavat osat määriteltyjen riippuvuuksien perusteella. | Kokoaa tarvittavat osat määriteltyjen riippuvuuksien perusteella. |
| Rinnakkainen kokoaminen | GNU Makessa esimerkiksi make -j4. | Käyttää rinnakkaisuutta oletuksena. |
| Tyypillinen käyttö | Käsin kirjoitetut Makefilet ja Makea käyttävät olemassa olevat projektit. | Generoidut kokoamisohjeet ja nopea toistuva kokoaminen. |
Make sopii hyvin kokoamisen sääntöjen opiskeluun ja projekteihin, joissa Makefile on jo käytössä. CMake-projektissa Ninja on luonteva vaihtoehto, kun haluat automatisoidun ja nopean kokoamisen. Tässä pienessä esimerkissä nopeusero tuskin näkyy; Ninjan hyöty korostuu suuremmissa projekteissa. Ninjan ja Maken vertailu.
Näillä videoilla käyn läpi WSL-ympäristön käyttöönottoa sekä Make- ja CMake-esimerkkejä. Ensimmäisellä videolla asennan Windowsiin Ubuntun käyttäen WSL-systeemiä: