Ero sivun ”CMake syvemmin” versioiden välillä

Siirry navigaatioon Siirry hakuun
10 454 merkkiä lisätty ,  10. joulukuuta 2024
ei muokkausyhteenvetoa
Ei muokkausyhteenvetoa
Ei muokkausyhteenvetoa
Rivi 200: Rivi 200:


Vielä emme siis ole päässeet nauttimaan cmake:n erityisen hienoista ominaisuuksista, mutta ensimmäisen C/C++-ohjelman onnistuimme kuitenkin kääntää ajettavaksi ohjelmaksi.
Vielä emme siis ole päässeet nauttimaan cmake:n erityisen hienoista ominaisuuksista, mutta ensimmäisen C/C++-ohjelman onnistuimme kuitenkin kääntää ajettavaksi ohjelmaksi.
== Cmake-ohjelman mallien käyttäminen ==
== Cmake-ohjelman mallien käyttäminen ==
C++/C-ohjelmalle mallin luominen cmake:n ja CMakeLists.txt:n avulla. Ensimmäisessä esimerkissämme tulostimme message-käskyllä projektin tiedot tulostusjonoon. Nyt lisäämme kyseiset tiedot ohjelmamme lähdekoodeihin, jotka sitten tulostamme ajettavassa ohjelmassa.
Luomme projektimme juureen cmakemallit-kansion, johon kirjoitamme cmake-kielellä pohjan käännettäävää ohjelmaa varten. Annamme tiedostonnimeksi asetukset.cmake.
Luo projektikansiomme juureen cmake-kansio, johon luo config.h.cmake-tiedosto. Siihen kirjoita seuraava sisältö:
<syntaxhighlight lang=CMake line >
#ifndef CONFIG_H
#define CONFIG_H
#define PROJECT "@PROJECT_NAME@"
#define PROJECT_VERSION "@PROJECT_VERSION@"
#define PROJECT_VERSION_MAJOR "@PROJECT_VERSION_MAJOR@"
#define PROJECT_VERSION_MINOR "@PROJECT_VERSION_MINOR@"
#define PROJECT_VERSION_PATCH "@PROJECT_VERSION_PATCH@"
#define PROJECT_VERSION_TWEAK "@PROJECT_VERSION_TWEAK@"
#define PROJECT_HOMEPAGE_URL "@PROJECT_HOMEPAGE_URL@"
#define PROJECT_DESCRIPTION "@PROJECT_DESCRIPTION@"
#endif
</syntaxhighlight>
Malli on siis lähes samanlainen kuin puhdaskin C-otsaketiedosto. ”@...@”-välissä määritellyn cmake-muuttujan cmake muuttaa saman muuttujan arvoksi ennen C-kielisen ohjelman kääntämistä. Nämä ovat siis samat arvot kuin CMakeLists.txt-tiedoston message-käskyllä annetuissa muuttujissa.
Tosin CMakeLists.txt-tiedostoon pitää lisätä käsky, jotta cmake osaa kirjoittaa header-tiedoston oikealla nimellä oikeaan paikkaan. Käsky, joka pitää lisätä on configure_file, ja tarkemmin:
<syntaxhighlight lang=Cmake line start=21>
configure_file(${CMAKE_SOURCE_DIR}/cmake/config.h.cmake ${CMAKE_SOURCE_DIR}/src/config.h)
</syntaxhighlight>
se pidän loogisena, että sen paikka on ennen add_executable-käskyä, mutta se saattaa toimia myös sen jälkeen. Tämän muutoksen jälkeen CMakeLists.txt-tiedosto on kokonaisuudessaan seuraavan lainen …
<syntaxhighlight lang=cmake line >
cmake_minimum_required(VERSION 3.21)
project(
    "eka-projekti"
    VERSION 0.1.0.2
    DESCRIPTION "Ensimmainen cmake-projektini"
    HOMEPAGE_URL "https://linux.fi"
    LANGUAGES "C" "CXX"
)
message("${PROJECT_NAME} on ensimmäinen projektimme, ja tässä on sen tiedot:")
message("Projektin versio on ${PROJECT_VERSION}")
message("Se koostuu neljästä osasta:")
message(${PROJECT_VERSION_MAJOR})
message(${PROJECT_VERSION_MINOR})
message(${PROJECT_VERSION_PATCH})
message(${PROJECT_VERSION_TWEAK})
message("Projektimme kuvaus on:${PROJECT_DESCRIPTION}")
message("Kotisivuksi olemme määritelleet tutun ${PROJECT_HOMEPAGE_URL}.")
configure_file(${CMAKE_SOURCE_DIR}/cmake/config.h.cmake ${CMAKE_SOURCE_DIR}/src/config.h)
add_executable("hello" "src/hello.cpp")
</syntaxhighlight>
Elikkä configure_file-käskyllä lisätään config.h.cmake-tiedoston ohjeiden mukaisesti projektin tiedot C-ystävälliseen muotoon #define-käskyjen muodossa. ${CMAKE_SOURCE_DIR} on lähdekoodin polku, /cmake/config.h.cmake-on lähdekoodipolussa olevan tiedoston nimi. /src/config.h on lähdekoodin (koko)polku, jonne asetustiedosto (config.h) lisätään.
Tämän jälkeen voit testata onnistuuko kääntäminen.
<syntaxhighlight lang=bash line >
d ..
mkdir build
cd build
rm -r *
cmake ..
make all
</syntaxhighlight>
Kääntämisen jälkeen ./hello-ohjelman pitäisi toimia samalla tavalla kuin ennen, mutta jos huomaat, niin projektin src-hakemistoon ilmestyi uusi config.h-tiedosto. Jotta saisimme konkreettista hyötyä mallitiedostosta, niin sen generoima otsaketiedosto kannattaa lisätä hello.cpp ohjelmaan #include-käskyllä: #include ”config.h”. Tämän jälkeen hello.cpp-tiedostomme on siis seuraavan mukainen…
<syntaxhighlight lang=C++ line >
#include <iostream>
#include "config.h"
int main(int args,char **argv) {
    std::cout << "ohjelman ajotiedoston nimi hakemistopolkuineen on " << argv[0] << "\n";
    std::cout << PROJECT;
    std::cout << "\n" << PROJECT_VERSION ;
    std::cout << "\n" << PROJECT_VERSION_MAJOR ;
    std::cout << "\n" << PROJECT_VERSION_MINOR;
    std::cout << "\n" << PROJECT_VERSION_PATCH;
    std::cout << "\n" << PROJECT_VERSION_TWEAK;
    std::cout << "\n" << PROJECT_HOMEPAGE_URL;
    std::cout << "\n" << PROJECT_DESCRIPTION;
    std::cout << "\n";
    return 0
}
</syntaxhighlight>
Tiedosto puu (ilman build-kansiota) on seuraavannäköinen…
<syntaxhighlight lang=bash >
$ tree cmakeprojekti
cmakeprojekti
├── cmake
│   └── config.h.cmake
├── CMakeLists.txt
└── src
    ├── config.h
    └── hello.cpp
