2015-06-22 11 views
8

मैं PROJECTA है, जिसमें मैं के साथ एक पुस्तकालय का आयात कर रहा हूँ निर्यात:एक आयातित पुस्तकालय

add_library(foo STATIC IMPORTED) 
set_property(TARGET foo PROPERTY IMPORTED_LOCATION /path/to/foo.a) 

मैं तो foo कई स्थानों पर परियोजना के भीतर उपयोग करते हैं, और यह सब ठीक काम करता है।

कुछ निर्देशिका स्तर नीचे मैं इस प्रोजेक्ट के भीतर बनाई गई लाइब्रेरी को पूरी तरह से डिस्कनेक्ट किए गए सीएमके कॉन्फ़िगर के साथ एक और प्रोजेक्ट में उपयोग के लिए निर्यात करना चाहता हूं। मुझे मिल गया है:

... 
target_link_libraries(thislib foo) 
export(TARGETS thislib FILE /path/to/thislib.cmake) 

आयात करने projectB भी हालांकि foo की जरूरत है (क्योंकि आयातित पुस्तकालय इसकी आवश्यकता है), और शिकायत है कि यह cannot find -lfoo। मैं export आदेश में जोड़ने की कोशिश की, लेकिन फिर मैं मिलता है:

CMake Error at thislib/CMakeLists.txt:37 (export): 
    export given target "foo" which is not built by this project. 

मैं सिर्फ एक ही विन्यास मैं अन्य (आयात करने) परियोजना के लिए स्थानीय स्तर पर उपयोग करने के निर्यात करना चाहते हैं। मैं प्रोजेक्ट बी को स्पष्ट रूप से foo के बारे में बताना नहीं चाहता हूं। क्या इसे पूरा करने का कोई तरीका है?

उत्तर

1

मुझे बताए गए समस्या के लिए एक वास्तविक समाधान नहीं मिला, लेकिन भविष्य के संदर्भ के लिए अपना खुद का कामकाज पोस्ट कर रहा हूं।

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

तो मैं वापस मूल जगह है जहाँ foo आयात किया जा रहा था के पास गया और add_library और set_property हटा दिया, उन्हें इस के साथ की जगह: में

target_link_libraries(thislib ${foo}) 

:

set(foo /path/to/foo.a) 

फिर target_link_libraries करने के लिए बदल अन्य शब्द, इसे वास्तविक "आयातित लाइब्रेरी" बनाने के बजाय, यह सिर्फ एक कच्चा पुस्तकालय पथ है। यह निर्यात फ़ाइल में सही ढंग से लिखा जाता है और प्रोजेक्टबी को लिंक करने की अनुमति देता है।

+1

इसके साथ एक समस्या यह है कि यह आपको INTERFACE_INCLUDE_DIRECTORIES – RiaD

0

