Prezentare generală
predare: 10 Min
exerciții: 15 minîntrebări
cum funcționează obiectivele?
obiective
știți cum să configurați ținte
înțelegeți proprietățile de legătură și interfață
Faceți ținte de interfață
acum știți cum să compilați un singur fișier folosind trei linii de cmake. Dar ce se întâmplă dacă avețimai mult de un fișier cu dependențe? Trebuie să puteți spune CMake despre structura dvs. proiect și vă va ajuta să îl construiți. Pentru a face acest lucru, veți avea nevoie de ținte.
ați văzut deja o țintă:
add_executable(myexample simple.cpp)
aceasta creează o țintă „executabilă” cu numelemyexample
. Numele țintă trebuie să fie unic (și existăeste o modalitate de a seta numele executabil la altceva decât numele țintă, dacă doriți cu adevărat).
țintele seamănă mult cu „obiectele” în alte limbi; ei au proprietăți (variabile membre) carețineți informații. ProprietateaSOURCES
, de exemplu, va aveasimple.cpp
în ea.
un alt tip de țintă este o bibliotecă:
add_library(mylibrary simplelib.cpp)
puteți adăuga cuvintele cheie STATIC
SHARED
sau MODULE
dacă știți ce fel de bibliotecă doriți să faceți; implicit este un fel de bibliotecă „auto” care poate fi selectată de utilizator cu BUILD_SHARED_LIBS
.
puteți face biblioteci non-construite prea. Mai multe despre asta mai târziu, odată ce vom vedea ce putem face cu țintele.
legarea
odată ce aveți mai multe obiective, puteți descrie relația dintre ele cutarget_link_libraries
și un cuvânt cheie; unul dintrePUBLIC
PRIVATE
șiINTERFACE
. Nu uitați acest cuvânt cheie atunci când creați o bibliotecă! CMake intră într-un mod vechi de compatibilitate pentru această țintă careîn general rupe lucrurile.
întrebare
aveți o bibliotecă,
my_lib
, făcută dinmy_lib.hpp
șimy_lib.cpp
. Este nevoie de cel puțin C++14pentru a compila. Dacă apoi adăugațimy_exe
și are nevoie demy_lib
, ar trebui ca forțamy_exe
să compilezecu C++14 sau mai bine?răspuns
aceasta depinde de antet. Dacă antetul conține C++14, Aceasta este o cerință publică – ambelebiblioteca și utilizatorii săi au nevoie de ea. Cu toate acestea, dacă antetul este valabil în toate versiunile C++ șinumai implementările din
my_lib.cpp
necesită C++14, atunci acesta este unPRIVATE
cerință
- utilizatorii nu trebuie să fie forțați în modul C++14.
poate aveți nevoie de utilizatori au C++14, dar biblioteca poate compila cu orice versiune de c++.Aceasta ar fi o cerință
INTERFACE
.
Figura 1: Exemplu de PUBLIC, privat și interfață. myprogram
va construi cele trei biblioteci itsees prin mylibrary
; biblioteca privată nu o va afecta.
există două colecții de proprietăți pe fiecare țintă care pot fi umplute cu valori; proprietățile”private” controlează ce se întâmplă atunci când construiți acea țintă, iar proprietățile „interfață” spun țintelor legate de aceasta ce trebuie făcut atunci când construiți. PUBLIC
cuvinte cheie umple ambele propertyfields în același timp.
Exemplul 1: Includeți directoarele
când executați , proprietateaINCLUDE_DIRECTORIES
aTargetA
aremydir
anexată. Dacă utilizați cuvântul cheie INTERFACE
în schimb, atunci INTERFACE_INCLUDE_DIRECTORIES
este adăugat la, în schimb. Dacă utilizați PUBLIC
, atunci ambele proprietăți sunt atașate în același timp.
Exemplul 2: C++ standard
există o proprietate c++ standard – CXX_STANDARD
. Puteți seta această proprietate, și ca manyproperties în CMake,ea devine valoarea implicită de la un CMAKE_CXX_STANDARD
variabilă în cazul în care este setat, dar nu există nici o versiune de interfață – nu puteți forța un CXX_STANDARD
printr-o țintă. Ce ai face dacă ai avea o țintă de interfață C++11 și o țintă de interfață C++14 și legată de ambele?apropo, există o modalitate de a gestiona acest lucru – puteți specifica caracteristicile minime de compilare de care aveți nevoiepentru a compila o țintă; cxx_std_11
și meta-caracteristici similare sunt perfecte pentru acest lucru – targetwill compila cu cel puțin cel mai înalt nivel specificat, cu excepția cazului înCXX_STANDARD
este setat (și that ‘ o eroare frumos, clar dacă setațiCXX_STANDARD
prea mic). target_compile_features
poate umpleCOMPILE_FEATURES
șiINTERFACE_COMPILE_FEATURES
, la fel ca directoarele din exemplul 1.
încercați
obțineți acest depozit și mergeți la exemplu. Încercați să scrieți un CMakeLists care va construi corect.
git clone https://github.com/hsf-training/hsf-training-cmake-webpage.gitcd hsf-training-cmake-webpage/code/01-simple
fișierele de aici sunt:
- simple_lib.cpp: trebuie compilat cu
MYLIB_PRIVATE
șiMYLIB_PUBLIC
definit. - simple_example.cpp: trebuie compilat cu
MYLIB_PUBLIC
definit, dar nuMYLIB_PRIVATE
utilizați pentru a seta definițiile pesimple_lib
.
lucruri pe care le puteți seta pe obiective
-
target_link_libraries
: alte obiective; poate trece, de asemenea, nume de bibliotecă direct -
target_include_directories
: Include directories -
target_compile_features
: The compiler features you need activated, likecxx_std_11
-
target_compile_definitions
: Definitions -
target_compile_options
: More general compile flags -
target_link_directories
: Don’t use, give full paths instead (CMake 3.13+) -
target_link_options
: General link flags (CMake 3.13+) -
target_sources
: Add source files
See more commands here.
alte tipuri de ținte
s-ar putea să fiți cu adevărat ieșiți de ținte și deja planificați cum puteți descrie programele dvs. în termeni de ținte. E grozav! Cu toate acestea, veți întâlni rapid încă două situațiiîn care limba țintă este utilă, dar aveți nevoie de o flexibilitate suplimentară față de ceea ce am acoperit.
În primul rând, este posibil să aveți o bibliotecă care conceptual ar trebui să fie o țintă, dar nu are de fapt componente anybuilt – o bibliotecă „numai antet”. Acestea se numesc biblioteci de interfață în CMake și youwould scrie:
add_library(some_header_only_lib INTERFACE)
observați că nu a fost nevoie să adăugați fișiere sursă. Acum Puteți setaINTERFACE
proprietăți numai pe aceasta(deoarece nu există o componentă construită).
a doua situație este dacă aveți o bibliotecă pre-construită pe care doriți să o utilizați. Aceasta se numește biblioteca animported în CMake și folosește cuvântul cheie IMPORTED
. Bibliotecile importate pot fi, de asemenea,INTERFACE
biblioteci, pot fi construite și modificate folosind aceeași sintaxă ca și alte biblioteci(începând cu CMake 3.11), și pot avea ::
în numele lor. (ALIAS
bibliotecile, care pur și simplu denumesc o altă bibliotecă, au, de asemenea, permisiunea de a avea::
). De cele mai multe ori veți fi importațibibliotecile din alte locuri și nu vă vor face propriile.
interfață IMPORETED
Ce zici de
INTERFACE IMPORTED
?Diferența se reduce la două lucruri:
IMPORTED
țintele nu sunt exportabile. Dacă vă salvați țintele, nu le puteți salva pe cele importate-acestea trebuie recreate (sau găsite din nou).IMPORTED
antet includ directoare vor fi întotdeauna marcate caSYSTEM
.prin urmare, o
IMPORTED
țintă ar trebui să reprezinte ceva care nu face parte direct din pachetul dvs.
mai multe lecturi
- bazat pe elementele de bază Moderne CMake
- vezi și documentele CMake
puncte cheie
bibliotecile și executabilele sunt ținte.
țintele au o mulțime de proprietăți utile.
țintele pot fi legate de alte ținte.
puteți controla ce părți ale unei ținte sunt moștenite atunci când se leagă.
puteți face ținte de interfață în loc să faceți variabile.