सीएमके साथ निर्देशिकाओं को ठीक से कैसे जोड़ें


243

लगभग एक साल पहले मैंने सीएमके में हेडर निर्भरता के बारे में पूछा था ।

मुझे हाल ही में एहसास हुआ कि यह मुद्दा ऐसा लग रहा था कि सीएमके ने उन हेडर फाइलों को परियोजना के लिए बाहरी माना है । कोड उत्पन्न करते समय कम से कम :: ब्लॉक परियोजनाएं हेडर फाइलें परियोजना के भीतर दिखाई नहीं देती हैं (स्रोत फाइलें करते हैं)। इसलिए मुझे लगता है कि सीएमके उन हेडर को परियोजना के लिए बाहरी मानते हैं , और उन्हें निर्भरता में ट्रैक नहीं करते हैं।

सीएमके ट्यूटोरियल में एक त्वरित खोज केवल यह इंगित include_directoriesकरती है कि मैं जो चाहता हूं वह नहीं करता है ...

सीएमके को संकेत देने का उचित तरीका क्या है कि किसी विशेष निर्देशिका में हेडर शामिल किया जाना है, और यह कि हेडर को उत्पन्न मेकफाइल द्वारा ट्रैक किया जाना चाहिए?


इस प्रश्न के लिए किए गए संपादन इसे भ्रमित करते हैं। मूल प्रश्न और उत्तर एक आईडीई में हेडर फ़ाइलों को ट्रैक करने के तरीके थे। यह एक जनरेटेड मेकफाइल लापता हेडर फ़ाइल निर्भरता और उस समस्या को हल करने के तरीके से काफी भिन्न है।
fdk1342

@ फ़्रेड: मुझे नहीं पता कि आप किस बारे में बात कर रहे हैं। जैसा कि संपादन संशोधन स्पष्ट रूप से दिखाता है, अंतिम वाक्य हमेशा रहा है। इस प्रश्न पर केवल कॉस्मेटिक संपादन किए गए थे, और कोई शब्द पेश नहीं किया गया था (या हटा दिया गया था)।
मथिउ एम।

फिर वही मेरी गलतफहमी है। यह मुझे पसंद आया एक संपूर्ण पैराग्राफ जोड़ा गया था। stackoverflow.com/questions/13703647/… आम समझ यह है कि आईडीई में हेडर फ़ाइल को कैसे सूचीबद्ध किया जाए। यह .cbpप्रोजेक्ट फ़ाइल की बात कर रहा होगा । अब अगर cmake डिपेंडेंसी स्कैनर हेडफाइल फाइल को सही ढंग से पहचानने में विफल रहता है, तो मेकफाइल के लिए एक निर्भरता के रूप में इसे ठीक करने के तरीके हैं, लेकिन कुछ मामलों में यह गलत हो जाएगा क्योंकि इसमें पूर्ण प्रीप्रोसेसर शामिल नहीं है।
fdk1342

जवाबों:


267

दो काम करने होंगे।

सबसे पहले निर्देशिका को शामिल करें:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

यदि आप समर्थन के बिना बहुत पुराने सीएमके संस्करण (2.8.10 या पुराने) के साथ फंस गए हैं target_include_directories, तो आप include_directoriesइसके बजाय विरासत का उपयोग कर सकते हैं :

include_directories(${YOUR_DIRECTORY})

फिर आपको वर्तमान लक्ष्य के लिए अपनी स्रोत फ़ाइलों की सूची में हेडर फ़ाइलों को भी जोड़ना होगा, उदाहरण के लिए:

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

इस तरह, हेडफ़्लेक फाइलें मेकफाइल में निर्भरता के रूप में दिखाई देंगी, और उदाहरण के लिए उत्पन्न विज़ुअल स्टूडियो प्रोजेक्ट में, यदि आप एक उत्पन्न करते हैं।

कई लक्ष्यों के लिए उन हेडर फ़ाइलों का उपयोग कैसे करें:

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