आप

  1. निर्यात foo जहां यह बनाया गया है से (करने के लिए, कहते हैं, foolibs.cmake)
  2. इसके बजाय /path/to/thislib.cmake सीधे का उपयोग कर (निर्यात export(TARGETS thislib... द्वारा उत्पन्न फ़ाइल दूसरा बनाने के की

    , thislib-and-deps.cmake जिसमें शामिल करने की जरूरत है दोनों:

    include(<...>/foolibs.cmake) 
    include(${CMAKE_CURRENT_LIST_DIR}/thislib.cmake) 
    
+0

जैसे लक्षित गुण सेट करने की अनुमति नहीं देता है क्या प्रति परियोजना के बहुत से सीएमके कोड को लागू किए बिना इसे पुन: प्रयोज्य तरीके से कार्यान्वित करने के लिए एक आसान समाधान मौजूद है? यह * सीएमके-रास्ता-टू-जाने * प्रतीत नहीं होता है। वर्तमान में मैं प्रत्येक ट्रांजिटिव निर्भरता के लिए 'find_package ( CONFIG)' कॉल दोहराता हूं, जो भी बेकार है, क्योंकि यह ट्रांजिटिव निर्भरताओं की अवधारणा को तोड़ देता है। –

0

मुझे यह करने का एक आदर्श तरीका भी नहीं मिल रहा है। लेकिन यहां वह कामकाज है जिसका मैं अभी उपयोग कर रहा हूं। यह अतिरिक्त काम है, और DRY नहीं, लेकिन मुझे लगता है कि यह सही चीज़ प्राप्त करता है।

कल्पना कीजिए B तीसरे पक्ष के lib A पर निर्भर करता है। A या तो एक खोज मॉड्यूल परिभाषित किया गया है, या हम इसके लिए एक कस्टम खोज मॉड्यूल लागू कर सकते हैं। दोनों काम करने योग्य हैं। मान लें कि हमने पहले ही FindA.cmake लिखा है और ${CMAKE_SOURCE_DIR}/cmake में संग्रहीत किया है।साथ ही, मान लीजिए कि जब आप B की बिल्ड सिस्टम उत्पन्न करने के लिए cmake चलाते हैं, तो आप A_ROOT प्रदान करते हैं ताकि cmake A का पता लगाने में सहायता मिल सके।

फिर बी के शीर्ष स्तरीय CMakeLists.txt में हम की जरूरत है:

# Use FindA.cmake, defined in the cmake/ directory. 
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 
find_package(A REQUIRED) 

# ... (define the B target here)... 

# Copy the config file to the build dir 
configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY) 

# Copy A's find module (skip this step if FindA is not custom). 
configure_file(cmake/FindA.cmake cmake/FindA.cmake COPYONLY) 

# Create the target export. 
export(EXPORT BTargets 
    FILE ${CMAKE_BINARY_DIR}/cmake/BTargets.cmake 
    NAMESPACE B:: 
    ) 

# Register B so cmake can find B's config file. 
export(PACKAGE B) 

अब cmake/BConfig.cmake में:

# Get the exported find module onto the module path. 
# This step is unnecessary if the find module is part of cmake. 
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 

# Store the root so that find_package will work. 
# You may have to store other variables here, too, but 
# the principle is just more of the same. 
set(A_ROOT @[email protected]) # **Could optionally cache this. 
find_package(A MODULE REQUIRED) 

# The usual one-liner for a config file. 
include("${CMAKE_CURRENT_LIST_DIR}/BTargets.cmake") 

बस समाधान घर ड्राइव करने के लिए, का उपयोग करते हुए, चलो एक दूसरे उदाहरण देखते हैं Rocket इस समय Boost, जो पहले से ही एक खोज मॉड्यूल परिभाषित किया गया है।

CMakeLists.txt:

option(Boost_USE_MULTITHREADED ON) 
option(Boost_USE_STATIC_LIBS OFF) 
find_package(Boost REQUIRED COMPONENTS filesystem program_options) 

add_library(Rocket rocket.cpp) 
target_link_libraries(Rocket 
    PUBLIC Boost::filesystem 
    PRIVATE Boost::program_options 
    ) 

configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY) 

export(EXPORT RocketTargets 
    FILE ${CMAKE_BINARY_DIR}/RocketTargets.cmake 
    NAMESPACE Rocket:: 
    ) 
export(PACKAGE Rocket) 

फिर cmake/RocketConfig.cmake होगा:

set(BOOST_ROOT @[email protected] CACHE PATH "In case boost was relocated.") 
set(Boost_USE_MULTITHREADED @[email protected]) 
set(Boost_USE_STATIC LIBS @[email protected]) 
find_package(Boost REQUIRED COMPONENTS filesystem program_options) 

include("${CMAKE_CURRENT_LIST_DIR}/RocketTargets.cmake") 

तो, हाँ। ऐसा लगता है कि बहुत ज्यादा टाइपिंग है। ऐसा लगता है कि सेमेक कथन से CMakeLists.txt में उस कोड को उत्पन्न करने में सक्षम होना चाहिए। लेकिन यह रणनीति लक्ष्य हासिल करने के लिए प्रतीत होती है।

इसके अलावा, मैं अभी तक परीक्षण नहीं किया है, लेकिन मुझे लगता है कि, अपने सकर्मक निर्भरता एक CONFIG बजाय find_package के लिए MODULE एक के उपयोग करता है, यह सिर्फ रूप में अच्छी तरह से अपने कॉन्फ़िग फ़ाइल में CMAKE_PREFIX_PATH में जोड़ने के लिए बहुत आसान होना चाहिए।

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