CMake: इकाई परीक्षणों के साथ परियोजना संरचना


139

मैं उत्पादन स्रोतों ( srcसबफ़ोल्डर में) और परीक्षणों (सबफ़ोल्डर में) को शामिल करने के लिए अपनी परियोजना की संरचना करने की कोशिश कर रहा हूं test। मैं इसे बनाने के लिए CMake का उपयोग कर रहा हूं। एक न्यूनतम उदाहरण के रूप में मेरे पास निम्नलिखित फाइलें हैं:

CMakeLists.txt:

cmake_minimum_required (VERSION 2.8) 
project (TEST) 

add_subdirectory (src) 
add_subdirectory (test) 

src / CMakeLists.txt:

add_executable (demo main.cpp sqr.cpp) 

src / sqr.h

#ifndef SQR_H
#define SQR_H
double sqr(double);    
#endif // SQR_H

src / sqr.cpp

#include "sqr.h"
double sqr(double x) { return x*x; }

src / main.cpp - वास्तव में कोई फर्क नहीं पड़ता, sqr का उपयोग करता है

परीक्षा / CMakeLists.txt:

find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)

include_directories (${TEST_SOURCE_DIR}/src) 

ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) 

add_executable (test test.cpp ${TEST_SOURCE_DIR}/src/sqr.cpp) 

target_link_libraries(test
                      ${Boost_FILESYSTEM_LIBRARY}
                      ${Boost_SYSTEM_LIBRARY}
                      ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                      )

enable_testing()
add_test(MyTest test)

परीक्षा / test.cpp:

#define BOOST_TEST_MODULE SqrTests
#include <boost/test/unit_test.hpp>

#include "sqr.h"

BOOST_AUTO_TEST_CASE(FailTest)
{
    BOOST_CHECK_EQUAL(5, sqr(2));
}

BOOST_AUTO_TEST_CASE(PassTest)
{
    BOOST_CHECK_EQUAL(4, sqr(2));
}

कुछ प्रश्न:

  1. क्या यह संरचना समझ में आती है? इस कोड को संरचित करते समय सर्वोत्तम अभ्यास क्या हैं? (मैं C # और जावा से आ रहा हूँ, और वहाँ एक अर्थ में आसान है)
  2. मुझे इस तथ्य को पसंद नहीं है कि मुझे फ़ाइल srcमें फ़ोल्डर से सभी फ़ाइलों को सूचीबद्ध करना test/CMakeLists.txtहै। यदि यह एक पुस्तकालय परियोजना थी, तो मैं सिर्फ पुस्तकालय को लिंक करूंगा। क्या अन्य परियोजना से सभी सीपीपी फ़ाइलों को सूचीबद्ध करने से बचने का कोई तरीका है?
  3. रेखाएँ enable_testing()और add_test(MyTest test)क्या कर रही हैं? मैंने कोई प्रभाव नहीं देखा। मैं CMake (या CTest) से परीक्षण कैसे चला सकता हूं?
  4. अभी तक मैं सिर्फ cmake .रूट फ़ोल्डर में भागता था, लेकिन इसने हर जगह अस्थायी फ़ाइलों के साथ एक गड़बड़ पैदा कर दी। मैं एक उचित संरचना में संकलन परिणाम कैसे प्राप्त कर सकता हूं?

मैं खुद को एक सीएमके नौसिखिया मानता हूं, इसलिए मुझे नहीं पता कि स्वीकृत सर्वोत्तम प्रथाएं क्या हैं, लेकिन एफडब्ल्यूआईडब्ल्यू मैं एक "वर्ग" पुस्तकालय * बनाऊंगा, जो मुख्य और परीक्षण दोनों पर निर्भर था। (* या नैतिक समतुल्य)
user786653

जवाबों:


125

प्रश्न 1 और 2 के लिए, मैं आपके गैर-परीक्षण फ़ाइलों से main.cpp (इस मामले में सिर्फ src / sqr.cpp और src / sqr.h को छोड़कर) को लाइब्रेरी बनाने की सलाह दूंगा, और तब आप लिस्टिंग से बच सकते हैं (और अधिक महत्वपूर्ण बात) पुन: संकलन) सभी स्रोतों को दो बार।

प्रश्न 3 के लिए, ये आदेश "MyTest" नामक एक परीक्षण जोड़ते हैं जो बिना किसी तर्क के आपके निष्पादन योग्य "परीक्षण" को आमंत्रित करता है। हालाँकि, चूंकि आपने इन आदेशों को परीक्षण / CMakeLists.txt में जोड़ा है, न कि आपके शीर्ष-स्तरीय CMakeLists.txt पर, आप केवल अपने बिल्ड ट्री (प्रयास cd test && ctest -N) के "परीक्षण" उपनिर्देशिका के भीतर से परीक्षण को आमंत्रित कर सकते हैं । यदि आप चाहते हैं कि परीक्षण आपके शीर्ष-स्तरीय बिल्ड निर्देशिका add_testसे रन करने योग्य हो, तो आपको शीर्ष-स्तरीय CMakeLL.txt से कॉल करना होगा । इसका मतलब यह भी है कि आपको अधिक वर्बोज़ फॉर्म का उपयोग करना होगा add_testक्योंकि आपके टेस्ट एक्ज़ को समान CMakeLists.txt में परिभाषित नहीं किया गया है

