CMake ne içindir?
Wikipedia'ya göre:
CMake, derleyiciden bağımsız bir yöntem kullanarak yazılım oluşturma sürecini yönetmek için [...] bir yazılımdır. Birden çok kitaplığa bağlı olan dizin hiyerarşilerini ve uygulamaları desteklemek için tasarlanmıştır. Make, Apple'ın Xcode'u ve Microsoft Visual Studio gibi yerel derleme ortamlarıyla birlikte kullanılır.
CMake ile artık derleyicinize / derleme ortamınıza özgü ayrı ayarlar tutmanıza gerek kalmaz. Tek bir yapılandırmanız var ve bu birçok ortam için çalışıyor .
CMake, içindeki hiçbir şeyi değiştirmeden aynı dosyalardan bir Microsoft Visual Studio çözümü, bir Eclipse projesi veya bir Makefile labirenti oluşturabilir .
İçlerinde kod bulunan bir grup dizin verildiğinde, CMake tüm bağımlılıkları, derleme siparişlerini ve projenizin derlenmeden önce yapılması gereken diğer görevleri yönetir. Aslında hiçbir şey derlemez. CMake'i kullanmak için (CMakeLists.txt adlı yapılandırma dosyalarını kullanarak) hangi yürütülebilir dosyaları derlemeniz gerektiğini, hangi kitaplıklara bağlandıklarını, projenizde hangi dizinlerin olduğunu ve bunların içinde ne olduğunu ve bayraklar gibi ayrıntıları söylemelisiniz. veya ihtiyacınız olan herhangi bir şey (CMake oldukça güçlüdür).
Bu doğru bir şekilde ayarlanmışsa, seçtiğiniz "yerel oluşturma ortamının" işini yapması için ihtiyaç duyduğu tüm dosyaları oluşturmak için CMake kullanırsınız. Linux'ta varsayılan olarak bu Makefiles anlamına gelir. Yani CMake'i çalıştırdığınızda, kendi kullanımı için bir sürü dosya ve bazı dosyalar oluşturacaktır Makefile
. Bundan sonra yapmanız gereken tek şey, kodunuzu her düzenlemeyi bitirdiğinizde kök klasörden konsola "make" yazmaktır ve bam, derlenmiş ve bağlantılı bir yürütülebilir dosya oluşturulur.
CMake nasıl çalışır? Bu ne işe yarıyor?
İşte boyunca kullanacağım örnek bir proje kurulumu:
simple/
CMakeLists.txt
src/
tutorial.cxx
CMakeLists.txt
lib/
TestLib.cxx
TestLib.h
CMakeLists.txt
build/
Her dosyanın içeriği daha sonra gösterilir ve tartışılır.
CMake, projenizi projenizin köküne göre ayarlar CMakeLists.txt
ve bunu cmake
konsolda çalıştırdığınız dizine göre yapar . Bunu projenizin kökü olmayan bir klasörden yapmak , kaynak dışı derleme denen şeyi üretir , bu da derleme sırasında oluşturulan dosyaların (obj dosyaları, lib dosyaları, çalıştırılabilirler, bilirsiniz) söz konusu klasöre yerleştirileceği anlamına gelir. , gerçek koddan ayrı tutulur. Dağınıklığı azaltmaya yardımcı olur ve tartışmayacağım başka nedenlerle de tercih edilir.
cmake
Kök dışında herhangi bir şekilde çalıştırırsanız ne olur bilmiyorum CMakeLists.txt
.
Bu örnekte, hepsinin build/
klasörün içine yerleştirilmesini istediğim için , önce oraya gitmem, sonra da geçmem gerekiyor CMakeLists.txt
. Kökün bulunduğu dizini al .
cd build
cmake ..
Varsayılan olarak, bu, söylediğim gibi her şeyi Makefiles kullanarak ayarlar. Yapı klasörünün şimdi nasıl görünmesi gerektiği aşağıda açıklanmıştır:
simple/build/
CMakeCache.txt
cmake_install.cmake
Makefile
CMakeFiles/
(...)
src/
CMakeFiles/
(...)
cmake_install.cmake
Makefile
lib/
CMakeFiles/
(...)
cmake_install.cmake
Makefile
Tüm bu dosyalar nedir? Endişelenmeniz gereken tek şey Makefile ve proje klasörleridir .
src/
Ve lib/
klasörlerine dikkat edin . Bunlar simple/CMakeLists.txt
, komutu kullanarak onları işaret ettiği için oluşturulmuştur add_subdirectory(<folder>)
. Bu komut CMake'ye söz konusu klasöre başka bir CMakeLists.txt
dosya bakmasını ve bu komut dosyasını çalıştırmasını söyler , böylece bu şekilde eklenen her alt dizinin içinde bir dosya olmalıdırCMakeLists.txt
. Bu projede, simple/src/CMakeLists.txt
gerçek yürütülebilir dosyanın simple/lib/CMakeLists.txt
nasıl oluşturulacağını ve kitaplığın nasıl oluşturulacağını açıklar. CMakeLists.txt
Açıklanan her hedef, varsayılan olarak yapı ağacındaki alt dizinine yerleştirilecektir. Yani, kısa bir süre sonra
make
konsolda build/
, bazı dosyalar eklenir:
simple/build/
(...)
lib/
libTestLib.a
(...)
src/
Tutorial
(...)
Proje oluşturuldu ve yürütülebilir dosya yürütülmeye hazır. Yürütülebilir dosyaların belirli bir klasöre yerleştirilmesini istiyorsanız ne yaparsınız? Uygun CMake değişkenini ayarlayın veya belirli bir hedefin özelliklerini değiştirin . CMake değişkenleri hakkında daha sonra.
CMake'e projemi nasıl oluşturacağını nasıl söylerim?
Kaynak dizindeki her dosyanın içeriği açıklanmıştır:
simple/CMakeLists.txt
:
cmake_minimum_required(VERSION 2.6)
project(Tutorial)
# Add all subdirectories in this project
add_subdirectory(lib)
add_subdirectory(src)
Gerekli olan minimum sürüm, siz yapmadığınızda CMake'nin attığı uyarıya göre her zaman ayarlanmalıdır. CMake sürümünüz ne olursa olsun kullanın.
Projenizin adı daha sonra kullanılabilir ve aynı CMake dosyalarından birden fazla projeyi yönetebileceğiniz gerçeğine işaret eder. Yine de bununla ilgilenmeyeceğim.
Daha önce bahsedildiği gibi add_subdirectory()
, projeye bir klasör ekler, bu da CMake'in bir CMakeLists.txt
içinde olmasını beklediği ve devam etmeden önce çalışacağı anlamına gelir . Bu arada, tanımlanmış bir CMake işlevine sahipseniz, onu CMakeLists.txt
alt dizinlerdeki diğer URL'lerden kullanabilirsiniz , ancak kullanmadan önce tanımlamanız add_subdirectory()
gerekir, yoksa bulamaz. CMake kütüphaneler konusunda daha akıllıdır, bu yüzden muhtemelen bu tür bir problemle karşılaşacağınız tek zaman budur.
simple/lib/CMakeLists.txt
:
add_library(TestLib TestLib.cxx)
Kendi kitaplığınızı oluşturmak için ona bir ad verin ve ardından oluşturduğu tüm dosyaları listeleyin. Basit. Derlenmesi için başka bir dosyaya ihtiyaç foo.cxx
duysaydı, onun yerine yazardın add_library(TestLib TestLib.cxx foo.cxx)
. Bu, örneğin diğer dizinlerdeki dosyalar için de işe yarar add_library(TestLib TestLib.cxx ${CMAKE_SOURCE_DIR}/foo.cxx)
. CMAKE_SOURCE_DIR değişkeni hakkında daha sonra daha fazlası.
Bununla yapabileceğiniz başka bir şey, paylaşılan bir kitaplık istediğinizi belirtmektir. Örnek: add_library(TestLib SHARED TestLib.cxx)
. Korkmayın, CMake hayatınızı kolaylaştırmaya başladığı yerdir. Paylaşılmış olsun ya da olmasın, bu şekilde oluşturulmuş bir kitaplığı kullanmak için yapmanız gereken tek şey ona burada verdiğiniz addır. Bu kütüphanenin adı artık TestLib'tir ve projenin herhangi bir yerinden ona başvurabilirsiniz . CMake onu bulacaktır.
Bağımlılıkları listelemenin daha iyi bir yolu var mı? Kesinlikle evet . Bununla ilgili daha fazla bilgi için aşağıya bakın.
simple/lib/TestLib.cxx
:
#include <stdio.h>
void test() {
printf("testing...\n");
}
simple/lib/TestLib.h
:
#ifndef TestLib
#define TestLib
void test();
#endif
simple/src/CMakeLists.txt
:
# Name the executable and all resources it depends on directly
add_executable(Tutorial tutorial.cxx)
# Link to needed libraries
target_link_libraries(Tutorial TestLib)
# Tell CMake where to look for the .h files
target_include_directories(Tutorial PUBLIC ${CMAKE_SOURCE_DIR}/lib)
Komut , elbette bunun yerine bir yürütülebilir dosya oluşturması dışında, add_executable()
tamamen aynı şekilde çalışır add_library()
. Bu yürütülebilir dosya artık gibi şeyler için bir hedef olarak gösterilebilir target_link_libraries()
. Tutorial.cxx, TestLib kitaplığında bulunan kodu kullandığından, bunu gösterildiği gibi CMake'e yönlendirirsiniz.
Benzer şekilde, herhangi bir kaynaklarca #include herhangi .h dosyaları add_executable()
o vardır değil kaynak nasılsa eklenmesi gerekir aynı dizinde. target_include_directories()
Komut için değilse , lib/TestLib.h
Tutorial derlenirken bulunmaz, bu nedenle tüm lib/
klasör #includes için aranacak içerme dizinlerine eklenir. include_directories()
Tüm çalıştırılabilir dosyalar için doğrudan genel olarak belirlediği için bir hedef belirtmenize gerek olmaması dışında, benzer şekilde davranan komutu da görebilirsiniz . Bir kez daha, CMAKE_SOURCE_DIR'i daha sonra açıklayacağım.
simple/src/tutorial.cxx
:
#include <stdio.h>
#include "TestLib.h"
int main (int argc, char *argv[])
{
test();
fprintf(stdout, "Main\n");
return 0;
}
"TestLib.h" dosyasının nasıl dahil edildiğine dikkat edin. Tam yolu eklemeye gerek yok: CMake sayesinde perde arkasındaki her şeyi hallediyor target_include_directories()
.
Teknik olarak siz olmadan bu gibi basit bir kaynak ağacında, olabilir konuşan CMakeLists.txt
altında s lib/
ve src/
sadece böyle bir şey eklemeden add_executable(Tutorial src/tutorial.cxx)
için simple/CMakeLists.txt
. Size ve projenizin ihtiyaçlarına bağlıdır.
CMake'i doğru şekilde kullanmak için başka ne bilmeliyim?
(Anlayışınızla ilgili AKA konuları)
Paketleri bulmak ve kullanmak : Bu sorunun cevabı onu benim yapabileceğimden daha iyi açıklıyor.
Değişkenleri ve fonksiyonları bildirme, kontrol akışını kullanma vb .: CMake'nin sunduğu temel bilgileri açıklayan ve genel olarak iyi bir giriş niteliğindeki bu eğiticiye göz atın.
CMake değişkenleri : Bol miktarda var, bu yüzden sizi doğru yola sokmak için hızlandırılmış bir kurs var. CMake wiki, değişkenler ve görünüşte diğer şeyler hakkında daha derinlemesine bilgi almak için iyi bir yerdir .
Yapı ağacını yeniden oluşturmadan bazı değişkenleri düzenlemek isteyebilirsiniz. Bunun için ccmake kullanın (dosyayı düzenler CMakeCache.txt
). Unutmayın c
değişiklikleri ve daha sonra içinde yapıldığında onfigure g
güncellenmiş yapılandırmayla Nesli bozuk makefiles.
Değişkenleri kullanma hakkında bilgi edinmek için önceden atıfta bulunulan öğreticiyi okuyun , ancak uzun lafın kısası:
set(<variable name> value)
bir değişkeni değiştirmek veya oluşturmak için.
${<variable name>}
kullanmak için.
CMAKE_SOURCE_DIR
: Kaynağın kök dizini. Önceki örnekte, bu her zaman şuna eşittir:/simple
CMAKE_BINARY_DIR
: Yapının kök dizini. Önceki örnekte, bu şuna eşittir simple/build/
, ancak cmake simple/
gibi bir klasörden koşarsanız , bu yapı ağacındaki foo/bar/etc/
tüm başvurular CMAKE_BINARY_DIR
olur /foo/bar/etc
.
CMAKE_CURRENT_SOURCE_DIR
: Dizin içinde mevcut CMakeLists.txt
olan bu boyunca değişen bu araçlar. Bu baskı simple/CMakeLists.txt
verimleri /simple
ve onu baskı simple/src/CMakeLists.txt
verimi /simple/src
.
CMAKE_CURRENT_BINARY_DIR
: Kaptın bu işi. Bu yol sadece yapının bulunduğu klasöre değil, aynı zamanda geçerli CMakeLists.txt
betiğin konumuna da bağlı olacaktır.
Bunlar neden önemlidir? Kaynak dosyalar açıkça yapı ağacında olmayacaktır. target_include_directories(Tutorial PUBLIC ../lib)
Önceki örnekteki gibi bir şey denerseniz , bu yol inşa ağacına göre olacaktır, yani yazıya ${CMAKE_BINARY_DIR}/lib
benzeyecek ve içeriye bakacaktır simple/build/lib/
. Orada .h dosyası yok; en fazla bulacaksın libTestLib.a
. Onun ${CMAKE_SOURCE_DIR}/lib
yerine istiyorsun .
CMAKE_CXX_FLAGS
: Derleyiciye, bu durumda C ++ derleyicisine iletilecek bayraklar. Ayrıca DEBUG olarak ayarlanmışsa CMAKE_CXX_FLAGS_DEBUG
bunun yerine hangisinin kullanılacağına dikkat edilmelidir CMAKE_BUILD_TYPE
. Bunun gibi daha fazlası var; kontrol CKağıt wiki .
CMAKE_RUNTIME_OUTPUT_DIRECTORY
: CMake'e derlendiğinde tüm yürütülebilir dosyaları nereye koyacağını söyleyin. Bu küresel bir ayardır. Örneğin, onu ayarlayabilir bin/
ve her şeyi oraya düzgün bir şekilde yerleştirebilirsiniz. EXECUTABLE_OUTPUT_PATH
benzer, ancak yanılmanız durumunda kullanımdan kaldırılmıştır.
CMAKE_LIBRARY_OUTPUT_DIRECTORY
: Benzer şekilde, CMake'e tüm kitaplık dosyalarını nereye koyacağını söyleyen genel bir ayar.
Hedef özellikleri : Bir yürütülebilir dosya veya bir kitaplık (veya bir arşiv ... fikri alırsınız), yalnızca bir hedefi etkileyen özellikleri ayarlayabilirsiniz. İşte nasıl kullanılacağına dair güzel bir örnek ( set_target_properties()
.
Bir hedefe otomatik olarak kaynak eklemenin kolay bir yolu var mı? Belirli bir dizindeki her şeyi aynı değişken altında listelemek için GLOB'u kullanın . Örnek sözdizimi FILE(GLOB <variable name> <directory>/*.cxx)
.
Farklı yapı türleri belirtebilir misiniz? Evet, bunun nasıl çalıştığından veya bunun sınırlamalarından emin değilim. Muhtemelen biraz if / then'ning gerektirir, ancak CMake, örneğin için varsayılanlar gibi herhangi bir şeyi yapılandırmadan bazı temel destek sunar CMAKE_CXX_FLAGS_DEBUG
. Derleme türünüzü , örneğin, uygun bayraklarla konsoldan CMake'i çağırarak veya CMakeLists.txt
dosya içinden ayarlayabilirsiniz .set(CMAKE_BUILD_TYPE <type>)
cmake -DCMAKE_BUILD_TYPE=Debug
CMake kullanan herhangi bir iyi proje örneği var mı? Wikipedia'da, bakmak isterseniz, CMake kullanan açık kaynaklı projelerin bir listesi vardır. Çevrimiçi eğitimler bu konuda şimdiye kadar benim için bir hayal kırıklığından başka bir şey olmadı, ancak bu Stack Overflow sorusu oldukça havalı ve anlaşılması kolay bir CMake kurulumuna sahip. Bir bakmaya değer.
CMake'deki değişkenleri kodunuzda kullanma : İşte hızlı ve kirli bir örnek ( başka bir öğreticiden uyarlanmıştır ):
simple/CMakeLists.txt
:
project (Tutorial)
# Setting variables
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 1)
# Configure_file(<input> <output>)
# Copies a file <input> to file <output> and substitutes variable values referenced in the file content.
# So you can pass some CMake variables to the source code (in this case version numbers)
configure_file (
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_SOURCE_DIR}/src/TutorialConfig.h"
)
simple/TutorialConfig.h.in
:
// Configured options and settings
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
CMake tarafından oluşturulan sonuç dosyası simple/src/TutorialConfig.h
:
// Configured options and settings
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 1
Bunların akıllıca kullanılmasıyla, bir kitaplığı kapatmak gibi harika şeyler yapabilirsiniz. Er ya da geç, daha büyük projelerde çok yararlı olması gereken biraz daha gelişmiş şeyler olduğu için bu eğiticiye bir göz atmanızı tavsiye ederim .
Diğer her şey için, Stack Overflow, başlatılmamış olanlar dışındaki herkes için harika olan belirli sorular ve kısa cevaplarla doludur.