Cmake बनाम नमूना कोड बनाते हैं?


118

मैं सोच रहा था कि क्या कोई नमूना कोड Makefiles ( make) और CMakeLists.txt( के लिए था )cmake ) के लिए है कि दोनों एक ही काम करते हैं (केवल अंतर यह है कि एक में लिखा है makeऔर दूसरे में cmake)।

मैंने 'cmake vs make' की तलाश की, लेकिन मुझे कभी कोई कोड तुलना नहीं मिली। यह मतभेदों को समझने में वास्तव में मददगार होगा, भले ही एक साधारण मामले के लिए।


20
+1 यह एक अच्छा सवाल है; जब मैं शुरू कर रहा था तब मैं cmakeभी यही चाहता था। लेकिन मुझे संदेह है कि आप इसे पा लेंगे क्योंकि क्षमताएं बस उस एक को अच्छी तरह से मैप नहीं करती हैं। यदि आप इस cmakeतरह का कार्य करने की कोशिश करते हैं make, तो आप अपने आप को गंभीर रूप से पागल कर देंगे। सबसे अच्छा सिर्फ खरोंच से शुरू करने के लिए। जो चीजें तुच्छ हैं, makeवे इसमें शामिल हैं cmake, और इसके विपरीत।
अर्नेस्ट फ्रीडमैन-हिल

1
@ ErnestFriedman-Hill क्या आपके पास उस पर अधिक विवरण हैं? इसलिए makeऔर cmakeइतने अलग हैं कि उन्हें प्रतिस्पर्धी उपकरणों के बजाय पूरक के रूप में अधिक देखा जाना चाहिए?
एहतेश चौधरी

2
@ शौर्येन - सीमेक स्वयं कुछ भी नहीं बनाता है; यह मेकफाइल्स (और अन्य, समान निर्माण स्क्रिप्ट) बनाता है, जिसे आप तब चलाते हैं। इसलिए जब भी आप cmake फाइल लिख रहे हैं, तो आपको यह सोचना होगा कि क्या कोई कमांड जनरेशन टाइम के दौरान, या बिल्ड टाइम के दौरान लागू होना चाहिए। कुछ क्रियाएं - बिल्ड टाइम पर फ़ाइलों के एक वाइल्डकार्ड सेट की नकल करें, उदाहरण के लिए - cp *.x $(OUTDIR)आप मेकफाइल में लिखेंगे " " की तुलना में काफी जटिल हैं । शायद मेरे लिए सबसे कष्टप्रद हिस्सा यह है कि जेनरेट किए गए मेकफाइल्स पूरी तरह से नॉनपोर्टेबल और अनम्य (निरंतर) डिज़ाइन द्वारा हैं
अर्नेस्ट फ्रीडमैन-हिल

1
(जारी रखा) आप मेकफाइल को फिर से बनाने के लिए एक ही मशीन पर स्रोत निर्देशिका को फिर से चलने वाले सेमीके बिना स्थानांतरित नहीं कर सकते हैं! तो चुनाव सीमेक और मेक के बीच नहीं है, बल्कि खुद पोर्टेबल मेकफाइल्स लिखने के बीच, या प्रत्येक बिल्ड मशीन पर गैर-आनुपातिक लोगों को उत्पन्न करने के लिए सीमेक का उपयोग करना (और यह देखते हुए कि आप विंडोज पर सिग्विन या मिंगव का उपयोग कर सकते हैं, मुझे आमतौर पर पता चलता है कि पूर्व आसान है। )
अर्नेस्ट फ्रीडमैन-हिल

1
एक अच्छा सवाल है, लेकिन कोई विशेष जवाब नहीं है, दोनों उपकरण एक अलग समस्या को हल करने की कोशिश करते हैं। cmake प्रोग्राम बनाने के बारे में जानकारी लेता है, जो प्रोग्राम बनाने वाले मेकफाइल्स बनाता है। इसलिए सीमेक अमूर्त बिल्ड नियमों के साथ एक भाषा है और ग्नू मेक एक निर्भरता है जो एक निर्देशित एसाइक्लिक ग्राफ ट्रैवर्सल पर प्रोग्राम निष्पादित करता है।
एलेक्स

जवाबों:


118