3 directories, 4 files
</syntaxhighlight>
Tämän jälkeen voitkin koeajaa ohjelman:
<syntaxhighlight lang=bash line >
cd ..
rm -r build
mkdir build
cd build
cmake ..
make all
./hello
</syntaxhighlight>
./hello:n pitäisi tulostaa seuraavaa…
<syntaxhighlight lang=bash>
eka-projekti
0
1
0
2
https://linux.fi
Ensimmäinen cmake-projektini
</syntaxhighlight>
== Oman kirjaston lisääminen (.h) ==
Cmake:lla voi määritellä ja kääntää omia kirjastoja joko lähdeohjelmien kanssa tai pelkän käännöksen ja otsaketiedostojen (.h) avulla. Lisäämme itse tekemämme kirjaston, joka palauttaa liukulukujen välisen kertolaskun tuloksen palautteena.
Siispä lisäämme lib-hakemiston kirjaston lähdekoodia varten ja include-hakemiston otsaketiedostoja varten. Päätteellä se tapahtuu seuraavalla tavalla, mikäli olet päätteellä projektin build-hakemistossa.
<syntaxhighlight lang=bash line>
mkdir ../lib;touch ../lib/mylib.cpp
mkdir ../include;touch ../include/mylib.h
</syntaxhighlight>
Tämän jälkeen projektin hakemistopuu näyttää tältä:
<syntaxhighlight lang=bash>
cmakeprojekti
├── build
├── cmake
│   └── config.h.cmake
├── CMakeLists.txt
├── include
│   └── mylib.h
├── lib
│   └── mylib.cpp
└── src
    ├── config.h
    └── hello.cpp
