2013-05-06 6 views
53

निम्नलिखित परिदृश्य की कल्पना करें: प्रोजेक्ट ए एक साझा लाइब्रेरी है जिसमें कई निर्भरताएं हैं (लीबिया, लीबीबी, लिबसी)। प्रोजेक्ट बी एक निष्पादन योग्य है जिस पर प्रोजेक्ट ए पर निर्भरता है, और इसलिए निर्माण के लिए परियोजना ए की निर्भरताओं की भी आवश्यकता है।सीएमके और अन्य परियोजनाओं और उनकी निर्भरताओं को ढूंढना

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

तो सवाल यह है कि, सीएमके का उपयोग करके इन निर्भरताओं को हल करने का सबसे अच्छा तरीका क्या है? आदर्श समाधान जितना संभव हो सके उतना आसान होगा (हालांकि कोई आसान नहीं), और न्यूनतम रखरखाव की आवश्यकता होती है।

+2

भविष्य की समृद्धि के लिए: http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file – blockchaindev

+0

यह ट्यूटोरियल बाहरी लाइब्रेरी निर्भरताओं को निर्यात करने के तरीके को समझाने के लिए प्रतीत नहीं होता है। परियोजना द्वारा निर्मित एकमात्र पुस्तकालय है। मुझे परियोजना बी को बताना है कि प्रोजेक्ट ए को विभिन्न बाहरी पुस्तकालयों की आवश्यकता है और इसलिए उन्हें परियोजना बी –

उत्तर

103

आसान।

शीर्ष स्तर CMakeLists.txt:

components/B में
cmake_minimum_required(VERSION 2.8.10) 

# You can tweak some common (for all subprojects) stuff here. For example: 

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) 
set(CMAKE_DISABLE_SOURCE_CHANGES ON) 

if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") 
    message(SEND_ERROR "In-source builds are not allowed.") 
endif() 

set(CMAKE_VERBOSE_MAKEFILE ON) 
set(CMAKE_COLOR_MAKEFILE ON) 

# Remove 'lib' prefix for shared libraries on Windows 
if (WIN32) 
    set(CMAKE_SHARED_LIBRARY_PREFIX "") 
endif() 

# When done tweaking common stuff, configure the components (subprojects). 
# NOTE: The order matters! The most independent ones should go first. 
add_subdirectory(components/B) # B is a static library (depends on Boost) 
add_subdirectory(components/C) # C is a shared library (depends on B and external XXX) 
add_subdirectory(components/A) # A is a shared library (depends on C and B) 

add_subdirectory(components/Executable) # Executable (depends on A and C) 

CMakeLists.txt:

components/C में
cmake_minimum_required(VERSION 2.8.10) 

project(B C CXX) 

find_package(Boost 
      1.50.0 
      REQUIRED) 