निम्न Makefile progस्रोतों से एक निष्पादन योग्य नाम बनाता है prog1.c, prog2.c, prog3.c and main.cprogके खिलाफ जुड़ा हुआ है libmystatlib.a और libmydynlib.soजो दोनों स्रोत से भी निर्मित हैं। इसके अतिरिक्त, में और उसके हेडर में progपुस्तकालय का उपयोग करता है । डिफ़ॉल्ट रूप से Makefile एक रिलीज़ लक्ष्य बनाता है, लेकिन एक डीबग लक्ष्य भी प्रदान करता है:libstuff.astuff/libstuff/include

#Makefile    
CC = gcc
CPP = g++
RANLIB = ar rcs
RELEASE = -c -O3 
DEBUG = -c -g -D_DEBUG
INCDIR = -I./stuff/include
LIBDIR = -L./stuff/lib -L.
LIBS = -lstuff -lmystatlib -lmydynlib
CFLAGS = $(RELEASE)

PROGOBJS = prog1.o prog2.o prog3.o

prog: main.o $(PROGOBJS) mystatlib mydynlib
    $(CC) main.o $(PROGOBJS) $(LIBDIR) $(LIBS) -o prog 
debug: CFLAGS=$(DEBUG)
debug: prog

mystatlib: mystatlib.o
    $(RANLIB) libmystatlib.a mystatlib.o
mydynlib: mydynlib.o
    $(CPP) -shared mydynlib.o -o libmydynlib.so

%.o: %.c
    $(CC) $(CFLAGS) $(INCDIR) $< -o $@ 
%.o: %.cpp
    $(CPP) $(CFLAGS) $(INCDIR) -fPIC  $< -o $@ 

यहाँ एक CMakeLists.txtऐसा है (लगभग) बिल्कुल वैसा ही, कुछ टिप्पणियों के साथ मेकफाइल के समानताओं को रेखांकित करने के लिए:

#CMakeLists.txt     
cmake_minimum_required(VERSION 2.8)                    # stuff not directly
project(example)                                       # related to building

include_directories(${CMAKE_SOURCE_DIR}/stuff/include) # -I flags for compiler
link_directories(${CMAKE_SOURCE_DIR}/stuff/lib)        # -L flags for linker

set(PROGSRC prog1.c prog2.c prog3.c)                   # define variable 

add_executable(prog main.c ${PROGSRC})                 # define executable target prog, specify sources
target_link_libraries(prog mystatlib mydynlib stuff)   # -l flags for linking prog target

add_library(mystatlib STATIC mystatlib.c)              # define static library target mystatlib, specify sources

add_library(mydynlib SHARED mydynlib.cpp)              # define shared library target mydynlib, specify sources
#extra flags for linking mydynlib
set_target_properties(mydynlib PROPERTIES POSITION_INDEPENDENT_CODE TRUE) 
#alternatively:
#set_target_properties(mydynlib PROPERTIES COMPILE_FLAGS "-fPIC")

इस सरल उदाहरण में, सबसे महत्वपूर्ण अंतर हैं:

  • सीएमके पहचानता है कि किस तरह के स्रोत के लिए कौन से कंपाइलर का उपयोग करना है। इसके अलावा, यह प्रत्येक प्रकार के लक्ष्य के लिए आदेशों के सही अनुक्रम को आमंत्रित करता है। इसलिए, जैसे आदेशों का कोई स्पष्ट विनिर्देश नहीं है $(CC) ..., $(RANLIB) ...और इसी तरह।

  • हेडर फाइल, लाइब्रेरी आदि को शामिल करने से संबंधित सभी सामान्य कंपाइलर / लिंकर झंडे को प्लेटफ़ॉर्म स्वतंत्र / बिल्ड सिस्टम स्वतंत्र कमांड द्वारा प्रतिस्थापित किया जाता है।

  • डिबगिंग झंडे को या तो चर CMAKE_BUILD_TYPEको "डिबग" में सेट करके , या प्रोग्राम को लागू करते समय सीएमके को पास करके शामिल किया जाता है cmake -DCMAKE_BUILD_TYPE:STRING=Debug:।

  • CMake '-fPIC' ध्वज ( POSITION_INDEPENDENT_CODEसंपत्ति के माध्यम से ) और कई अन्य लोगों के लिए स्वतंत्र मंच भी प्रदान करता है । फिर भी, सीएमके में और साथ ही मेकफाइल (उपयोग COMPILE_FLAGS और समान गुणों के द्वारा) में अधिक अस्पष्ट सेटिंग्स को हाथ से लागू किया जा सकता है । बेशक सीएमके वास्तव में चमकना शुरू कर देता है जब तीसरे पक्ष के पुस्तकालयों (जैसे ओपनजीएल) को पोर्टेबल तरीके से शामिल किया जाता है।

  • यदि आप Makefile का उपयोग करते हैं, अर्थात makeकमांड लाइन पर टाइप करने पर निर्माण प्रक्रिया में एक कदम होता है । CMake के लिए, दो चरण हैं: सबसे पहले, आपको अपना बिल्ड वातावरण सेटअप करने की आवश्यकता है (या तो cmake <source_dir>अपनी बिल्ड निर्देशिका में टाइप करके या कुछ GUI क्लाइंट चलाकर)। यह आपकी पसंद के बिल्ड सिस्टम पर निर्भर करता है (जैसे यूनिक्स या VC ++ या विंडोज पर MinGW + Msys) के आधार पर मेकफिल या कुछ समान बनाता है। निर्माण प्रणाली को पैरामीटर के रूप में CMake को पारित किया जा सकता है; हालाँकि, CMake आपके सिस्टम कॉन्फ़िगरेशन के आधार पर उचित डिफ़ॉल्ट विकल्प बनाता है। दूसरा, आप चयनित बिल्ड सिस्टम में वास्तविक निर्माण करते हैं।

