सीएमके लिए क्या है?
विकिपीडिया के अनुसार:
संकलक [...] एक संकलक-स्वतंत्र पद्धति का उपयोग करके सॉफ्टवेयर की निर्माण प्रक्रिया के प्रबंधन के लिए सॉफ्टवेयर है। यह निर्देशिका पदानुक्रम और अनुप्रयोगों का समर्थन करने के लिए डिज़ाइन किया गया है जो कई पुस्तकालयों पर निर्भर करता है। इसका उपयोग देशी बिल्ड वातावरण जैसे मेक, एप्पल के Xcode, और Microsoft Visual Studio के संयोजन में किया जाता है।
CMake के साथ, आपको अब अपने कंपाइलर / बिल्ड वातावरण के लिए विशिष्ट सेटिंग्स को बनाए रखने की आवश्यकता नहीं है। आपके पास एक कॉन्फ़िगरेशन है, और यह कई वातावरणों के लिए काम करता है।
CMake उनमें से कुछ भी बदले बिना एक ही फाइलों से एक Microsoft Visual Studio समाधान, एक ग्रहण परियोजना या एक मेकफाइल भूलभुलैया उत्पन्न कर सकता है।
कोड के साथ निर्देशिकाओं के एक समूह को देखते हुए, सीएमके सभी आश्रितों का निर्माण करता है, आदेश और अन्य कार्यों का निर्माण करता है जिन्हें आपकी परियोजना की जरूरत होती है। यह वास्तव में कुछ भी संकलित नहीं करता है। CMake का उपयोग करने के लिए, आपको इसे बताना चाहिए (CMakeLists.txt नामक कॉन्फ़िगरेशन फ़ाइलों का उपयोग करके) आपको किन निष्पादन योग्य चीज़ों का संकलन करने की आवश्यकता है, वे किन पुस्तकालयों से लिंक करते हैं, आपकी परियोजना में कौन सी निर्देशिकाएँ हैं और उनके अंदर क्या है, साथ ही किसी भी विवरण जैसे झंडे या कुछ और जो आपको चाहिए (CMake काफी शक्तिशाली है)।
यदि यह सही तरीके से सेट किया गया है, तो आप सीएमके का उपयोग उन सभी फाइलों को बनाने के लिए करते हैं जो आपके "पसंद के मूल निर्माण वातावरण" को अपना काम करने के लिए चाहिए। लिनक्स में, डिफ़ॉल्ट रूप से, इसका मतलब है मेकफाइल्स। तो एक बार जब आप CMake चलाते हैं, तो यह अपने स्वयं के उपयोग के लिए फ़ाइलों का एक गुच्छा तैयार करेगा और कुछ Makefile
s। उसके बाद आपको रूट फ़ोल्डर से कंसोल में "कोड" टाइप करने की आवश्यकता होती है, हर बार जब आप अपना कोड संपादित करते हैं, और bam, एक संकलित और जुड़ा निष्पादन योग्य बनाया जाता है।
CMake कैसे काम करता है? यह क्या करता है?
यहाँ एक उदाहरण परियोजना सेटअप है जिसे मैं पूरे समय उपयोग करूँगा:
simple/
CMakeLists.txt
src/
tutorial.cxx
CMakeLists.txt
lib/
TestLib.cxx
TestLib.h
CMakeLists.txt
build/
प्रत्येक फ़ाइल की सामग्री को बाद में दिखाया और चर्चा की जाती है।
CMake आपके प्रोजेक्ट को आपके प्रोजेक्ट के रूट CMakeLists.txt
के अनुसार सेट करता है, और cmake
कंसोल में आपके द्वारा निष्पादित की गई डायरेक्टरी में ऐसा करता है। ऐसा करने वाले फ़ोल्डर से ऐसा करना जो आपकी परियोजना की जड़ नहीं है, जिसे आउट-ऑफ-सोर्स बिल्ड कहा जाता है , जिसका अर्थ है संकलन के दौरान बनाई गई फ़ाइलें (obj फ़ाइलें, lib फ़ाइलें, निष्पादक, आप जानते हैं) उक्त फ़ोल्डर में रखी जाएंगी , वास्तविक कोड से अलग रखा गया। यह अव्यवस्था को कम करने में मदद करता है और अन्य कारणों से भी पसंद किया जाता है, जिसकी मैं चर्चा नहीं करूंगा।
मुझे नहीं पता कि क्या होता है अगर आप cmake
रूट के अलावा किसी और पर अमल करते हैं CMakeLists.txt
।
इस उदाहरण में, चूंकि मैं चाहता हूं कि यह सब build/
फ़ोल्डर के अंदर रखा जाए , पहले मुझे वहां नेविगेट करना होगा, फिर उस निर्देशिका को सीएमके पास करना होगा जिसमें रूट CMakeLists.txt
छुपा हो।
cd build
cmake ..
जैसा कि मैंने कहा है, डिफ़ॉल्ट रूप से, यह मेकफाइल्स का उपयोग करके सब कुछ सेट करता है। यहां बताया गया है कि बिल्ड फ़ोल्डर को अब कैसा दिखना चाहिए:
simple/build/
CMakeCache.txt
cmake_install.cmake
Makefile
CMakeFiles/
(...)
src/
CMakeFiles/
(...)
cmake_install.cmake
Makefile
lib/
CMakeFiles/
(...)
cmake_install.cmake
Makefile
ये सभी फाइलें क्या हैं? केवल एक चीज जिसके बारे में आपको चिंता करने की ज़रूरत है वह है मेकफाइल और प्रोजेक्ट फ़ोल्डर ।
नोटिस src/
और lib/
फोल्डर। इन्हें बनाया गया है क्योंकि simple/CMakeLists.txt
कमांड का उपयोग करके उन्हें इंगित करता है add_subdirectory(<folder>)
। यह आदेश बताता है CMake किसी अन्य के लिए कहा फ़ोल्डर में देखने के लिए CMakeLists.txt
फ़ाइल और निष्पादित कि , स्क्रिप्ट तो हर उपनिर्देशिका इस तरह से जोड़ा जाना चाहिए एक है CMakeLists.txt
के भीतर फ़ाइल। इस परियोजना में, simple/src/CMakeLists.txt
वास्तविक निष्पादन योग्य simple/lib/CMakeLists.txt
बनाने के तरीके का वर्णन करता है और पुस्तकालय के निर्माण का वर्णन करता है। प्रत्येक लक्ष्य जो एक CMakeLists.txt
वर्णन बिल्ड ट्री के भीतर उसके उपनिर्देशिका में डिफ़ॉल्ट रूप से रखा जाएगा। तो, एक त्वरित के बाद
make
कंसोल में build/
, कुछ फ़ाइलों को जोड़ा गया है:
simple/build/
(...)
lib/
libTestLib.a
(...)
src/
Tutorial
(...)
प्रोजेक्ट बनाया गया है, और निष्पादन योग्य निष्पादित होने के लिए तैयार है। यदि आप चाहते हैं कि निष्पादन योग्य एक विशिष्ट फ़ोल्डर में रखा जाए तो आप क्या करते हैं? उपयुक्त CMake चर सेट करें, या किसी विशिष्ट लक्ष्य के गुणों को बदलें । बाद में CMake चर पर अधिक।
मैं सीएमके को अपनी परियोजना कैसे बनाऊं?
यहां स्रोत निर्देशिका में प्रत्येक फ़ाइल की सामग्री, व्याख्या की गई है:
simple/CMakeLists.txt
:
cmake_minimum_required(VERSION 2.6)
project(Tutorial)
# Add all subdirectories in this project
add_subdirectory(lib)
add_subdirectory(src)
चेतावनी के अनुसार न्यूनतम आवश्यक संस्करण हमेशा सेट किया जाना चाहिए, जब आप नहीं करते हैं। अपने सीएमके संस्करण का उपयोग करें।
आपके प्रोजेक्ट का नाम बाद में उपयोग किया जा सकता है, और इस तथ्य की ओर संकेत करता है कि आप एक ही सीएमके फ़ाइलों से एक से अधिक प्रोजेक्ट प्रबंधित कर सकते हैं। मैं उस में तल्लीन नहीं होगा, यद्यपि।
जैसा कि पहले उल्लेख किया add_subdirectory()
गया है, परियोजना में एक फ़ोल्डर जोड़ता है, जिसका अर्थ है कि सीएमके को उम्मीद है कि यह CMakeLists.txt
भीतर होगा, जिसे वह जारी रखने से पहले चलेगा। वैसे, यदि आप सीएमके फ़ंक्शन को परिभाषित करते हैं, तो आप इसे CMakeLists.txt
उपनिर्देशिकाओं में अन्य एस से उपयोग कर सकते हैं , लेकिन आपको इसे उपयोग करने से पहले इसे परिभाषित add_subdirectory()
करना होगा या इसे नहीं मिलेगा। सीएमके पुस्तकालयों के बारे में अधिक चालाक है, हालांकि, इसलिए यह संभावना है कि आप इस तरह की समस्या में भाग लेंगे।
simple/lib/CMakeLists.txt
:
add_library(TestLib TestLib.cxx)
अपनी खुद की लाइब्रेरी बनाने के लिए, आप इसे एक नाम देते हैं और फिर इसके द्वारा बनाई गई सभी फाइलों को सूचीबद्ध करते हैं। सीधा। यदि इसे foo.cxx
संकलित करने के लिए दूसरी फ़ाइल की आवश्यकता है , तो आप इसके बजाय लिखेंगे add_library(TestLib TestLib.cxx foo.cxx)
। यह अन्य निर्देशिकाओं में फ़ाइलों के लिए भी काम करता है, उदाहरण के लिए add_library(TestLib TestLib.cxx ${CMAKE_SOURCE_DIR}/foo.cxx)
। बाद में CMAKE_SOURCE_DIR चर पर अधिक।
इसके साथ एक और बात आप निर्दिष्ट कर सकते हैं कि आप एक साझा पुस्तकालय चाहते हैं। उदाहरण add_library(TestLib SHARED TestLib.cxx)
:। डर नहीं, यह वह जगह है जहां सीएमके आपके जीवन को आसान बनाने के लिए शुरू होता है। यह साझा किया गया है या नहीं, अब आपको इस तरह से बनाई गई लाइब्रेरी का उपयोग करने के लिए सभी को संभालने की आवश्यकता है जो आपने यहां दिया था। इस लाइब्रेरी का नाम अब TestLib है, और आप इसे प्रोजेक्ट में कहीं से भी संदर्भित कर सकते हैं । सीएमके पास मिलेगा।
क्या निर्भरता को सूचीबद्ध करने का एक बेहतर तरीका है? निश्चित रूप से हाँ । इस पर अधिक जानकारी के लिए नीचे देखें।
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)
कमांड add_executable()
बिल्कुल वैसा ही काम करता है, जैसे add_library()
, निश्चित रूप से, यह एक निष्पादन योग्य उत्पन्न करेगा। इस निष्पादन योग्य को अब जैसी चीजों के लिए एक लक्ष्य के रूप में संदर्भित किया जा सकता है target_link_libraries()
। चूंकि Tutorial.cxx TestLib लाइब्रेरी में पाए गए कोड का उपयोग करता है, आप इसे दिखाए गए अनुसार सीएमके को इंगित करते हैं।
इसी तरह, किसी भी ज में किसी भी स्रोत से #included फ़ाइलों add_executable()
कि कर रहे हैं नहीं के रूप में स्रोत किसी भी तरह जोड़ा जा करने के लिए है एक ही निर्देशिका में। यदि target_include_directories()
कमांड के lib/TestLib.h
लिए नहीं है, तो ट्यूटोरियल संकलित करते समय नहीं मिलेगा, इसलिए पूरे lib/
फ़ोल्डर को #inceses के लिए खोजे जाने के लिए शामिल निर्देशिकाओं में जोड़ा जाता है। आप कमांड को भी देख सकते हैं include_directories()
जो एक समान फैशन में काम करता है, सिवाय इसके कि आपको एक लक्ष्य निर्दिष्ट करने की आवश्यकता नहीं है क्योंकि यह एकमुश्त इसे विश्व स्तर पर सेट करता है, सभी निष्पादन योग्य लोगों के लिए। एक बार फिर, मैं CMAKE_SOURCE_DIR को बाद में समझाऊंगा।
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" फ़ाइल कैसे शामिल है। पूर्ण पथ को शामिल करने की आवश्यकता नहीं है: सीएमके उन सभी का ध्यान रखता है जो पर्दे के पीछे धन्यवाद करते हैं target_include_directories()
।
तकनीकी तौर पर इस तरह बात करते हुए एक साधारण स्रोत पेड़ में आप कर सकते हैं बिना CMakeLists.txt
तहत lib/
और src/
और बस की तरह कुछ जोड़ने add_executable(Tutorial src/tutorial.cxx)
के लिए simple/CMakeLists.txt
। यह आपके और आपकी परियोजना की जरूरतों पर निर्भर है।
सीएमके को ठीक से उपयोग करने के लिए मुझे और क्या पता होना चाहिए?
(AKA आपकी समझ के लिए प्रासंगिक विषय)
पैकेज खोजना और उसका उपयोग करना : इस प्रश्न का उत्तर मुझे पहले से बेहतर समझा गया है।
चर और कार्यों की घोषणा करना, नियंत्रण प्रवाह का उपयोग करना, आदि : इस ट्यूटोरियल की जांच करें जो मूल बातें बताती है कि सीएमके को क्या पेशकश करनी है, साथ ही साथ सामान्य रूप से एक अच्छा परिचय भी है।
सीएमके चर : बहुत सारे हैं, इसलिए आपको सही रास्ते पर लाने के लिए एक दुर्घटना पाठ्यक्रम है। CMake wiki एक अच्छी जगह है जो चर और गहराई से अधिक जानकारी के साथ-साथ अन्य चीजों के बारे में गहराई से जानकारी प्राप्त करता है।
आप बिल्ड ट्री के पुनर्निर्माण के बिना कुछ चर को संपादित करना चाह सकते हैं। इसके लिए ccmake का उपयोग करें (यह CMakeCache.txt
फ़ाइल को संपादित करता है)। याद रखें कि c
जब परिवर्तन के साथ किया जाता है और तब g
अद्यतन विन्यास के साथ मेकफाइल्स को लागू करें।
चर का उपयोग करने के बारे में जानने के लिए पहले संदर्भित ट्यूटोरियल पढ़ें , लेकिन लंबी कहानी छोटी:
set(<variable name> value)
एक चर को बदलने या बनाने के लिए।
${<variable name>}
इसके प्रयेाग के लिए।
CMAKE_SOURCE_DIR
: स्रोत की जड़ निर्देशिका। पिछले उदाहरण में, यह हमेशा के बराबर है/simple
CMAKE_BINARY_DIR
: बिल्ड की रूट डायरेक्टरी। पिछले उदाहरण में, यह बराबर है simple/build/
, लेकिन यदि आप cmake simple/
एक फ़ोल्डर से भागते हैं जैसे कि foo/bar/etc/
, तो CMAKE_BINARY_DIR
उस बिल्ड ट्री में सभी संदर्भ बन जाएंगे /foo/bar/etc
।
CMAKE_CURRENT_SOURCE_DIR
: निर्देशिका जिसमें वर्तमान CMakeLists.txt
में है इस का मतलब यह भर परिवर्तन:। से इस मुद्रण simple/CMakeLists.txt
पैदावार /simple
, और से यह मुद्रण simple/src/CMakeLists.txt
पैदावार /simple/src
।
CMAKE_CURRENT_BINARY_DIR
: तुम्हें नया तरीका मिल गया है। यह पथ न केवल उस फ़ोल्डर पर निर्भर करेगा जो निर्माण में है, बल्कि वर्तमान CMakeLists.txt
स्क्रिप्ट के स्थान पर भी है ।
ये महत्वपूर्ण क्यों हैं? स्रोत फ़ाइलें स्पष्ट रूप से बिल्ड ट्री में नहीं होंगी। यदि आप target_include_directories(Tutorial PUBLIC ../lib)
पिछले उदाहरण में ऐसा कुछ करने का प्रयास करते हैं , तो वह पथ बिल्ड ट्री के सापेक्ष होगा, कहने का मतलब यह है कि यह लेखन जैसा ${CMAKE_BINARY_DIR}/lib
होगा, जो अंदर दिखेगा simple/build/lib/
। वहाँ कोई .h फ़ाइलें नहीं हैं; ज्यादा से ज्यादा तुम पाओगे libTestLib.a
। आप ${CMAKE_SOURCE_DIR}/lib
इसके बजाय चाहते हैं।
CMAKE_CXX_FLAGS
: झंडे कंपाइलर को पास करने के लिए, इस मामले में C ++ कंपाइलर। इसके अलावा ध्यान देने योग्य है CMAKE_CXX_FLAGS_DEBUG
जो CMAKE_BUILD_TYPE
कि DEBUG पर सेट होने के बजाय उपयोग किया जाएगा । ऐसे और भी हैं; सीएमके विकि की जाँच करें ।
CMAKE_RUNTIME_OUTPUT_DIRECTORY
: सीएमके को बताएं कि निर्मित होने पर सभी निष्पादन योग्य कहां रखें। यह एक वैश्विक सेटिंग है। उदाहरण के लिए, आप इसे सेट कर सकते हैं bin/
और वहां सब कुछ बड़े करीने से रख सकते हैं। EXECUTABLE_OUTPUT_PATH
यदि आप इस पर ठोकर खाते हैं तो समान है, लेकिन पदावनत किया गया है।
CMAKE_LIBRARY_OUTPUT_DIRECTORY
: इसी तरह, सीएमके को यह बताने के लिए एक वैश्विक सेटिंग कि सभी लाइब्रेरी फ़ाइलों को कहां रखा जाए।
लक्ष्य गुण : आप केवल एक लक्ष्य को प्रभावित करने वाले गुण सेट कर सकते हैं, यह एक निष्पादन योग्य या एक पुस्तकालय (या एक संग्रह ... आपको विचार मिलता है) हो सकता है। इसका उपयोग कैसे करें (इसके साथ) इसका एक अच्छा उदाहरण है set_target_properties()
।
क्या स्वचालित रूप से किसी लक्ष्य में स्रोतों को जोड़ने का एक आसान तरीका है? एक ही चर के तहत दिए गए निर्देशिका में सब कुछ सूचीबद्ध करने के लिए GLOB का उपयोग करें । उदाहरण वाक्य रचना है FILE(GLOB <variable name> <directory>/*.cxx)
।
क्या आप विभिन्न बिल्ड प्रकार निर्दिष्ट कर सकते हैं? हां, हालांकि मैं इस बारे में निश्चित नहीं हूं कि यह कैसे काम करता है या इसकी सीमाएं क्या हैं। यह शायद कुछ की आवश्यकता है अगर / फिर'ning, लेकिन CMake CMAKE_CXX_FLAGS_DEBUG
उदाहरण के लिए, डिफ़ॉल्ट के बिना, कुछ भी कॉन्फ़िगर किए बिना कुछ मूल समर्थन प्रदान करता है । आप या तो CMakeLists.txt
फ़ाइल के भीतर set(CMAKE_BUILD_TYPE <type>)
या उदाहरण के लिए उपयुक्त झंडे के साथ कंसोल से सीएमके को कॉल करके अपने बिल्ड प्रकार को सेट कर सकते हैं cmake -DCMAKE_BUILD_TYPE=Debug
।
CMake का उपयोग करने वाली परियोजनाओं का कोई अच्छा उदाहरण? विकिपीडिया में सीएमके का उपयोग करने वाले ओपन-सोर्स प्रोजेक्ट्स की एक सूची है, यदि आप उस पर गौर करना चाहते हैं। ऑनलाइन ट्यूटोरियल इस संबंध में अब तक मेरे लिए कुछ भी नहीं है, लेकिन इस स्टैक ओवरफ्लो प्रश्न में एक बहुत अच्छा और आसानी से समझने वाला CMake सेटअप है। यह देखने लायक है।
अपने कोड में CMake से चर का उपयोग करना : यहाँ एक त्वरित और गंदा उदाहरण है ( कुछ अन्य ट्यूटोरियल से अनुकूलित ):
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@
सीएमके द्वारा उत्पन्न परिणामी फाइल simple/src/TutorialConfig.h
:
// Configured options and settings
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 1
इन के चतुर उपयोग से आप शांत चीजें कर सकते हैं जैसे पुस्तकालय बंद करना और इस तरह से। मैं उस ट्यूटोरियल पर एक नज़र डालने की सलाह देता हूं क्योंकि कुछ और उन्नत चीजें हैं जो बड़ी परियोजनाओं, बहुत जल्दी या बाद में बहुत उपयोगी होने के लिए बाध्य हैं।
बाकी सभी चीजों के लिए, स्टैक ओवरफ्लो विशिष्ट प्रश्नों और संक्षिप्त उत्तरों के साथ काम कर रहा है, जो कि बिना किसी को छोड़कर सभी के लिए बहुत अच्छा है।