একই লাইব্রেরির স্থির এবং ভাগ করা সংস্করণ উভয়ই সিএমকে পাওয়া সম্ভব?


141

একই উত্স, সমস্ত, কেবল একটি স্থির এবং ভাগ করা সংস্করণ উভয়ই চান। করাটা সহজ?

উত্তর:


123

হ্যাঁ, এটি পরিমিতরূপে সহজ। কেবলমাত্র দুটি "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(স্থির) পছন্দ করি। (এগুলি লিনাক্সের নাম হবে))


তাদের একই নাম হওয়ার আশা ছিল, তবে ওহ ভাল। আরেকটি প্রশ্ন: আপনি কি সম্ভব হলে সিএমকে স্থির লাইব্রেরিগুলিকে ভাগ করে নেওয়া লাইব্রেরিতে লিঙ্ক করতে বলতে পারেন?
gct

"একই নাম" সম্পর্কে আরও: আপনি যদি উইন্ডোতে থাকেন এবং উভয় লাইব্রেরির জন্য একই নাম চান এবং আপনার যদি ভাগ করা .lib ফাইলের প্রয়োজন না হয়, তবে একটি স্ট্যাটিক .lib এবং একটি শেয়ার্ড .dll তৈরি করা সম্ভব। তবে আপনার যদি সেই সাধারণ শেয়ারের সময় লিঙ্ক করার জন্য আপনার লাইব্রেরিটি ব্যবহার করা হয় তবে সেই ভাগ করা .লিব ফাইলটি আপনার দরকার।
ক্রিস্টোফার ব্রুনস

1
আমি নিশ্চিত নই যে আমি স্থির লাইব্রেরিগুলিকে ভাগ করে নেওয়া লাইব্রেরিতে সংযুক্ত করার বিষয়ে আপনার প্রশ্নটি বুঝতে পেরেছি।
ক্রিস্টোফার ব্রুনস

5
নোট করুন যে এটি আর করার পরামর্শ দেওয়া উপায় নয়। তুচ্ছ-আকারের আকারের প্রকল্পগুলির জন্য (যেগুলি সংকলন করতে কয়েক মিনিট সময় নেয় না কয়েক মিনিট সময় নেয়), সংকলনের সময় দ্বিগুণ করা এড়ানো অবাক করা। অবজেক্ট লাইব্রেরি ব্যবহারের জন্য বা ডক্সের জন্য নীচে ব্যবহারকারীর 656513১9৯ উত্তরটি দেখুন: cmake.org/cmake/help/v3.8/command/…
কিমিকোলোকে

3
@ কিমিকোলোকো: অবজেক্ট লাইব্রেরি পদ্ধতির সাহায্যে সংকলনের সময়টি অর্ধেক কমেছে, তবে এটি স্ট্যাটিক লাইব্রেরিগুলি পজিশন ইন্ডিপেন্ডেন্ট কোড (যেমন সহ -fPIC) হিসাবে তৈরি করা দরকার , যখন স্ট্যাটিক লাইব্রেরিগুলি ব্যবহৃত হয় তখন রানটাইম ওভারহেডের একটি সামান্য পরিমাণ যুক্ত করে। সুতরাং সর্বোচ্চ পারফরম্যান্সের জন্য, এই উত্তরটি এখনও সেরা।
জন জুইনক

95

যেহেতু সিএমকে সংস্করণ ২.৮.৮, আপনি অবজেক্ট ফাইলগুলির নকল সংকলন এড়াতে "অবজেক্ট লাইব্রেরি" ব্যবহার করতে পারেন । দুটি উত্স ফাইল যুক্ত লাইব্রেরির ক্রিস্টোফার ব্রুনস উদাহরণ ব্যবহার করে:

# 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ফাইলগুলি সংকলন করতে বেশ দীর্ঘ সময় নিতে পারে; অবজেক্ট লাইব্রেরিতে আপনি সেগুলি একবারেই সংকলন করতে পারেন।

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


3
এটি আমার জন্য একটি কবজির মতো কাজ করেছিল - কেবলমাত্র সতর্কতামূলক পরবর্তী target_link_libraries()কলগুলি ছিল যা আপনার লাইব্রেরির উপর নির্ভর করে "অবজেক্ট লাইব্রেরি" এর সাথে লিংক করতে পারবেন না; তাদের অবশ্যই নতুন ভাগ করা বা স্থির লাইব্রেরিগুলিকে লক্ষ্য করতে হবে (এবং এটির সদৃশও হতে পারে)। তবে প্রথম মন্তব্যকারীদের অভিজ্ঞতার বিপরীতে এটি বেশ কার্যকর ছিল এবং আমাকে সমস্ত নকল লক্ষ্যগুলি সরিয়ে ফেলতে এবং আমার সমস্ত CMakeLists.txtফাইলকে অর্ধেক করে কাটতে দেয় ।
fish2000

