উত্তর:
হ্যাঁ, এটি পরিমিতরূপে সহজ। কেবলমাত্র দুটি "add_library" কমান্ড ব্যবহার করুন:
add_library(MyLib SHARED source1.c source2.c)
add_library(MyLibStatic STATIC source1.c source2.c)
আপনার অনেক উত্স ফাইল থাকা সত্ত্বেও, আপনি উত্সের তালিকাটিকে একটি চক্র পরিবর্তনশীলতে রাখবেন, তাই এটি করা এখনও সহজ।
উইন্ডোজ আপনার সম্ভবত প্রতিটি লাইব্রেরির একটি আলাদা নাম দেওয়া উচিত, যেহেতু ভাগ করা এবং স্থির উভয়ের জন্য একটি ".lib" ফাইল রয়েছে। তবে লিনাক্স এবং ম্যাকের জন্য আপনি উভয় গ্রন্থাগারকে একই নাম দিতে পারেন (যেমন libMyLib.a
এবং libMyLib.so
):
set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
তবে আমি লাইব্রেরির স্থির এবং গতিশীল সংস্করণ উভয়কে একই নাম দেওয়ার প্রস্তাব দিচ্ছি না। আমি বিভিন্ন নাম ব্যবহার করতে পছন্দ করি কারণ এটি লাইব্রেরিতে লিঙ্কযুক্ত সরঞ্জামগুলির জন্য সংকলন লাইনে স্থির বনাম গতিশীল লিঙ্কেজ নির্বাচন করা সহজ করে তোলে। সাধারণত আমি নামগুলি libMyLib.so
(ভাগ করা) এবং libMyLib_static.a
(স্থির) পছন্দ করি। (এগুলি লিনাক্সের নাম হবে))
-fPIC
) হিসাবে তৈরি করা দরকার , যখন স্ট্যাটিক লাইব্রেরিগুলি ব্যবহৃত হয় তখন রানটাইম ওভারহেডের একটি সামান্য পরিমাণ যুক্ত করে। সুতরাং সর্বোচ্চ পারফরম্যান্সের জন্য, এই উত্তরটি এখনও সেরা।
যেহেতু সিএমকে সংস্করণ ২.৮.৮, আপনি অবজেক্ট ফাইলগুলির নকল সংকলন এড়াতে "অবজেক্ট লাইব্রেরি" ব্যবহার করতে পারেন । দুটি উত্স ফাইল যুক্ত লাইব্রেরির ক্রিস্টোফার ব্রুনস উদাহরণ ব্যবহার করে:
# list of source files
set(libsrc source1.c source2.c)
# this is the "object library" target: compiles the sources only once
add_library(objlib OBJECT ${libsrc})
# shared libraries need PIC
set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)
# shared and static libraries built from the same object files
add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>)
add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>)
থেকে CMake ডক্স :
একটি অবজেক্ট লাইব্রেরি উত্স ফাইলগুলি সংকলন করে কিন্তু সংরক্ষণাগার বা তাদের অবজেক্ট ফাইলগুলিকে একটি লাইব্রেরিতে লিঙ্ক করে না। পরিবর্তে অন্যান্য টার্গেটগুলি উত্স হিসাবে ফর্মের একটি এক্সপ্রেশন ব্যবহার করে অবজেক্টগুলিকে রেফারেন্স করতে পারে
add_library()
বা সেখানে রেজিস্ট্রেশন করতে পারে, যেখানে অজব্লিবইজ অবজেক্ট লাইব্রেরির নাম।add_executable()
$<TARGET_OBJECTS:objlib>
সহজ কথায় add_library(objlib OBJECT ${libsrc})
কমান্ডটি সিএমকেকে উত্স ফাইলগুলিকে ফাইল করার জন্য নির্দেশ করতে নির্দেশ দেয় *.o
। *.o
ফাইলগুলির এই সংগ্রহটি তখন $<TARGET_OBJECT:objlib>
দুটি add_library(...)
কমান্ডের মতো উল্লেখ করা হয় যা উপযুক্ত লাইব্রেরি তৈরি কমান্ডকে অনুরোধ করে যা একই বস্তু ফাইলগুলির সেট থেকে ভাগ এবং স্থিতিক লাইব্রেরি তৈরি করে । আপনার যদি প্রচুর উত্স ফাইল থাকে তবে *.o
ফাইলগুলি সংকলন করতে বেশ দীর্ঘ সময় নিতে পারে; অবজেক্ট লাইব্রেরিতে আপনি সেগুলি একবারেই সংকলন করতে পারেন।
আপনার দেওয়া মূল্যটি হ'ল অবজেক্ট ফাইলগুলি অবশ্যই অবস্থান-স্বতন্ত্র কোড হিসাবে তৈরি করতে হবে কারণ ভাগ করে নেওয়া লাইব্রেরিগুলিতে এটির প্রয়োজন (স্ট্যাটিক লিবসের কোনও যত্ন নেই)। নোট করুন যে অবস্থান-স্বতন্ত্র কোডটি কম দক্ষ হতে পারে, তাই যদি আপনি সর্বাধিক পারফরম্যান্সের লক্ষ্য রাখেন তবে আপনি স্থির লাইব্রেরিগুলিতে যেতে চাইবেন। তদতিরিক্ত, স্ট্যাটিকালি লিঙ্কযুক্ত এক্সিকিউটেবলগুলি বিতরণ করা সহজ।
target_link_libraries()
কলগুলি ছিল যা আপনার লাইব্রেরির উপর নির্ভর করে "অবজেক্ট লাইব্রেরি" এর সাথে লিংক করতে পারবেন না; তাদের অবশ্যই নতুন ভাগ করা বা স্থির লাইব্রেরিগুলিকে লক্ষ্য করতে হবে (এবং এটির সদৃশও হতে পারে)। তবে প্রথম মন্তব্যকারীদের অভিজ্ঞতার বিপরীতে এটি বেশ কার্যকর ছিল এবং আমাকে সমস্ত নকল লক্ষ্যগুলি সরিয়ে ফেলতে এবং আমার সমস্ত CMakeLists.txt
ফাইলকে অর্ধেক করে কাটতে দেয় ।
set_property
আমি কেবল তখন ব্যবহার করি যখন আমি ব্যবহার করি objlib
না ${objlib}
। তাহলে হয়তো এই উত্তরটি সংশোধন করা যায়?
সাধারণত ADD_LIBRARY
আপনার উদ্দেশ্যটির জন্য কলগুলি নকল করার প্রয়োজন নেই । শুধু ব্যবহার করুন
$> man cmake | grep -A6 '^ *BUILD_SHARED_LIBS$'
BUILD_SHARED_LIBS
Global flag to cause add_library to create shared libraries if on.
If present and true, this will cause all libraries to be built shared unless the library was
explicitly added as a static library. This variable is often added to projects as an OPTION
so that each user of a project can decide if they want to build the project using shared or
static libraries.
যখন বিল্ডিং (এক আউট-অফ-উৎস ডিরেক্টরির মধ্যে) প্রথম, সঙ্গে -DBUILD_SHARED_LIBS:BOOL=ON
, এবং OFF
অন্য।
পূর্ববর্তী উত্তরের পরামর্শ অনুসারে একই সংমিশ্রণে শ্বাসনালীতে প্যাক করা সম্ভব, তবে আমি এর বিরুদ্ধে পরামর্শ দেব, কারণ শেষ পর্যন্ত এটি হ্যাক যা কেবল সাধারণ প্রকল্পের জন্য কাজ করে। উদাহরণস্বরূপ, লাইব্রেরির বিভিন্ন সংস্করণের জন্য আপনার কোনও সময়ে বিভিন্ন পতাকা লাগতে পারে (যেমন উইন্ডোতে যেখানে পতাকাগুলি সাধারণত রফতানি প্রতীকগুলির মধ্যে স্যুইচ করতে ব্যবহৃত হয় বা না)। বা উপরে উল্লিখিত হিসাবে, আপনি .lib
স্ট্যাটিক বা ভাগ করা লাইব্রেরির সাথে সম্পর্কিত কিনা তা নির্ভর করে আপনি ফাইলগুলি বিভিন্ন ডিরেক্টরিতে রেখে দিতে পারেন । এই প্রতিবন্ধকগুলির প্রত্যেকটির জন্য একটি নতুন হ্যাক প্রয়োজন।
এটি সুস্পষ্ট হতে পারে, তবে একটি বিকল্প যা আগে উল্লেখ করা হয়নি তা হ'ল লাইব্রেরির ধরণটিকে পরামিতি বানানো:
set( ${PROJECT_NAME}_LIBTYPE CACHE STRING "library type" )
set_property( CACHE ${PROJECT_NAME}_LIBTYPE PROPERTY STRINGS "SHARED;STATIC" )
add_library( ${PROJECT_NAME} ${PROJECT_NAME}_LIBTYPE ${SOURCE_FILES} )
দুটি পৃথক বাইনারি গাছগুলিতে লাইব্রেরির ভাগ এবং স্থিতিশীল সংস্করণ থাকা বিভিন্ন সংকলনের বিকল্পগুলি পরিচালনা করা সহজ করে। সংকলন গাছগুলি আলাদা রাখার ক্ষেত্রে আমি কোনও গুরুতর অসুবিধা দেখতে পাচ্ছি না, বিশেষত যদি আপনার সংকলনগুলি স্বয়ংক্রিয়ভাবে সজ্জিত থাকে।
মনে রাখবেন যে আপনি যদি একটি মধ্যবর্তী OBJECT
লাইব্রেরি ব্যবহার করে সংকলনগুলি পারস্পরিক করতে চান (উপরে বর্ণিত ক্যাভ্যাটগুলি সহ, তাই এটি করার জন্য আপনার একটি বাধ্যতামূলক কারণ প্রয়োজন), আপনার এখনও দুটি পৃথক প্রকল্পের অন্তিম গ্রন্থাগার থাকতে পারে।
এটা আসলে সম্ভব। @ ক্রিস্টোফার ব্রুনস তার উত্তরে বলেছিলেন, আপনার গ্রন্থাগারের দুটি সংস্করণ যুক্ত করতে হবে:
set(libsrc source1.c source2.c source3.c)
add_library(mylib-static STATIC ${libsrc})
add_library(mylib-shared SHARED ${libsrc})
তারপরে, এখানে বর্ণিত হিসাবে , আপনাকে অবশ্যই উল্লেখ করতে হবে যে উভয় লক্ষ্যকেই একই আউটপুট নাম ব্যবহার করা উচিত এবং একে অপরের ফাইলগুলি ওভাররাইট না করে:
SET_TARGET_PROPERTIES(mylib-static PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(mylib-shared PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1)
এইভাবে, আপনি উভয়ই libmylib.a এবং libmylib.so (লিনাক্সে) বা mylib.lib এবং mylib.dll (উইন্ডোজ) পাবেন।