আপনার যদি যাইহোক CMAKE_MODULE_PATH নির্দিষ্ট করার দরকার হয় তবে Find_package () কী ব্যবহার?


167

আমি সিএমকে ব্যবহার করে ক্রস-প্ল্যাটফর্ম বিল্ড সিস্টেমটি কাজ করার চেষ্টা করছি। এখন সফ্টওয়্যারটির কয়েকটি নির্ভরতা রয়েছে। আমি সেগুলি নিজেই সংকলন করেছি এবং এগুলি আমার সিস্টেমে ইনস্টল করেছি।

ইনস্টল হওয়া কয়েকটি উদাহরণ ফাইল:

-- Installing: /usr/local/share/SomeLib/SomeDir/somefile
-- Installing: /usr/local/share/SomeLib/SomeDir/someotherfile
-- Installing: /usr/local/lib/SomeLib/somesharedlibrary
-- Installing: /usr/local/lib/SomeLib/cmake/FindSomeLib.cmake
-- Installing: /usr/local/lib/SomeLib/cmake/HelperFile.cmake

এখন সিএমকে find_package()একটি Find*.cmakeফাইল খোলে এবং সিস্টেমে লাইব্রেরির পরে অনুসন্ধান করে এবং কিছু ভেরিয়েবল SomeLib_FOUNDইত্যাদি সংজ্ঞায়িত করে etc.

আমার সিএমকেলিস্ট.টেক্সটে এমন কিছু রয়েছে:

set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)

প্রথম কমান্ডটি নির্ধারণ করে যেখানে সিএমকে অনুসন্ধানের পরে কোথায় অনুসন্ধান করবে Find*.cmakeএবং আমি SomeLibকোথায় FindSomeLib.cmakeপাওয়া যাবে সেই ডিরেক্টরিটি যুক্ত করেছি , সুতরাং find_package()প্রত্যাশার মতো কাজ করে।

তবে এটি এক ধরণের অদ্ভুত কারণ কারণ find_package()বিদ্যমান থাকার অন্যতম কারণ হ'ল নন-ক্রস-প্লাটফর্ম হার্ড কোডিং পথ থেকে দূরে চলে যাওয়া।

এটি সাধারণত কীভাবে হয়? আমি কি আমার প্রকল্পের cmake/ডিরেক্টরিটি অনুলিপি SomeLibকরে CMAKE_MODULE_PATHতুলনামূলকভাবে সেট করব ?


এই নিদর্শনটি আমার কাছে খুব অদ্ভুত বলে মনে হচ্ছে। সিএমকে ব্যবহার করে গ্রন্থাগারগুলি তাদের 'সন্ধান' মডিউলটি এভাবে প্রকাশ করার কথা নয়। কীভাবে আপনি এই "সামারলিব" সন্ধানের উপায় নিয়ে এসেছিলেন? এবং এটি কোন lib হয়?
স্যারডিয়ারিয়াস

2
অনুরূপ কিছু cmake.org/Wiki/… তে করা হয় । এবং এটি ওজিআরই।
মারকডিফিয়ান্ট

2
আপনি যে বিভাগটি সংযুক্ত করেছেন এটি এতে উল্লেখ করেছে: "যেহেতু সিএমকে (বর্তমানে) এটি পাঠায় না, আপনাকে এটি আপনার প্রকল্পের মধ্যে পাঠাতে হবে।" এটিই আমি লিবিওয়াইএমএল সন্ধানের জন্য ফ্ল্ভমেটাতে করেছি ( github.com/noirotm/flvmeta/tree/master/cmake/modules দেখুন )। আমার প্রকল্পের ভিতরে মডিউলটির পথটি এই ডিরেক্টরিতে নির্দেশ করে।
স্যারডিয়ারিয়াস

3
আমি সাধারণত আমার প্রোজেক্ট এবং সেট CMAKE_MODULE_PATH করার FindXXX মডিউল কপি (যদি মডিউলের অবশ্যই CMake নেই বর্তমান) আমিও এই প্যাটার্ন অনেকবার অন্যান্য প্রকল্পে দেখা করেছি
szx

উত্তর:


213

কমান্ডের find_packageদুটি মোড রয়েছে: Moduleমোড এবং Configমোড। আপনি Moduleযখন Configমোডটি প্রয়োজন তখন আপনি মোডটি ব্যবহার করার চেষ্টা করছেন ।

মডিউল মোড