आह! मुझे पता था कि यह कुछ बेवकूफ होना चाहिए। वास्तव में, मैंने हेडरों को सूचीबद्ध नहीं किया है ... क्या मुझे सिर्फ इस लाइब्रेरी के हेडर, या सभी हेडर सूचीबद्ध करने की आवश्यकता है जो कि यह निर्भर हो सकता है (लाइब्रेरी पर निर्भरता घोषित करने के शीर्ष पर)? यह एक बढ़ती हुई परियोजना है और रूट लाइब्रेरी में एक जोड़ने पर सभी आश्रितों के लिए एक हेडर जोड़ने के विचार को मैं काफी भयभीत करता हूं।
Matthieu M.

बेहतर निर्भरता ट्रैकिंग के लिए अनुमति देने के लिए (उदाहरण के लिए सभी प्रभावित लक्ष्यों के लिए हेडर फ़ाइल ट्रिगर संकलन सुनिश्चित करने के लिए उदाहरण के लिए), हाँ। हालाँकि आप केवल एक बार हेडर फ़ाइलों को सूचीबद्ध करने और उन्हें कई स्थानों पर उपयोग करने के लिए cmake चरों का उपयोग कर सकते हैं, मेरा संपादन देखें।
सिराद्रईस

1
मेरा प्रश्न इस अर्थ में अधिक था कि मेरे पास कई पुस्तकालय हैं जो एक-दूसरे से निर्भर हैं: लिबरोट, लिबा कामेच्छा पर निर्भर करता है, लिबास लिबेरोट पर निर्भर करता है। क्या मैं LIBROOT_HEADER_FILESचर का उपयोग कर सकता हूं liba/CMakefileऔर libb/CMakefileफिर?
Matthieu M.

2
यह गलत है, तो आप चाहिए कभी नहीं का उपयोग include_directoriesअधिक target_include_directories। पूर्व उस निर्देशिका में सभी लक्ष्यों के लिए पुनरावर्ती सेट करता है; जबकि उत्तरार्द्ध इसे एक लक्ष्य के लिए निर्धारित करता है। पूर्व करना सीएमके में एक लक्ष्य ग्राफ की धारणा को तोड़ता है, और इसके बजाय आपकी फ़ाइल पदानुक्रम के दुष्प्रभावों पर निर्भर करता है।
एंडी

1
मैंने target_include_directoriesआधुनिक सीएमके कोड के लिए पसंद करने की वर्तमान धारणा को प्रतिबिंबित करने के लिए उत्तर को संपादित किया । यदि आप परिवर्तनों से असहमत हैं, तो मुझे एक चैट में आमंत्रित करने के लिए स्वतंत्र महसूस करें।
कॉमिक्ससंस

74

सबसे पहले, आप संकलन कमांड लाइन के include_directories()रूप में निर्देशिका को जोड़ने के लिए सीएमके को बताने के लिए उपयोग करते हैं -I। दूसरा, आप अपने add_executable()या add_library()कॉल में हेडरों को सूचीबद्ध करते हैं ।

एक उदाहरण के रूप में, यदि आपके प्रोजेक्ट के स्रोत हैं src, और आपको हेडर की आवश्यकता है include, तो आप इसे इस तरह से कर सकते हैं:

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)

19
क्या आपको वास्तव में हेडर जोड़ने की आवश्यकता है add_executable? मैंने सोचा कि सीएमके में फ़ाइल निर्भरता को स्वचालित रूप से शामिल किया गया है।
कॉलिन डी बेनेट

57
@ColinDBennett आपको निर्भरता कारणों के लिए उन्हें सूचीबद्ध करने की आवश्यकता नहीं है - यदि आप नहीं करते हैं तो सीएमके आंकड़े निर्भरता को ठीक करते हैं। लेकिन अगर आप उन्हें सूचीबद्ध करते हैं, तो उन्हें परियोजना का हिस्सा माना जाता है, और इसे आईडीई में सूचीबद्ध किया जाएगा (जो प्रश्न का विषय था)।
एंग्यू को अब

कम से कम QtCreator के लिए यह आवश्यक नहीं है कि class.h को जोड़ दिया जाए क्योंकि class.cpp मौजूद है। केवल स्रोत के लिए अकेला जोड़ा जाना चाहिए। Www.th-thielemann.de/cmake
Th

19