स्रोत और बिल्ड निर्देश https://github.com/rhoelzel/make_cmake पर उपलब्ध हैं ।


3
क्या मेकफाइल अत्यधिक जटिल नहीं है? एक के CPPFLAGSबजाय का उपयोग करके INCDIRअंतर्निहित नियमों का उपयोग किया जा सकता है और संकलक का स्पष्ट आह्वान बेमानी हो जाएगा। इसी तरह से निपटने के लिए, बिल्ट-इन नियमों को कवर किया जा सकता है। भी, क्यों सेट CPPऔर CCस्पष्ट रूप से? वे पहले से ही अच्छे मूल्यों के लिए तैयार हैं make, वे पूर्वनिर्धारित चर हैं। makeयह भी पहचानता है कि किस संकलक को किस प्रकार के स्रोत के लिए उपयोग करना है, अंतर्निहित नियम कई हैं।
ईसाई हुजेर

1
और इनमें से कई चर को :=इसके बजाय सौंपा जाना चाहिए =
ईसाई हुजेर

1
विवरण को देखते हुए, cmakeकी तुलना में अधिक तुलनीय automakeहै make
ivan_pozdeev

प्रदत्त Makefile को 3/4 पंक्तियों में घटाया जा सकता है। आप INCLUDESइसके बजाय निर्दिष्ट करना चाहिए INCDIR। आपको% .o:%। C नियमों की आवश्यकता नहीं है।
शुवा

6

सीएमके का उपयोग करने वाले कुछ सॉफ्टवेयर को इसके बिल्ड सिस्टम के रूप में पकड़ो (उदाहरण के रूप में चुनने के लिए बहुत सारे ओपनसोर्स प्रोजेक्ट हैं)। स्रोत कोड प्राप्त करें और इसे CMake का उपयोग करके कॉन्फ़िगर करें। परिणामी मेकफाइल्स पढ़ें और आनंद लें।

एक बात का ध्यान रखें कि वे उपकरण वन-टू-वन मैप नहीं करते हैं। सबसे स्पष्ट अंतर यह है कि सीएमके विभिन्न फाइलों (जैसे सी हेडर और सोर्स फाइल्स) के बीच निर्भरता के लिए स्कैन करता है, जबकि पत्तियां जो मेकफाइल लेखकों को देता है।


4

यदि यह प्रश्न फ़ाइल के एक नमूना Makefileआउटपुट के बारे में है, CMakeList.txtतो कृपया cmake-backend स्रोतों की जाँच करें और एक ऐसा जेनरेट करें Makefile। यदि यह नहीं है तो @Roberto के उत्तर को जोड़कर विवरण को छिपाकर इसे सरल बनाने का प्रयास कर रहा हूं।

सीएमके समारोह

जबकि Makeनियम और नुस्खा के लिए लचीला उपकरण है, CMakeअमूर्त की एक परत है जो कॉन्फ़िगरेशन सुविधा को भी जोड़ता है।

मेरा मैदान CMakeLists.txtनिम्नलिखित की तरह दिखेगा,

cmake_minimum_required(VERSION 2.8)
project(example)
file(GLOB testapp_SOURCES *.cc)
add_executable(testapp ${testapp_SOURCES})

ध्यान दें, कि निर्माण CMakeछुपाता howहै किया जा सकता है। हम केवल निर्दिष्ट whatइनपुट और आउटपुट है।