1
লক্ষ্য বৈশিষ্ট্য নির্ধারণের সময় আপনার কি "অব্যাহতি" পড়তে হবে? অর্থ্যাৎ সেট_প্রোপার্টি (টার্গেট $ lজিবলিব P সম্পত্তি ...) বনাম সেট_প্রোপার্টি (টার্গেট অজেলিব প্রোপার্টি ...)
জেনাক

1
যারাই এটিকে অবমূল্যায়ন করেছে ... সেই ব্যক্তি কী ব্যাখ্যা দিতে পারে যে সে কী ভুল বলে বিবেচিত হয়েছে? আরও বেশি কারণ ওপি যা চায় তা করার এটিই প্রস্তাবিত উপায়, সিএমকে ডক্স দেখুন।
ল্যারিক্স ডেসিডুয়া

1
@ user465139 সম্ভবত আপনার ব্যাখ্যা করা উচিত কেন স্থির এবং ভাগ করা লক্ষ্য উভয়র জন্যই এটি পুনরায় ব্যবহারের জন্য অবজেক্ট ফাইলগুলির কাজ করা উচিত। বিশেষত, এসও-তে সাধারণ জ্ঞান এখনও এটি সম্পর্কে খুব বিভ্রান্তিকর, পুরানো / সংরক্ষণাগারগুলি এটির স্পষ্ট করতে কোনও সাহায্য করে না, যেমন। cmake.org/pipermail/cmake/2008-Mark/020315.html স্থিতাবস্থার একটি দৃ explanation ব্যাখ্যা প্রয়োজন। পিএস এটি আমিই হলাম না যে
ম্লসকোট ২

2
@gnac আমি এটি নিশ্চিত করতে পারি না। আমার ক্ষেত্রে, set_propertyআমি কেবল তখন ব্যবহার করি যখন আমি ব্যবহার করি objlibনা ${objlib}। তাহলে হয়তো এই উত্তরটি সংশোধন করা যায়?
জোশ

22

সাধারণত 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অন্য।


43
এটি দু'টি স্থিতিশীল এবং ভাগ করা সংস্করণগুলি বানাচ্ছে বলে মনে হচ্ছে না, যা আমি মনে করি এই প্রশ্নটি কী হচ্ছে।
নিক দেসৌলনিয়ার্স

0

পূর্ববর্তী উত্তরের পরামর্শ অনুসারে একই সংমিশ্রণে শ্বাসনালীতে প্যাক করা সম্ভব, তবে আমি এর বিরুদ্ধে পরামর্শ দেব, কারণ শেষ পর্যন্ত এটি হ্যাক যা কেবল সাধারণ প্রকল্পের জন্য কাজ করে। উদাহরণস্বরূপ, লাইব্রেরির বিভিন্ন সংস্করণের জন্য আপনার কোনও সময়ে বিভিন্ন পতাকা লাগতে পারে (যেমন উইন্ডোতে যেখানে পতাকাগুলি সাধারণত রফতানি প্রতীকগুলির মধ্যে স্যুইচ করতে ব্যবহৃত হয় বা না)। বা উপরে উল্লিখিত হিসাবে, আপনি .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লাইব্রেরি ব্যবহার করে সংকলনগুলি পারস্পরিক করতে চান (উপরে বর্ণিত ক্যাভ্যাটগুলি সহ, তাই এটি করার জন্য আপনার একটি বাধ্যতামূলক কারণ প্রয়োজন), আপনার এখনও দুটি পৃথক প্রকল্পের অন্তিম গ্রন্থাগার থাকতে পারে।


-2

এটা আসলে সম্ভব। @ ক্রিস্টোফার ব্রুনস তার উত্তরে বলেছিলেন, আপনার গ্রন্থাগারের দুটি সংস্করণ যুক্ত করতে হবে:

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 (উইন্ডোজ) পাবেন।


10
২.৮-র উপরে সিএমকে সংস্করণ ব্যবহার করার সময় এটি অপ্রয়োজনীয় [[0?], কারণ সম্পত্তিটি ২০০৯ সালে সরিয়ে দেওয়া হয়েছিল, এবং এটি প্রদান করা আচরণটি এখন ডিফল্ট। এটি ২.৮ এর নীচের লোকদের জন্য উপকারী হতে পারে তবে আপনি যদি এখনও সিএমকে <2.7 ব্যবহার করেন তবে আমি আপনাকে আপগ্রেড করার জন্য অনুরোধ করছি। github.com/Kitware/CMake/commit/…
কিমিকোলোকো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.