आपके मामले में, जब से आप रूट फ़ोल्डर में cmake चला रहे हैं, आपका बिल्ड ट्री और आपका सोर्स ट्री एक ही हैं। इसे इन-सोर्स बिल्ड के रूप में जाना जाता है और यह आदर्श नहीं है, जो प्रश्न 4 की ओर जाता है।

बिल्ड ट्री को जेनरेट करने के लिए पसंदीदा तरीका है, आउट-ऑफ-सोर्स बिल्ड करना, यानी अपने सोर्स ट्री के बाहर कहीं एक डायरेक्टरी बनाना और वहां से cmake को एक्जिक्यूट करना। यहां तक ​​कि आपकी परियोजना की जड़ में एक "बिल्ड" निर्देशिका बनाने और निष्पादित cmake ..करने से एक स्वच्छ संरचना प्रदान होगी जो आपके स्रोत के पेड़ के साथ हस्तक्षेप नहीं करेगी।

एक अंतिम बिंदु निष्पादन योग्य "परीक्षण" (केस-संवेदी) को कॉल करने से बचने के लिए है। कारणों के लिए, यह उत्तर देखें ।

इन परिवर्तनों को प्राप्त करने के लिए, मैं निम्नलिखित कार्य करूंगा:

CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src) 
add_subdirectory (test)
enable_testing ()
add_test (NAME MyTest COMMAND Test)


src / CMakeLists.txt:

add_library (Sqr sqr.cpp sqr.h)
add_executable (demo main.cpp)
target_link_libraries (demo Sqr)


परीक्षा / CMakeLists.txt:

find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src
                     ${Boost_INCLUDE_DIRS}
                     )
add_definitions (-DBOOST_TEST_DYN_LINK)
add_executable (Test test.cpp)
target_link_libraries (Test
                       Sqr
                       ${Boost_FILESYSTEM_LIBRARY}
                       ${Boost_SYSTEM_LIBRARY}
                       ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                       )

2
मैंने अभी देखा है कि आपने भी .h फ़ाइलों को CMakeLists.txt फ़ाइलों के अनुसार जोड़ा है। क्या इसकी आवश्यकता है? और अगर मैं उन्हें छोड़ दूं तो क्या होगा?
ग्रेजेनियो

3
@Grzenio यह सिर्फ एक सुविधा सुविधा है - वे लक्ष्य के हिस्से के रूप में IDE के MSVC की तरह दिखाई देते हैं, लेकिन अन्यथा इसका कोई प्रभाव नहीं होता है।
फ्रेजर

1
TEST_SOURCE_DIR कहां सेट है?
aggsol

6
कॉल करते समय यह स्वचालित रूप से CMake द्वारा सेट किया गया है project (TEST)- cmake.org/cmake/help/v3.6/variable/PROJECT-NAME_SOURCE_DIR.html
फ्रेजर

> वे लक्ष्य के हिस्से के रूप में IDE की तरह IDE में दिखाई देते हैं --- MSVC हेडर के साथ निर्देशिका को चिह्नित करने का समर्थन नहीं करता है क्योंकि "निर्देशिका शामिल है"?
isnullxbh

46

मुझे @Fraser का उदाहरण पसंद है लेकिन टेस्ट / CMakeLists.txt में add_test कमांड का उपयोग करेगा और add_subdirectory (परीक्षण) से पहले enable_testing का उपयोग करेगा।

इस तरह से आप परीक्षण / CMakeLists.txt में अपने परीक्षणों को निर्दिष्ट करते हुए शीर्ष-स्तरीय बिल्ड निर्देशिका से अपने परीक्षण चला सकते हैं।

परिणाम इस तरह दिखाई देगा (मैंने @Fraser के उदाहरण का पुन: उपयोग किया):

CMakeLists.txt

cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src)

enable_testing ()
add_subdirectory (test)

src / CMakeLists.txt

add_library (Sqr sqr.cpp sqr.h)
add_executable (demo main.cpp)
target_link_libraries (demo Sqr)

परीक्षा / CMakeLists.txt

find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src
                     ${Boost_INCLUDE_DIRS}
                     )
add_definitions (-DBOOST_TEST_DYN_LINK)
add_executable (Test test.cpp)
target_link_libraries (Test
                       Sqr
                       ${Boost_FILESYSTEM_LIBRARY}
                       ${Boost_SYSTEM_LIBRARY}
                       ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                       )
add_test (NAME MyTest COMMAND Test)

1
धन्यवाद, मैंने ctest -Nउपडिर जोड़ने से पहले परीक्षण को सक्षम करने के बारे में आपकी टिप तक कोई परीक्षण नहीं दिखाया ।
अलफैग

@ लाफर्ग: वे अन्यथा बिल्ड डायर के अंदर परीक्षण उपखंड में समाप्त हो जाएंगे।
14

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