Find<package>.cmakeআপনার প্রকল্পের মধ্যে ফাইল অবস্থিত । এটার মতো কিছু:

CMakeLists.txt
cmake/FindFoo.cmake
cmake/FindBoo.cmake

CMakeLists.txt বিষয়বস্তু:

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
find_package(Foo REQUIRED) # FOO_INCLUDE_DIR, FOO_LIBRARIES
find_package(Boo REQUIRED) # BOO_INCLUDE_DIR, BOO_LIBRARIES

include_directories("${FOO_INCLUDE_DIR}")
include_directories("${BOO_INCLUDE_DIR}")
add_executable(Bar Bar.hpp Bar.cpp)
target_link_libraries(Bar ${FOO_LIBRARIES} ${BOO_LIBRARIES})

নোট করুন যে CMAKE_MODULE_PATHউচ্চ অগ্রাধিকার আছে এবং আপনি যখন স্ট্যান্ডার্ড Find<package>.cmakeফাইলটি পুনরায় লেখার দরকার পড়ে তখন তা কার্যকর হতে পারে ।

কনফিগার মোড (ইনস্টল)

<package>Config.cmakeফাইলটি বাইরে অবস্থিত এবং install অন্য প্রকল্পের কমান্ড দ্বারা উত্পাদিত ( Fooউদাহরণস্বরূপ)।

foo গ্রন্থাগার:

> cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
project(Foo)

add_library(foo Foo.hpp Foo.cpp)
install(FILES Foo.hpp DESTINATION include)
install(TARGETS foo DESTINATION lib)
install(FILES FooConfig.cmake DESTINATION lib/cmake/Foo)

কনফিগারেশন ফাইলের সরলীকৃত সংস্করণ:

> cat FooConfig.cmake 
add_library(foo STATIC IMPORTED)
find_library(FOO_LIBRARY_PATH foo HINTS "${CMAKE_CURRENT_LIST_DIR}/../../")
set_target_properties(foo PROPERTIES IMPORTED_LOCATION "${FOO_LIBRARY_PATH}")

CMAKE_INSTALL_PREFIXডিরেক্টরিতে ডিফল্ট প্রকল্প ইনস্টল করা হয়েছে :

> cmake -H. -B_builds
> cmake --build _builds --target install
-- Install configuration: ""
-- Installing: /usr/local/include/Foo.hpp
-- Installing: /usr/local/lib/libfoo.a
-- Installing: /usr/local/lib/cmake/Foo/FooConfig.cmake

কনফিগার মোড (ব্যবহার)

আমদানি করা লক্ষ্য সহ find_package(... CONFIG)অন্তর্ভুক্ত করতে ব্যবহার করুন :FooConfig.cmakefoo

> cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
project(Boo)

# import library target `foo`
find_package(Foo CONFIG REQUIRED)

add_executable(boo Boo.cpp Boo.hpp)
target_link_libraries(boo foo)
> cmake -H. -B_builds -DCMAKE_VERBOSE_MAKEFILE=ON
> cmake --build _builds
Linking CXX executable Boo
/usr/bin/c++ ... -o Boo /usr/local/lib/libfoo.a

নোট করুন যে আমদানি করা লক্ষ্যটি অত্যন্ত কনফিগারযোগ্য। আমার উত্তর দেখুন ।

হালনাগাদ


1
আপনার উত্তর দুর্দান্ত। তবে, গিথুবের উদাহরণটি আরও জটিল যে এটি আইএমও হতে পারে। সাধারণ ক্ষেত্রে যেখানে একটি উপ-ডিরেক্টরি (মডিউল) একটি একক শৈল্পিক রফতানি করে, শিরোনামগুলির সাথে একটি স্বাচ্ছন্দ্য বলতে দেয়, আপনাকে কাস্টম * কনফিগারেশন তৈরি করতে হবে না Config ফলস্বরূপ কনফিগারেশনটি উল্লেখযোগ্যভাবে কাটা যেতে পারে। আমি মনে করি আমি নিজেও একটি অনুরূপ উদাহরণ করব।
দিমিত্রিস

2
@ ডিমিট্রিস হ্যাঁ, এটি কিছুটা সহজ করা যায়। আমি গিথুব উদাহরণ আপডেট করেছি তাই এখন এটি ব্যবহার হয় না configure_package_config_file। যাইহোক আপনার যদি অন্য কোনও পরামর্শ থাকে তবে আপনি আমাকে টানতে অনুরোধ পাঠাতে পারেন।