file(GLOB CPP_FILES source/*.cpp) 

include_directories(${Boost_INCLUDE_DIRS}) 

add_library(${PROJECT_NAME} STATIC ${CPP_FILES}) 

# Required on Unix OS family to be able to be linked into shared libraries. 
set_target_properties(${PROJECT_NAME} 
         PROPERTIES POSITION_INDEPENDENT_CODE ON) 

target_link_libraries(${PROJECT_NAME}) 

# Expose B's public includes (including Boost transitively) to other 
# subprojects through cache variable. 
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include 
           ${Boost_INCLUDE_DIRS} 
    CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE) 

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.10) 

project(C C CXX) 

find_package(XXX REQUIRED) 

file(GLOB CPP_FILES source/*.cpp) 

add_definitions(${XXX_DEFINITIONS}) 

# NOTE: Boost's includes are transitively added through B_INCLUDE_DIRS. 
include_directories(${B_INCLUDE_DIRS} 
        ${XXX_INCLUDE_DIRS}) 

add_library(${PROJECT_NAME} SHARED ${CPP_FILES}) 

target_link_libraries(${PROJECT_NAME} B 
             ${XXX_LIBRARIES}) 

# Expose C's definitions (in this case only the ones of XXX transitively) 
# to other subprojects through cache variable. 
set(${PROJECT_NAME}_DEFINITIONS ${XXX_DEFINITIONS} 
    CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE) 

# Expose C's public includes (including the ones of C's dependencies transitively) 
# to other subprojects through cache variable. 
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include 
           ${B_INCLUDE_DIRS} 
           ${XXX_INCLUDE_DIRS} 
    CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE) 

यहाँ मेरे सिर के ऊपर से उदाहरण हैcomponents/A में:

components/Executable में
cmake_minimum_required(VERSION 2.8.10) 

project(A C CXX) 

file(GLOB CPP_FILES source/*.cpp) 

# XXX's definitions are transitively added through C_DEFINITIONS. 
add_definitions(${C_DEFINITIONS}) 

# NOTE: B's and Boost's includes are transitively added through C_INCLUDE_DIRS. 
include_directories(${C_INCLUDE_DIRS}) 

add_library(${PROJECT_NAME} SHARED ${CPP_FILES}) 

# You could need `${XXX_LIBRARIES}` here too, in case if the dependency 
# of A on C is not purely transitive in terms of XXX, but A explicitly requires 
# some additional symbols from XXX. However, in this example, I assumed that 
# this is not the case, therefore A is only linked against B and C. 
target_link_libraries(${PROJECT_NAME} B 
             C) 

# Expose A's definitions (in this case only the ones of C transitively) 
# to other subprojects through cache variable. 
set(${PROJECT_NAME}_DEFINITIONS ${C_DEFINITIONS} 
    CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE) 

# Expose A's public includes (including the ones of A's dependencies 
# transitively) to other subprojects through cache variable. 
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include 
           ${C_INCLUDE_DIRS} 
    CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE) 

CMakeLists.txt:

Root of the project 
├───components 
│ ├───Executable 
│ │ ├───resource 
│ │ │ └───icons 
│ │ ├───source 
| | └───CMakeLists.txt 
│ ├───A 
│ │ ├───include 
│ │ │ └───A 
│ │ ├───source 
| | └───CMakeLists.txt 
│ ├───B 
│ │ ├───include 
│ │ │ └───B 
│ │ ├───source 
| | └───CMakeLists.txt 
│ └───C 
│  ├───include 
│  │ └───C 
│  ├───source 
|  └───CMakeLists.txt 
└───CMakeLists.txt 

कई बिंदुओं जहां हैं:

cmake_minimum_required(VERSION 2.8.10) 

project(Executable C CXX) 

file(GLOB CPP_FILES source/*.cpp) 

add_definitions(${A_DEFINITIONS}) 

include_directories(${A_INCLUDE_DIRS}) 

add_executable(${PROJECT_NAME} ${CPP_FILES}) 

target_link_libraries(${PROJECT_NAME} A C) 

यह स्पष्ट करने के लिए यहां इसी स्रोत वृक्ष संरचना है यह कुछ ne को संतुष्ट करने के लिए tweaked/अनुकूलित या बदला जा सकता है eds, लेकिन यह कम से कम आप शुरू करना चाहिए।

नोट: मैंने इस ढांचे को कई मध्यम आकार और बड़ी परियोजनाओं में सफलतापूर्वक नियोजित किया है।

+11

के लिंकिंग चरण में जोड़ने की जरूरत है। आप एक एफ **** स्टार हैं! तुमने मुझे वास्तव में एक बड़े सिरदर्द से बाहर निकाला जो लगभग एक दिन तक चला। बहुत बहुत धन्यवाद 1 – rsacchettini

+1

मैं उत्सुक हूं, अगर मैं "निष्पादन योग्य" निर्देशिका से सीमेक का आह्वान करना चाहता हूं तो यह संकलित होगा; या मुझे हर समय परियोजना की जड़ से संकलित करना चाहिए? –

+1

मुझे लगता है कि इसमें प्रत्येक छोटी प्रोजेक्ट में परिभाषित छोटी कमी होती है जिसमें निर्देशिका दो बार शामिल होती है (एक बार 'सेट (... INCLUDE_DIRS' और' include_directories() 'के लिए), जिसे मुझे बनाए रखने में कठिनाई होती है (हमेशा याद रखना * दो * स्थानों में निर्भरता शामिल करें)। आप उन्हें 'get_property (... संपत्ति INCLUDE_DIRECTORIES)' – pseyfert

संबंधित मुद्दे