CMakeLists.txtसमारोह कॉल कि द्वारा परिभाषित कर रहे की सूची होती है cmake

(CMake फ़ंक्शन) बनाम नियम बनाएं

में के बजाय इस्तेमाल कर रहे हैं । -इस तरह की सुविधा के अलावा , चेनिंग प्रदान करते हैं। मेरा न्यूनतर निम्न की तरह दिखेगा,Makefilerules and recipesfunctionsfunctionrules and recipesMakefile

-include "executable.mk"
TARGETS=testapp.bin
all:${TARGETS}

जबकि executable.mkनिम्नलिखित की तरह दिखेगा,

SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)

%.bin:$(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LIBS)

.PHONY: all clean

clean:
    $(RM) $(OBJECTS) $(DEPS) $(TARGETS)

-include $(DEPS)

स्क्रैच से शुरू मैं Makefileनिम्नलिखित की तरह शुरू होगा ,

all: testapp.bin

testapp.bin:sourcea.o sourcb.o
    $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LIBS)

.PHONY: all clean

clean:
    $(RM) $(OBJECTS) testapp.bin

मुझे यह स्निपेट यहीं से मिली और इसे संशोधित किया। ध्यान दें कि इस फ़ाइल में कुछ निहित-नियम जोड़े गए हैं जो मेकफाइल-प्रलेखन में पाए जा सकते हैं। कुछ निहित चर भी यहां प्रासंगिक हैं।

ध्यान दें, कि निर्माण को दिखाते हुए Makefileविवरण प्रदान करता है। एक फाइल में परिभाषित विवरण रखने के लिए लिखना संभव है । उस तरह से मेकफाइल को कम किया जा सकता है जैसा मैंने पहले दिखाया था।recipehowexecutable.mk

में आंतरिक चर CMakeऔरMake

अब थोड़ा उन्नत हो रहा है, CMakeहम निम्नलिखित की तरह एक संकलक ध्वज सेट कर सकते हैं,

set(CMAKE_C_FLAGS "-Wall")

कृपया फ़ाइल में CMakeडिफ़ॉल्ट चर के बारे में अधिक जानकारी प्राप्त करें CMakeCache.txtCMakeउपरोक्त कोड के बराबर होगी Makeनीचे कोड,

CFLAGS = -Wall

ध्यान दें कि CFLAGSएक आंतरिक चर है Make, उसी तरह, CMAKE_C_FLAGSआंतरिक चर हैCMake

जोड़ना और CMake में पुस्तकालय पथ

हम इसे cmakeकार्यों का उपयोग करने में कर सकते हैं ।

target_include_directories(testapp PRIVATE "myincludes")
list(APPEND testapp_LIBRARIES
    mytest mylibrarypath
)
target_link_libraries(testapp ${testapp_LIBRARIES})

बनाम मेक शामिल हैं और मेक में लाइब्रेरी पथ

हम निम्नलिखित की तरह लाइनों को जोड़कर और पुस्तकालयों को जोड़ सकते हैं,

INCLUDES += -Imyincludes
LIBS += -Lmylibrarypath -lmytest

ध्यान दें कि ऊपर दी गई लाइनें ऑटो-जीन टूल या pkg-config से उत्पन्न हो सकती हैं। (हालांकि मेकफाइल ऑटो-कॉन्फिगर टूल्स के लिए निर्भर नहीं है)

CMake कॉन्फिगर / tweek

आम तौर पर फ़ंक्शन का उपयोग करके टूल की config.hतरह कुछ फ़ाइल उत्पन्न करना संभव है । कस्टम फ़ंक्शन लिखना अधिक ट्रिक करना संभव है। और अंत में हम निम्नलिखित की तरह एक विन्यास का चयन कर सकते हैं,auto-configconfigure_file

cmake --build . --config "Release"

optionफ़ंक्शन का उपयोग करके कुछ कॉन्फ़िगर करने योग्य विकल्प जोड़ना संभव है ।

Makefile कॉन्फ़िगर / tweak

अगर किसी तरह हमें इसे कुछ डिबग ध्वज के साथ संकलित करने की आवश्यकता है, तो हम इस makeतरह से आह्वान कर सकते हैं,

make CXXFLAGS=NDEBUG

मुझे लगता है कि आंतरिक चर, Makefile-rulesऔर CMake-functionsतुलना के लिए अच्छी शुरुआत हैं, अधिक खुदाई के साथ अच्छी किस्मत।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.