1
@ আরসিও এখানে আমার উদাহরণ । এটি একচেটিয়া বিল্ড (মূল ফোল্ডার থেকে সমস্ত মডিউল) বা স্বায়ত্তশাসিত বিল্ডগুলি (প্রতিটি মডিউল আলাদাভাবে ইনস্টল করা দরকার) সমর্থন করে।
দিমিত্রিস

1
@ ডিমিট্রিস ঠিক আছে, এখন আমি দেখছি। সাধারণত যে ফাইলটি আপনি "অপটিমাইজ" করেন সেগুলি অতিরিক্ত অনুসন্ধান যেমন_পালার উপর নির্ভরতা লোড করার জন্য পরিবেশন করে । আমি মনে করি এটি শুরু করার জন্য এটি একটি ভাল টেম্পলেট তাই আমি এটি এটি রাখব এমনকি এটি বাস্তবে ব্যবহৃত হয়নি। কোডটির বাকী অংশটি আরও সহজ দেখাচ্ছে কারণ আপনি সংস্করণ, ডিলের জন্য রফতানি, bin/libউইন্ডোতে এক্সিকিউটেবল ইনস্টল করার চেষ্টা করুন এবং এটি চালানোর চেষ্টা করুন - এর মতো কিছু কার্যকারিতা হারিয়ে ফেলছেন । এবং নেমস্পেসগুলি দেখতে খুব সুন্দর দেখাচ্ছে, তাই আমি সেগুলিও রাখব :) এছাড়াও আমি monolithicবিল্ড যুক্ত করেছি ।

1
আপনার প্রতিটি উদাহরণ আমার জন্য খুব সহায়ক ছিল। দুজন কেই ধন্যবাদ!
zmb

2

যদি আপনি নিজেকে cmakeতৈরি করতে SomeLibদৌড়াদৌড়ি করছেন (একটি সুপারবিল্ডের অংশ হিসাবে বলুন), ব্যবহারকারী প্যাকেজ রেজিস্ট্রি ব্যবহার করে বিবেচনা করুন । এর জন্য কোনও হার্ড-কোডেড পাথের প্রয়োজন নেই এবং এটি ক্রস প্ল্যাটফর্ম। উইন্ডোজ (mingw64 সহ) এ এটি রেজিস্ট্রি মাধ্যমে কাজ করে। যদি আপনি অনুসন্ধান উপস্থাপনের তালিকাটি কীভাবে Find_packages () কমান্ডের CONFIGমোড দ্বারা নির্মিত তা পরীক্ষা করে দেখেন যে ব্যবহারকারী প্যাকেজ রেজিস্ট্রি অন্যতম উপাদান।

কিভাবে সংক্ষেপে

SomeLibযে বাহ্যিক প্রকল্পের বাইরে আপনার প্রয়োজনীয় টার্গেটগুলি সংযুক্ত করে CMakeLists.txtসেগুলি তৈরি করা ফাইলগুলিতে রফতানি সেটে যুক্ত করে :

add_library(thingInSomeLib ...)
install(TARGETS thingInSomeLib Export SomeLib-export DESTINATION lib)

একটি তৈরি করুন XXXConfig.cmakeফাইল SomeLibতার মধ্যে ${CMAKE_CURRENT_BUILD_DIR}এবং দুটি কল যোগ করে ব্যবহারকারী প্যাকেজ রেজিস্ট্রি মধ্যে এই অবস্থান সঞ্চয় রপ্তানি () থেকে CMakeLists.txtযুক্ত SomeLib:

export(EXPORT SomeLib-export NAMESPACE SomeLib:: FILE SomeLibConfig.cmake) # Create SomeLibConfig.cmake
export(PACKAGE SomeLib)                                                    # Store location of SomeLibConfig.cmake

"ক্রস-প্ল্যাটফর্মহীন হার্ড কোডিং পাথগুলি" ছাড়াই নির্ভর করে এমন প্রকল্পের ফাইলটিতে আপনার find_package(SomeLib REQUIRED)কম্যান্ড জারি করুন ।CMakeLists.txtSomeLibCMAKE_MODULE_PATH

এটি সঠিক পদ্ধতির হতে পারে যখন