</syntaxhighlight>
Kirjoita mylib.h-tiedostoon seuraavanlainen otsaketiedosto:
<syntaxhighlight lang=C line >
#ifndef MYLIB_H
#define MYLIB_H
double multiply(double v1,double v2);
#endif
</syntaxhighlight>
Vastaavasti kirjoita mylib.cpp-tiedostoon seuraavanlainen ohjelmasisältö:
<syntaxhighlight lang=C line >
#include "mylib.h"
double multiply(double v1,double v2) {
    // multiply-funktion toteutus.
    // Palauttaa v1:n ja v2:n välisen kertolaskun tuloksen.
    return v1*v2;
}
</syntaxhighlight>
Jotta voimme testata ohjelman toimintaa, niin meidän pitää tehdä muutoksia (hello.cpp) pääohjelmaamme. Lisäämme #include <mylib.h> ja rivit ohjelman testaamista varten.
Muutosten jälkeen hello.cpp-näyttää tällaiselta:
<syntaxhighlight lang=C++ line >
#include <iostream>
#include "config.h"
#include <mylib.h>
int main(int args,char **argv) {
    std::cout << "ohjelman ajotiedoston nimi hakemistopolkuineen on " << argv[0] << "\n";
    std::cout << PROJECT;
    std::cout << "\n" << PROJECT_VERSION ;
    std::cout << "\n" << PROJECT_VERSION_MAJOR ;
    std::cout << "\n" << PROJECT_VERSION_MINOR;
    std::cout << "\n" << PROJECT_VERSION_PATCH;
    std::cout << "\n" << PROJECT_VERSION_TWEAK;
    std::cout << "\n" << PROJECT_HOMEPAGE_URL;
    std::cout << "\n" << PROJECT_DESCRIPTION;
    std::cout << "\n" << multiply(3,5);
    if(args>2) {
      std::cout << "\n" << multiply(atof(argv[1]) ,atof(argv[2]));
    }
    std::cout << "\n";
}
</syntaxhighlight>
Huomioi uudet rivit: 3,15-18 !
Edelliseen verrattuna ohjelmaan on tullut uusi #include-rivi #include-rivien viimeiseksi, jossa otetaan käyttöön oma tekemä mylib-kirjasto. Sen lisäksi mylib-kirjastossa olevaa multiply-funktiota testataan vakioilla, ja jos ohjelmalle syötetään parametreja kaksi tai enemmän, niin ohjelma yrittää muuttaa niistä kahta ensimmäista numeroksi ja kertoa ne keskenään. Muutokset ovat korostettu keltaisella taustavärillä.
Tämän osion lopuksi teemme tarvittavat muutokset CMakeLists.txt-tiedostoon, tiedostoon lisätään seuraavat rivit configure_file-käskyn jälkeen:
<syntaxhighlight lang=Cmake line start=22 >
add_library(mylib lib/mylib.cpp)
target_include_directories(mylib PUBLIC include)
</syntaxhighlight>
add_library-käskyllä lisätään projektiin mylib.cpp-kirjasto käännettäväksi, ja target_include_directories-käskyllä laitetaan include-hakemisto näkyväksi C/C++-kääntäjälle, josta kääntäjä osaa hakea (.h) header-tiedostot.
CMakeLists.txt-tiedoston loppuun lisätään vielä rivi, jolla kirjasto linkitetään projektin hello.cpp-ohjelmaan.
<syntaxhighlight lang=CMake line Start=28>
target_link_libraries(hello mylib )
</syntaxhighlight>
Tämän jälkeen CMakeLists.txt-tiedoston pitäisi näyttää tältä:
<syntaxhighlight lang=CMake line >
cmake_minimum_required(VERSION 3.21)
project(
    "eka-projekti"
    VERSION 0.1.0.2
    DESCRIPTION "Ensimmainen cmake-projektini"
    HOMEPAGE_URL "https://linux.fi"
    LANGUAGES "C" "CXX"
)
message("${PROJECT_NAME} on ensimmäinen projektimme, ja tässä on sen tiedot:")
message("Projektin versio on ${PROJECT_VERSION}")
message("Se koostuu neljästä osasta:")
message(${PROJECT_VERSION_MAJOR})
message(${PROJECT_VERSION_MINOR})
message(${PROJECT_VERSION_PATCH})
message(${PROJECT_VERSION_TWEAK})
message("Projektimme kuvaus on:${PROJECT_DESCRIPTION}")
message("Kotisivuksi olemme määritelleet tutun ${PROJECT_HOMEPAGE_URL}.")
configure_file(${CMAKE_SOURCE_DIR}/cmake/config.h.cmake ${CMAKE_SOURCE_DIR}/src/config.h)
add_library(mylib lib/mylib.cpp)
target_include_directories(mylib PUBLIC include)
add_executable("hello" "src/hello.cpp")
target_link_libraries(hello mylib )
</syntaxhighlight>
== Oman hello-ohjelman uusien ominaisuuksien kokeilu ==
Ensin käännetään ohjelma:
Mene päätteellä projektin juureen, ja suorita alla olevat käskyt. (Sinun tulee tietää, mitä käskyt tekevät, koska väärässä kansiossa annettuna nämä käskyt saattavat tehdä arvaamatonta tuhoa):
<syntaxhighlight lang=bash line >
mkdir build
cd build
rm -r *
cmake ..
make all
</syntaxhighlight>
Suoritusten jälkeen sinulla pitäisi olla valmiiksi käännettynä hello-ohjelma, jota voit testata esimerkiksi seuraavalla tavalla:
<syntaxhighlight lang=bash >
./hello
./hello 5 9
</syntaxhighlight>
Ohjelma tulostaneen seuraavan kaltaista:
<syntaxhighlight lang=bash >
ohjelman ajotiedoston nimi hakemistopolkuineen on ./hello
eka-projekti
0.1.0.2
0
1
0
2
https://linux.fi
Ensimmainen cmake-projektini
15
ohjelman ajotiedoston nimi hakemistopolkuineen on ./hello
eka-projekti
0.1.0.2
0
1
0
2
https://linux.fi
Ensimmainen cmake-projektini
15
45
</syntaxhighlight>
Tällä hetkellä puun pitäisi näyttää tältä:
<syntaxhighlight lang=bash >
cmakeprojekti
├── cmake
│   └── config.h.cmake
├── CMakeLists.txt
├── include
│   └── mylib.h
├── lib
│   └── mylib.cpp
└── src
    ├── config.h
    └── hello.cpp
</syntaxhighlight>
==Käyttö==
==Käyttö==
Yleensä projekti käännetään ajamalla sen lähdekoodihakemistossa komento
cmake .
Käännösprosessia voi ohjata määrittelemällä -D-valitsimella käännöstä ohjaavia muuttujia:
cmake -D<muuttuja>=arvo
Esimerkiksi [[gcc|g++]]:n käännösvalitsimiin voi vaikuttaa muuttujalla <tt>CMAKE_CXX_FLAGS</tt>:
cmake -DCMAKE_CXX_FLAGS="-g -O2" .
Tämän jälkeen CMake yleensä luo [[Makefile|Makefilen]], jonka avulla ohjelma voidaan asentaa tyypillisesti komennolla
[[make]] all install


==Katso myös==
==Katso myös==
54

muokkausta

Navigointivalikko