सीएमके स्क्रिप्ट भाषा की तरह अधिक है अगर इसे मेकफाइल बनाने के अन्य तरीकों (जैसे मेक या क्यूमेक) के साथ तुलना की जाए। यह अजगर की तरह बहुत शांत नहीं है, लेकिन फिर भी।

विभिन्न ओपनसोर्स परियोजनाओं में यदि लोग निर्देशिकाओं को शामिल करते हैं, तो " उचित तरीके " जैसी कोई चीज नहीं है । लेकिन इसे करने के दो तरीके हैं।

  1. क्रूड शामिल__निर्देशिका वर्तमान परियोजना के लिए एक निर्देशिका और अन्य सभी वंशज परियोजनाओं को जोड़ देगा, जिन्हें आप add_subdirectory आदेशों की एक श्रृंखला के माध्यम से जोड़ देंगे । कभी-कभी लोग कहते हैं कि ऐसा दृष्टिकोण विरासत है।

  2. एक अधिक सुंदर तरीका target_include_directories के साथ है । यह एक विशिष्ट परियोजना / लक्ष्य के लिए एक निर्देशिका को संलग्न करने की अनुमति देता है (हो सकता है) अनावश्यक विरासत या विभिन्न शामिल निर्देशिकाओं के टकराव के बिना। इसके अलावा एक सूक्ष्म विन्यास भी करने की अनुमति दें और इस कमांड के लिए निम्न मार्करों में से एक को जोड़ दें।

निजीकृत - केवल इस निर्दिष्ट निर्माण लक्ष्य के लिए उपयोग करें

सार्वजनिक - निर्दिष्ट लक्ष्य के लिए और इस परियोजना के साथ लिंक करने वाले लक्ष्यों के लिए इसका उपयोग करें

INTERFACE - इसका उपयोग केवल उन लक्ष्यों के लिए करें जो वर्तमान प्रोजेक्ट के साथ लिंक करते हैं

पुनश्च:

  1. दोनों कमांड एक संकेत देने के लिए सिस्टम के रूप में एक निर्देशिका को चिह्नित करने की अनुमति देते हैं कि यह आपका व्यवसाय नहीं है कि निर्दिष्ट निर्देशिकाओं में चेतावनी शामिल होगी।

  2. इसी तरह का उत्तर कमांड के अन्य जोड़ों के साथ है target_compile_definitions / add_definitions , target_compile_options / CMAKE_C_FLAGS


13

जोड़ें include_directories("/your/path/here")

यह विकल्प के gccसाथ कॉलिंग के समान होगा -I/your/path/here/

सुनिश्चित करें कि आपने पथ के चारों ओर दोहरे उद्धरण लगाए हैं। अन्य लोगों ने इसका उल्लेख नहीं किया और इसने मुझे 2 दिनों के लिए रोक दिया। तो यह जवाब उन लोगों के लिए है जो सीएमके लिए बहुत नए हैं और बहुत भ्रमित हैं।


7

मुझे भी यही समस्या थी।

मेरी परियोजना निर्देशिका इस प्रकार थी:

    --project
    ---Classes
    ----Application
    -----.h and .c files
    ----OtherFolders
    --main.cpp

और क्या मैं उन सभी फ़ोल्डरों में फ़ाइलों को शामिल करता था:

    file(GLOB source_files
            "*.h"
            "*.cpp"
            "Classes/*/*.cpp"
            "Classes/*/*.h"
    )

    add_executable(Server ${source_files})

और यह पूरी तरह से काम किया।


यह याद रखना कि cmake एक 'बिल्ड सिस्टम जनरेटर' है, न कि फाइल ग्लोब का उपयोग करने वाला 'बिल्ड सिस्टम', आधुनिक cmake (संस्करणों 3.0 और उससे अधिक वाले CMake) में एक अच्छा विचार नहीं है, क्योंकि फ़ाइल ग्लब्स का मूल्यांकन 'बिल्ड' समय पर किया जाता है और बिल्ड नहीं सिस्टम जनरेशन का समय। लिंक देखें: gist.github.com/mbinna/c61db39bca0e4fb7d1f73b0d66a4fd1
ggulgulia
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.