এই পদ্ধতির পরিস্থিতি সম্ভবত আপনি সবচেয়ে উপযুক্ত উপযুক্ত যেখানে আপনি কখনই আপনার সফ্টওয়্যারটি বিল্ড ডিরেক্টরিের প্রবাহে ব্যবহার করবেন না (উদাহরণস্বরূপ, আপনি ক্রস-সংকলন করছেন এবং কখনও আপনার মেশিনে কোনও কিছুই ইনস্টল করবেন না, বা আপনি কেবলমাত্র পরীক্ষা চালানোর জন্য সফ্টওয়্যারটি তৈরি করছেন) বিল্ড ডিরেক্টরি), যেহেতু এটি আপনার "বিল্ড" আউটপুটে একটি .cmake ফাইলের লিঙ্ক তৈরি করে, যা অস্থায়ী হতে পারে।

তবে যদি আপনি বাস্তবে কখনও SomeLibআপনার কর্মপ্রবাহে ইনস্টল না করেন, কলিং EXPORT(PACKAGE <name>)আপনাকে হার্ড-কোডড পথ এড়াতে দেয়। এবং অবশ্যই, আপনি যদি ইনস্টল করছেন SomeLib, আপনি সম্ভবত আপনার প্ল্যাটফর্ম CMAKE_MODULE_PATH, ইত্যাদি জানেন , তাই @ ব্যবহারকারী 2288008 এর দুর্দান্ত উত্তরটি আপনাকে .াকা দেবে।


1

আপনাকে প্রতি সেও মডিউল পথ নির্দিষ্ট করার দরকার নেই। সিএমকে জাহাজগুলি তার নিজস্ব অন্তর্নির্মিত সন্ধান_প্যাকেজ স্ক্রিপ্টগুলির সেট সহ পাঠায় এবং তাদের অবস্থান ডিফল্ট CMAKE_MODULE_PATH এ থাকে in

সিএমকেইফাইড হওয়া নির্ভরশীল প্রকল্পগুলির জন্য আরও সাধারণ ব্যবহারের বিষয়টি হ'ল সিএমকে-র বহিরাগত_প্রজেক্ট কমান্ড ব্যবহার করা হবে এবং তারপরে সাবজেক্ট থেকে ব্যবহার [প্রকল্প] .ক্যামেক ফাইল অন্তর্ভুক্ত করা হবে। আপনার যদি কেবল [প্রকল্প] .ক্যামেক স্ক্রিপ্টের প্রয়োজন হয় তবে এটিকে সাবপ্রজেক্টের বাইরে এবং আপনার নিজস্ব প্রকল্পের সোর্স কোডে অনুলিপি করুন এবং তারপরে আপনাকে সিস্টেম স্তরে সাবপ্রজেক্টটি সন্ধানের জন্য CMAKE_MODULE_PATH বাড়াতে হবে না।


12
their location is in the default CMAKE_MODULE_PATHডিফল্টরূপে CMAKE_MODULE_PATHখালি

2018 CMAKE_MODULE_PATHএ @ ব্যবহারকারী 2288008 এর মন্তব্যটি নিশ্চিত করতে পারে Windows উইন্ডোজ খালি।
জেরোইন

এটি আপনার প্রকল্পের সাথে মডিউল শিপিংয়ের জন্য একটি প্রকল্প নির্দিষ্ট পরিবর্তনশীল। "ডিফল্টরূপে এটি খালি, এটি প্রকল্প দ্বারা সেট করার উদ্দেশ্যে।" cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html
Farway

1

এটি সাধারণত কীভাবে হয়? আমি কি cmake/আমার প্রকল্পের মধ্যে সামারলিবের ডিরেক্টরিটি অনুলিপি করে তুলনামূলকভাবে CMAKE_MODULE_PATH সেট করব?

আপনি যদি সিএমকে সেই মডিউলটি রাখতে বিশ্বাস করেন না, তবে - হ্যাঁ, এটি করুন - সাজান:find_SomeLib.cmake আপনার cmake/ডিরেক্টরিতে এবং এর নির্ভরতাগুলি অনুলিপি করুন । ফ্যালব্যাক হিসাবে আমি এটাই করি। যদিও এটি একটি কুরুচিপূর্ণ সমাধান।

নোট করুন যে FindFoo.cmakeমডিউলগুলি প্রতিটি প্ল্যাটফর্ম-নির্ভরতা এবং প্ল্যাটফর্ম-স্বতন্ত্রতার মধ্যে একটি ব্রিজের ধরণ - তারা বিভিন্ন প্ল্যাটফর্ম-নির্দিষ্ট জায়গায় ভেরিয়েবলগুলির পথ অর্জনের জন্য অনুসন্ধান করে যাদের নাম প্ল্যাটফর্ম-স্বতন্ত্র।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.