CMake 3.10



cmake

cmake-buildsystem (7)

المقدمة

يتم تنظيم بنية مبنية على أساس CMake كمجموعة من الأهداف المنطقية عالية المستوى. يتوافق كل هدف مع ملف قابل للتنفيذ أو مكتبة ، أو عبارة عن هدف مخصص يحتوي على أوامر مخصصة. يتم التعبير عن التبعيات بين الأهداف في buildsystem لتحديد ترتيب البناء وقواعد التجديد استجابة للتغيير.

الأهداف الثنائية

يتم تعريف الملفات التنفيذية والمكتبات باستخدام add_executable() و add_library() . تحتوي الملفات الثنائية الناتجة على بادئات وملحقات وملحقات مناسبة للمنصة المستهدفة. يتم التعبير عن التبعيات بين الأهداف الثنائية باستخدام الأمر target_link_libraries() :

  add_library (archive archive.cpp zip.cpp lzma.cpp)
 add_executable (zipapp zipapp.cpp)
 target_link_libraries (أرشيف zipapp)

يتم تعريف archive على أنه مكتبة ثابتة - أرشيف يحتوي على كائنات تم تجميعها من archive.cpp و zip.cpp و lzma.cpp . يتم تعريف zipapp كـ قابل للتنفيذ تشكلت عن طريق ترجمة وربط zipapp.cpp . عند ربط ملف zipapp القابل للتنفيذ ، ترتبط مكتبة archive الثابتة بـ.

الملفات الثنائية القابلة للتنفيذ

يقوم الأمر add_executable() بتعريف هدف قابل للتنفيذ:

  add_executable (mytool mytool.cpp)

يمكن استخدام أوامر مثل add_custom_command() ، الذي ينشئ القواعد ليتم تشغيلها في وقت EXECUTABLE هدف EXECUTABLE مثل قابل للتنفيذ COMMAND . ستضمن قواعد buildsystem إنشاء الملف التنفيذي قبل محاولة تشغيل الأمر.

أنواع المكتبة الثنائية

مكتبات عادية

بشكل افتراضي ، يقوم الأمر add_library() بتعريف مكتبة ثابتة ، ما لم يتم تحديد نوع. يمكن تحديد نوع ما عند استخدام الأمر:

  add_library (archive SHARED archive.cpp zip.cpp lzma.cpp)
  add_library (archive STATIC archive.cpp zip.cpp lzma.cpp)

قد يتم تمكين متغير BUILD_SHARED_LIBS لتغيير سلوك add_library() لإنشاء مكتبات مشتركة بشكل افتراضي.

في سياق تعريف buildsystem ككل ، من غير المهم إلى حد كبير ما إذا كانت مكتبات معينة SHARED أو STATIC - تعمل الأوامر ومواصفات التبعية وواجهات برمجة التطبيقات الأخرى بطريقة مماثلة بغض النظر عن نوع المكتبة. نوع مكتبة MODULE يختلف عن أنه غير مرتبط بشكل عام - لا يتم استخدامه في الجانب الأيمن من الأمر target_link_libraries() . هو نوع يتم تحميله كمكوّن إضافي باستخدام تقنيات وقت التشغيل. إذا لم تقم المكتبة بتصدير أي رموز غير مُدارة (مثل مورد Windows DLL ، C ++ / CLI DLL) ، فمن الضروري ألا تكون المكتبة مكتبة SHARED لأن CMake يتوقع أن تقوم المكتبات SHARED بتصدير رمز واحد على الأقل.

  add_library (أرشفة MODULE 7z.cpp)
ابل ابل

قد يتم وضع علامة على مكتبة FRAMEWORK الهدف لإنشاء مكتبة OS X أو iOS Framework. يعيّن CFBundleIdentifier مفتاح CFBundleIdentifier الحزمة بشكل فريد.

  add_library (MyFramework SHARED MyFramework.cpp)
 set_target_properties (خصائص MyFramework
   الإطار الحقيقي
   FRAMEWORK_VERSION أ
   MACOSX_FRAMEWORK_IDENTIFIER org.cmake.MyFramework
 )

مكتبات الكائنات

نوع مكتبة OBJECT غير مرتبط أيضًا بـ. يحدد مجموعة غير المحفوظات من ملفات الكائن الناتجة من تجميع الملفات المصدر المعطاة. يمكن استخدام مجموعة ملفات الكائنات كمدخلات مصدر لأهداف أخرى:

  add_library (archive OBJECT archive.cpp zip.cpp lzma.cpp)

 add_library (archiveExtras STATIC $ <TARGET_OBJECTS: archive> extras.cpp)

 add_executable (test_exe $ <TARGET_OBJECTS: archive> test.cpp)

لا يجوز استخدام مكتبات OBJECT في الجانب الأيسر من target_link_libraries() . كما قد لا يتم استخدامها كـ TARGET في استخدام توقيع الأمر add_custom_command(TARGET) . قد يتم تثبيتها ، وسيتم تصديرها كمكتبة INTERFACE.

على الرغم من أن مكتبات الكائنات قد لا يتم تسميتها مباشرة في المكالمات إلى الأمر target_link_libraries() ، إلا أنها يمكن أن تكون "مرتبطة" بشكل غير مباشر باستخدام "مكتبة الواجهة" التي تم تعيين الخاصية المستهدفة الخاصة بها INTERFACE_SOURCES إلى اسم $<TARGET_OBJECTS:objlib> .

على الرغم من أنه قد لا يتم استخدام مكتبات الكائنات كـ TARGET في استخدام توقيع الأمر add_custom_command(TARGET) ، يمكن استخدام قائمة الكائنات بواسطة add_custom_command(OUTPUT) أو file(GENERATE) باستخدام $<TARGET_OBJECTS:objlib> .

بناء مواصفات ومتطلبات الاستخدام

تحدد أوامر target_include_directories() و target_compile_definitions() و target_compile_options() مواصفات الإنشاء ومتطلبات الاستخدام للأهداف الثنائية. تملأ الأوامر INCLUDE_DIRECTORIES و COMPILE_DEFINITIONS و COMPILE_OPTIONS الخصائص المستهدفة على التوالي و / أو INTERFACE_INCLUDE_DIRECTORIES و INTERFACE_COMPILE_DEFINITIONS و INTERFACE_COMPILE_OPTIONS الخصائص المستهدفة.

كل واحد من الأوامر لديه وضع PRIVATE و PUBLIC و INTERFACE . يقوم وضع PRIVATE بملء متغير INTERFACE_ فقط للخاصية الهدف ويؤدي وضع INTERFACE ملء المتغيرات INTERFACE_ فقط. يملأ وضع PUBLIC كلا المتغيرات الخاصة بالخاصية الهدف المعنية. يمكن استدعاء كل أمر باستخدامات متعددة لكل كلمة رئيسية:

  target_compile_definitions (أرشيف
   بناء خاص_ WITH_LZMA
   واجهة استخدام USING_ARCHIVE_LIB
 )

لاحظ أن متطلبات الاستخدام لم يتم تصميمها كطريقة لجعل عمليات downstreams تستخدم COMPILE_OPTIONS معينة أو COMPILE_DEFINITIONS وغيرها للراحة فقط. يجب أن تكون محتويات الخصائص متطلبات ، وليس مجرد توصيات أو راحة.

راجع قسم إنشاء الحزم cmake-packages(7) في cmake-packages(7) لمناقشة الرعاية الإضافية التي يجب اتخاذها عند تحديد متطلبات الاستخدام أثناء إنشاء الحزم لإعادة التوزيع.

خصائص الهدف

يتم استخدام محتويات INCLUDE_DIRECTORIES و COMPILE_DEFINITIONS و COMPILE_OPTIONS خصائص الهدف بشكل مناسب عند ترجمة الملفات المصدر لهدف ثنائي.

تتم إضافة إدخالات في INCLUDE_DIRECTORIES إلى سطر ترجمة مع البادئات -I أو -isystem وفي ترتيب المظهر في قيمة الخاصية.

يتم COMPILE_DEFINITIONS الإدخالات في COMPILE_DEFINITIONS بـ -D أو /D وإضافتها إلى سطر الترجمة بترتيب غير محدد. تتم DEFINE_SYMBOL الخاصية المستهدفة DEFINE_SYMBOL أيضًا DEFINE_SYMBOL ترجمة كحالة ملائمة خاصة لأهداف مكتبة SHARED و MODULE .

يتم إدخالات الإدخالات في COMPILE_OPTIONS shell وإضافتها بترتيب المظهر في قيمة الخاصية. تحتوي العديد من خيارات الترجمة على معالجة منفصلة خاصة ، مثل POSITION_INDEPENDENT_CODE .

تعتبر محتويات خصائص INTERFACE_COMPILE_DEFINITIONS و INTERFACE_COMPILE_DEFINITIONS و INTERFACE_COMPILE_OPTIONS هي متطلبات الاستخدام - فهي تحدد المحتوى الذي يجب على المستهلكين استخدامه لتكوين الارتباط الذي يظهرون عليه وربطه بشكل صحيح. لأي هدف ثنائي ، يتم استهلاك محتويات كل خاصية INTERFACE_ على كل هدف محدد في أمر target_link_libraries() :

  set (srcs archive.cpp zip.cpp)
 إذا (LZMA_FOUND)
   قائمة (APPEND srcs lzma.cpp)
 إنهاء إذا()
 add_library (archive SHARED $ {srcs})
 إذا (LZMA_FOUND)
   # يتم تجميع مصادر مكتبة الأرشيف مع -DBUILDING_WITH_LZMA
   target_compile_definitions (archive PRIVATE BUILDING_WITH_LZMA)
 إنهاء إذا()
 target_compile_definitions (أرشفة INTERFACE USING_ARCHIVE_LIB)

 add_executable (المستهلك)
 # ربط المستهلك بالأرشفة واستهلاك متطلبات استخدامه.  المستهلك
 يتم تصنيف # من المصادر القابلة للتنفيذ باستخدام -DUSING_ARCHIVE_LIB.
 target_link_libraries (أرشيف المستهلك)

لأنه من الشائع أن يتم إضافة الدليل المصدر ودليل INCLUDE_DIRECTORIES إلى INCLUDE_DIRECTORIES ، يمكن تمكين متغير CMAKE_INCLUDE_CURRENT_DIR لإضافة الدلائل المقابلة بسهولة إلى INCLUDE_DIRECTORIES من جميع الأهداف. يمكن تمكين متغير CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE لإضافة الدلائل المطابقة إلى INTERFACE_INCLUDE_DIRECTORIES من كافة الأهداف. هذا يجعل من استخدام الأهداف في دلائل مختلفة متعددة ملائمة من خلال استخدام الأمر target_link_libraries() .

متطلبات الاستخدام متعدية

يمكن لمتطلبات الاستخدام للهدف أن تنتشر بشكل عابر للمعالين. يحتوي الأمر target_link_libraries() على كلمات رئيسية خاصة بكل من PRIVATE و INTERFACE و PUBLIC للتحكم في التكاثر.

  add_library (archive archive.cpp)
 target_compile_definitions (أرشفة INTERFACE USING_ARCHIVE_LIB)

 add_library (serialization serialization.cpp)
 target_compile_definitions (واجهة تسلسلية USING_SERIALIZATION_LIB)

 add_library (archiveExtras extras.cpp)
 target_link_libraries (archiveExtras PUBLIC archive)
 target_link_libraries (archiveExtras PRIVATE serialization)
 يتم تصنيف # archiveExtras مع -DUSING_ARCHIVE_LIB
 # و- DUSING_SERIALIZATION_LIB

 add_executable (Consumer Consumer.cpp)
 يتم تصنيف # المستهلك مع -DUSING_ARCHIVE_LIB
 target_link_libraries (أرشيف المستهلك Extras)

لأن archive هي تبعية عامة لـ archiveExtras ، يتم نشر متطلبات الاستخدام الخاصة بها consumer أيضًا. لأن serialization هو تبعية PRIVATE لـ archiveExtras ، لا يتم نشر متطلبات الاستخدام الخاصة به consumer .

بشكل عام ، يجب تحديد التبعية في استخدام target_link_libraries() مع الكلمة الأساسية PRIVATE إذا تم استخدامها فقط من خلال تطبيق مكتبة ، وليس في ملفات الرأس. إذا تم استخدام التبعية بشكل إضافي في ملفات الرأس الخاصة بمكتبة (على سبيل المثال ، لوراثة الفئة) ، فيجب أن يتم تحديدها على أنها تبعية عامة. يجب تحديد التبعية التي لا يتم استخدامها من خلال تنفيذ مكتبة ، ولكن فقط من خلال رؤوسها باعتبارها تبعية في INTERFACE . قد يتم استدعاء الأمر target_link_libraries() باستخدامات متعددة لكل كلمة رئيسية:

  target_link_libraries (archiveExtras
   ارشيف PUBLIC
   التسلسل الخاص
 )

يتم نشر متطلبات الاستخدام بقراءة المتغيرات INTERFACE_ للخصائص المستهدفة من التبعيات وإلحاق القيم إلى المتغيرات غير INTERFACE_ للمعامل. على سبيل المثال ، تتم قراءة INTERFACE_INCLUDE_DIRECTORIES من التبعيات INCLUDE_DIRECTORIES من المعامل. في الحالات التي يكون فيها الطلب ملائمًا وصيانته ، ولا يسمح الترتيب الناتج عن الاستدعاءات target_link_libraries() بالتجميع الصحيح ، قد يؤدي استخدام الأمر المناسب لتعيين الخاصية مباشرةً إلى تحديث الطلب.

على سبيل المثال ، إذا كان يجب تحديد المكتبات المرتبطة لأحد الأهداف بالترتيب lib2 lib3 ، إلا أنه يجب تحديد lib3 في الترتيب lib3 lib2 :

  target_link_libraries (myExe lib1 lib2 lib3)
 target_include_directories (myExe
   PRIVATE $ <TARGET_PROPERTY: lib3 ، INTERFACE_INCLUDE_DIRECTORIES>)

لاحظ أنه يجب توخي الحذر عند تحديد متطلبات الاستخدام للأهداف التي سيتم تصديرها للتثبيت باستخدام الأمر install(EXPORT) . راجع إنشاء الحزم للمزيد.

خصائص واجهة متوافقة

بعض الخصائص الهدف مطلوبة لتكون متوافقة بين الهدف وواجهة كل تبعية. على سبيل المثال ، قد تحدد الخاصية المستهدفة POSITION_INDEPENDENT_CODE قيمة منطقية لتحديد ما إذا كان يجب تصنيف الهدف كرمز مستقل عن الموضع ، والذي يتضمن نتائج خاصة بالنظام الأساسي. قد يحدد الهدف أيضًا متطلبات الاستخدام INTERFACE_POSITION_INDEPENDENT_CODE للإبلاغ بأنه يجب تصنيف العملاء كرمز مستقل عن الموضع.

  add_executable (exe1 exe1.cpp)
 set_property (TARGET exe1 PROPERTY POSITION_INDEPENDENT_CODE ON)

 add_library (lib1 SHARED lib1.cpp)
 set_property (TARGET lib1 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

 add_executable (exe2 exe2.cpp)
 target_link_libraries (exe2 lib1)

هنا ، سيتم تجميع كل من exe1 و exe1 مستقل عن الموضع. سيتم أيضًا تصنيف lib1 كرمز مستقل عن موضع لأن هذا هو الإعداد الافتراضي للمكتبات SHARED . إذا كانت التبعيات متعارضة ، فإن المتطلبات غير المتوافقة cmake(1) تصدر cmake(1) :

  add_library (lib1 SHARED lib1.cpp)
 set_property (TARGET lib1 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

 add_library (lib2 SHARED lib2.cpp)
 set_property (TARGET lib2 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)

 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 lib1)
 set_property (TARGET exe1 PROPERTY POSITION_INDEPENDENT_CODE OFF)

 add_executable (exe2 exe2.cpp)
 target_link_libraries (exe2 lib1 lib2)

متطلبات lib1 INTERFACE_POSITION_INDEPENDENT_CODE ليست "متوافقة" مع الخاصية POSITION_INDEPENDENT_CODE للهدف exe1 . تطلب المكتبة أن يبنى المستهلكون كرمز مستقل عن الموضع ، بينما يحدد الملف التنفيذي أنه غير مبني كرمز مستقل عن الموضع ، لذلك يتم إصدار التشخيص.

متطلبات lib2 و lib2 ليست "متوافقة". يتطلب أحدها أن يتم بناء المستهلكين كرمز مستقل عن الموضع ، في حين يتطلب الآخر أن لا يتم إنشاء العملاء كرمز مستقل عن الموضع. نظرًا exe2 بكلتا exe2 وهما في حالة تضارب ، يتم إصدار تشخيص.

لتكون "متوافقًا" ، يجب أن تكون الخاصية POSITION_INDEPENDENT_CODE ، إذا تم تعيينها ، هي نفسها ، بالمعنى المنطقي ، كخاصية INTERFACE_POSITION_INDEPENDENT_CODE لجميع التبعيات المحددة العابرة التي تم تعيين تلك الخاصية عليها.

قد يتم تمديد هذه الخاصية "متطلبات واجهة متوافقة" إلى خصائص أخرى عن طريق تحديد الخاصية في محتوى الخاصية المستهدفة COMPATIBLE_INTERFACE_BOOL . يجب أن تكون كل خاصية محددة متوافقة بين الهدف المستهلك والخاصية المقابلة ببادئة INTERFACE_ من كل تبعية:

  add_library (lib1Version2 SHARED lib1_v2.cpp)
 set_property (TARGET lib1Version2 PROPERTY INTERFACE_CUSTOM_PROP ON)
 set_property (TARGET lib1Version2 APPEND PROPERTY
   COMPATIBLE_INTERFACE_BOOL CUSTOM_PROP
 )

 add_library (lib1Version3 SHARED lib1_v3.cpp)
 set_property (TARGET lib1Version3 PROPERTY INTERFACE_CUSTOM_PROP OFF)

 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 lib1Version2) # CUSTOM_PROP سيكون ON

 add_executable (exe2 exe2.cpp)
 target_link_libraries (exe2 lib1Version2 lib1Version3) # Diagnostic

قد تشارك الخصائص غير البوليانية أيضًا في حسابات "الواجهة المتوافقة". يجب أن تكون الخصائص المحددة في الخاصية COMPATIBLE_INTERFACE_STRING إما غير محددة أو مقارنتها بالسلسلة نفسها بين كافة التبعيات المحددة العابرة. قد يكون ذلك مفيدًا لضمان عدم ربط إصدارات غير متوافقة متعددة من المكتبة معًا من خلال المتطلبات المتعددة للهدف:

  add_library (lib1Version2 SHARED lib1_v2.cpp)
 set_property (TARGET lib1Version2 PROPERTY INTERFACE_LIB_VERSION 2)
 set_property (TARGET lib1Version2 APPEND PROPERTY
   COMPATIBLE_INTERFACE_STRING LIB_VERSION
 )

 add_library (lib1Version3 SHARED lib1_v3.cpp)
 set_property (TARGET lib1Version3 PROPERTY INTERFACE_LIB_VERSION 3)

 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 lib1Version2) # LIB_VERSION سيكون "2"

 add_executable (exe2 exe2.cpp)
 target_link_libraries (exe2 lib1Version2 lib1Version3) # Diagnostic

تحدد الخاصية المستهدفة COMPATIBLE_INTERFACE_NUMBER_MAX أنه سيتم تقييم المحتوى عدديًا وسيتم حساب الحد الأقصى للرقم بين جميع العناصر المحددة:

  add_library (lib1Version2 SHARED lib1_v2.cpp)
 set_property (TARGET lib1Version2 PROPERTY INTERFACE_CONTAINER_SIZE_REQUIRED 200)
 set_property (TARGET lib1Version2 APPEND PROPERTY
   COMPATIBLE_INTERFACE_NUMBER_MAX CONTAINER_SIZE_REQUIRED
 )

 add_library (lib1Version3 SHARED lib1_v3.cpp)
 set_property (TARGET lib1Version3 PROPERTY INTERFACE_CONTAINER_SIZE_REQUIRED 1000)

 add_executable (exe1 exe1.cpp)
 رقم CONTAINER_SIZE_REQUIRED سيكون "200"
 target_link_libraries (exe1 lib1Version2)

 add_executable (exe2 exe2.cpp)
 رقم CONTAINER_SIZE_REQUIRED سيكون "1000"
 target_link_libraries (exe2 lib1Version2 lib1Version3)

وبالمثل ، يمكن استخدام COMPATIBLE_INTERFACE_NUMBER_MIN لحساب القيمة الدنيا الرقمية لخاصية ما من تبعيات.

يمكن قراءة كل قيمة خاصية "متوافقة" محسوبة في المستهلك في وقت الإنشاء باستخدام تعبيرات المولد.

لاحظ أنه بالنسبة لكل مُرسل ، يجب ألا تتقاطع مجموعة الخصائص المحددة في كل خاصية واجهة متوافقة مع المجموعة المحددة في أي من الخصائص الأخرى.

تصحيح خاصية الملكية

نظرًا لأن مواصفات الإنشاء يمكن تحديدها من خلال التبعيات ، فإن عدم تحديد موقع الرمز الذي ينشئ هدفًا ورمزًا مسؤولًا عن تحديد مواصفات البنية قد يجعل التعليل أكثر صعوبة. cmake(1) مرفق تصحيح الأخطاء لطباعة أصل محتويات الخصائص التي يمكن تحديدها عن طريق التبعيات. يتم سرد الخصائص التي يمكن تصحيحه في وثائق متغير CMAKE_DEBUG_TARGET_PROPERTIES :

  مجموعة (CMAKE_DEBUG_TARGET_PROPERTIES
   INCLUDE_DIRECTORIES
   COMPILE_DEFINITIONS
   POSITION_INDEPENDENT_CODE
   CONTAINER_SIZE_REQUIRED
   LIB_VERSION
 )
 add_executable (exe1 exe1.cpp)

في حالة الخصائص المدرجة في COMPATIBLE_INTERFACE_BOOL أو COMPATIBLE_INTERFACE_STRING ، يوضح مخرجات تصحيح الأخطاء أن الهدف كان مسؤولاً عن إعداد الخاصية ، وأي تبعيات أخرى حددت الخاصية أيضًا. في حالة COMPATIBLE_INTERFACE_NUMBER_MAX و COMPATIBLE_INTERFACE_NUMBER_MIN ، يعرض إخراج التصحيح قيمة الخاصية من كل تبعية ، وما إذا كانت القيمة تحدد الحد الأقصى الجديد.

بناء مواصفات مع تعبيرات مولد

قد تستخدم مواصفات البناء generator expressions التي تحتوي على محتوى قد يكون مشروطًا أو معروفًا فقط في وقت الإنشاء. على سبيل المثال ، يمكن قراءة القيمة "المتوافقة" المحسوبة لأحد المواقع مع تعبير TARGET_PROPERTY :

  add_library (lib1Version2 SHARED lib1_v2.cpp)
 set_property (TARGET lib1Version2 PROPERTY
   INTERFACE_CONTAINER_SIZE_REQUIRED 200)
 set_property (TARGET lib1Version2 APPEND PROPERTY
   COMPATIBLE_INTERFACE_NUMBER_MAX CONTAINER_SIZE_REQUIRED
 )

 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 lib1Version2)
 target_compile_definitions (exe1 PRIVATE
     CONTAINER_SIZE = $ <TARGET_PROPERTY: CONTAINER_SIZE_REQUIRED>
 )

في هذه الحالة ، سيتم تجميع الملفات المصدر -DCONTAINER_SIZE=200 مع -DCONTAINER_SIZE=200 .

قد يتم ضبط مواصفات البنية المحددة بطريقة مريحة باستخدام تعبير مولد CONFIG .

  target_compile_definitions (exe1 PRIVATE
     $ <$ <CONFIG: تصحيح>: DEBUG_BUILD>
 )

تتم مقارنة المعلمة CONFIG بحالة غير حساسة مع التكوين الذي يتم إنشاؤه. في ظل وجود أهداف IMPORTED ، يتم أيضًا احتساب محتوى MAP_IMPORTED_CONFIG_DEBUG بهذا التعبير.

تحتوي بعض buildsystems التي تم إنشاؤها بواسطة cmake(1) على تكوين تكوين مسبق محدد في متغير CMAKE_BUILD_TYPE . يتم إنشاء buildsystem لـ IDEs مثل Visual Studio و Xcode مستقلة عن التكوين الإنشاء ، ولا يعرف تكوين الإنشاء الفعلي حتى وقت الإنشاء. لذلك ، رمز مثل

  string (TOLOWER $ {CMAKE_BUILD_TYPE} _type)
 إذا كان (_type STREQUAL debug)
   target_compile_definitions (exe1 PRIVATE DEBUG_BUILD)
 إنهاء إذا()

قد يبدو أنها تعمل من أجل مولدات Makefile ومولدات Ninja ، ولكنها ليست محمولة إلى مولدات IDE. بالإضافة إلى ذلك ، لا يتم حساب تعيينات تكوين IMPORTED مع رمز مثل هذا ، لذا يجب تجنبه.

يتم تقييم تعبير مولد TARGET_POLICY وتعبير المولد TARGET_POLICY مع سياق الهدف المستهلك. هذا يعني أنه يمكن تقييم مواصفات متطلبات الاستخدام بشكل مختلف بناءً على المستهلك:

  add_library (lib1 lib1.cpp)
 target_compile_definitions (lib1 INTERFACE
   $ <$ <STREQUAL: $ <TARGET_PROPERTY: TYPE>، قابل للتنفيذ>: LIB1_WITH_EXE>
   $ <$ <STREQUAL: $ <TARGET_PROPERTY: TYPE>، SHARED_LIBRARY>: LIB1_WITH_SHARED_LIB>
   $ <$ <TARGET_POLICY: CMP0041>: CONSUMER_CMP0041_NEW>
 )

 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 lib1)

 cmake_policy (SET CMP0041 NEW)

 add_library (shared_lib shared_lib.cpp)
 target_link_libraries (shared_lib lib1)

سيتم تجميع الملف التنفيذي exe1 مع -DLIB1_WITH_EXE ، بينما سيتم تجميع المكتبة المشتركة shared_lib مع -DLIB1_WITH_SHARED_LIB و -DCONSUMER_CMP0041_NEW ، لأن السياسة CMP0041 هي NEW عند النقطة التي يتم فيها إنشاء هدف shared_lib .

يلف تعبير BUILD_INTERFACE المتطلبات التي يتم استخدامها فقط عند استهلاكها من هدف في نفس buildsystem ، أو عند استهلاكها من هدف تم تصديره إلى دليل الإنشاء باستخدام الأمر export() . يلف تعبير INSTALL_INTERFACE المتطلبات التي يتم استخدامها فقط عند استهلاكها من هدف تم تثبيته وتصديره باستخدام الأمر install(EXPORT) :

  add_library (ClimbingStats climbingstats.cpp)
 target_compile_definitions (ClimbingStats INTERFACE
   $ <BUILD_INTERFACE: ClimbingStats_FROM_BUILD_LOCATION>
   $ <INSTALL_INTERFACE: ClimbingStats_FROM_INSTALLED_LOCATION>
 )
 تثبيت (TARGETS ClimbingStats EXPORT libExport $ {InstallArgs})
 تثبيت (EXPORT libExport NAMESPACE Upstream ::
         DESTINATION lib / cmake / ClimbingStats)
 تصدير (EXPORT libExport NAMESPACE Upstream: :)

 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 ClimbingStats)

في هذه الحالة ، سيتم exe1 الملف التنفيذي -DClimbingStats_FROM_BUILD_LOCATION مع -DClimbingStats_FROM_BUILD_LOCATION . تنشئ أوامر التصدير أهداف IMPORTED باستخدام إما INSTALL_INTERFACE أو BUILD_INTERFACE تم حذفها ، وتم *_INTERFACE علامة *_INTERFACE . يحتوي مشروع منفصل يستهلك حزمة ClimbingStats على:

  find_package (يتطلب التسلق)

 add_executable (Downstream main.cpp)
 target_link_libraries (Downstream Upstream :: ClimbingStats)

استنادًا إلى ما إذا كانت حزمة ClimbingStats قد تم استخدامها من موقع -DClimbingStats_FROM_BUILD_LOCATION أو موقع التثبيت ، فسيتم تجميع هدف Downstream إما مع -DClimbingStats_FROM_BUILD_LOCATION أو -DClimbingStats_FROM_INSTALL_LOCATION . لمعرفة المزيد عن الحزم والتصدير ، انظر cmake-packages(7) .

تضمين الدلائل ومتطلبات الاستخدام

تضمين الدلائل تتطلب بعض الاعتبارات الخاصة عند تحديدها كمتطلبات الاستخدام وعند استخدامها مع تعبيرات المولد. يقبل الأمر target_include_directories() كلاً من دلائل تضمين نسبيًا ومطلقًا:

  add_library (lib1 lib1.cpp)
 target_include_directories (lib1 PRIVATE
   /المسار المطلق
   مسار نسبي
 )

يتم تفسير المسارات النسبية بالنسبة إلى الدليل المصدر حيث يظهر الأمر. المسارات النسبية غير مسموح بها في INTERFACE_INCLUDE_DIRECTORIES من IMPORTED .

في الحالات التي يتم فيها استخدام تعبير مولد غير INSTALL_PREFIX يمكن استخدام تعبير INSTALL_PREFIX ضمن وسيطة تعبير INSTALL_INTERFACE . وهي علامة بديلة تتوسع لبادئة التثبيت عند استيرادها بواسطة مشروع مستهلك.

تضمين متطلبات استخدام الدلائل شائعة بين شجرة الإصدار وشجرة التثبيت. يمكن استخدام تعبيرات مولد BUILD_INTERFACE و INSTALL_INTERFACE لوصف متطلبات الاستخدام المنفصلة المستندة إلى موقع الاستخدام. يُسمح بالمسارات النسبية داخل تعبير INSTALL_INTERFACE ويتم تفسيرها بالنسبة إلى بادئة التثبيت. فمثلا:

  add_library (ClimbingStats climbingstats.cpp)
 target_include_directories (ClimbingStats INTERFACE
   $ <BUILD_INTERFACE: $ {CMAKE_CURRENT_BINARY_DIR} / الناتج>
   $ <INSTALL_INTERFACE: / مطلق / مسار>
   $ <INSTALL_INTERFACE: النسبي / مسار>
   $ <INSTALL_INTERFACE: $ <INSTALL_PREFIX> / $ <CONFIG> / الناتج>
 )

يتم توفير واجهات برمجة التطبيقات الملائمة اثنين المتعلقة تتضمن متطلبات استخدام الدلائل. قد يتم تمكين المتغير CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ، مع وجود تأثير مكافئ لـ:

  set_property (TARGET tgt APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
   $ <BUILD_INTERFACE: $ {CMAKE_CURRENT_SOURCE_DIR}؛ $ {CMAKE_CURRENT_BINARY_DIR}>
 )

لكل هدف يتأثر. تتمثل ملاءمة الأهداف المثبتة في أحد مكونات INCLUDES DESTINATION مع أمر install(TARGETS) :

  تثبيت (TARGETS foo bar bat EXPORT tgts $ {dest_args}
   تشمل تشمل وجهة
 )
 تثبيت (EXPL tgts $ {other_args})
 تثبيت (FILES $ {headers} DESTINATION include)

هذا يكافئ بإلحاق ${CMAKE_INSTALL_PREFIX}/include إلى INTERFACE_INCLUDE_DIRECTORIES لكل من الأهداف IMPORTED المثبتة عند إنشاء بواسطة install(EXPORT) .

عندما يتم استهلاك INTERFACE_INCLUDE_DIRECTORIES من هدف مستورد ، يتم معاملة الإدخالات في الخاصية كما تتضمن الدلائل SYSTEM ، كما لو تم سردها في INTERFACE_SYSTEM_INCLUDE_DIRECTORIES من التبعية. هذا يمكن أن يؤدي إلى إغفال تحذيرات برنامج التحويل البرمجي لعناوين موجودة في هذه الدلائل. قد يتم التحكم في هذا السلوك للأهداف المستوردة عن طريق تعيين الخاصية الهدف NO_SYSTEM_FROM_IMPORTED على مستهلكي الأهداف المستوردة.

إذا كان الهدف الثنائي مرتبطًا بشكل عمودي بإطار Mac OX ، Headers أيضًا التعامل مع دليل Headers للإطار كمتطلب استخدام. هذا له نفس التأثير مثل تمرير دليل الإطار كدليل تضمين.

مثل مواصفات البناء ، يمكن تحديد link libraries بشروط تعبير المولد. ومع ذلك ، وبما أن استهلاك متطلبات الاستخدام يعتمد على مجموعة من الاعتماديات المرتبطة ، هناك قيود إضافية على أن تبعيات الارتباط يجب أن تشكل "رسمًا دوريًا موجّهًا". بمعنى ، إذا كان الارتباط إلى هدف يعتمد على قيمة خاصية مستهدفة ، فقد لا تعتمد تلك الخاصية المستهدفة على الاعتماديات المرتبطة:

  add_library (lib1 lib1.cpp)
 add_library (lib2 lib2.cpp)
 الهدف_link_libraries (lib1 PUBLIC
   $ <$ <TARGET_PROPERTY: POSITION_INDEPENDENT_CODE>: lib2>
 )
 add_library (lib3 lib3.cpp)
 set_property (TARGET lib3 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 lib1 lib3)

نظرًا لأن قيمة الخاصية POSITION_INDEPENDENT_CODE الخاصة بالهدف exe1 تعتمد على المكتبات المرتبطة ( lib3 ) ، ويتم تحديد حافة ربط exe1 بواسطة الخاصية POSITION_INDEPENDENT_CODE نفسها ، فإن الرسم البياني للإعالة أعلاه يحتوي على دورة. cmake(1) يصدر cmake(1) في هذه الحالة.

القطع الانتاجية

إنشاء أهداف buildsystem إنشاؤها بواسطة add_library() add_executable() قواعد لإنشاء مخرجات ثنائية. لا يمكن تحديد موقع إخراج الثنائيات بالضبط إلا في وقت TARGET_FILE لأنه يمكن أن يعتمد على تكوين TARGET_FILE ولغة الارتباطات التابعة المرتبطة ، إلخ. يمكن استخدام TARGET_FILE و TARGET_LINKER_FILE والتعبيرات ذات الصلة للوصول إلى اسم وموقع توليد الثنائيات. لا تعمل هذه التعبيرات OBJECT ، حيث لا يوجد ملف واحد يتم إنشاؤه بواسطة مثل هذه المكتبات ذات الصلة بالتعبيرات.

توجد ثلاثة أنواع من عناصر الإخراج التي قد يتم إنشاؤها بواسطة أهداف كما هو موضح بالتفصيل في الأقسام التالية. يختلف تصنيفها بين الأنظمة الأساسية DLL ومنصات غير DLL. جميع الأنظمة التي تستند إلى Windows بما في ذلك Cygwin هي منصات DLL.

وقت التشغيل الناتج المخرجات

قد يكون ناتج وقت التشغيل الناتج عن هدف buildsystem:

  • الملف التنفيذي (على سبيل المثال. .exe ) من هدف قابل للتنفيذ تم إنشاؤه بواسطة الأمر add_executable() .
  • على منصات مكتبة الارتباط الحيوي (DLL): الملف القابل للتنفيذ (على سبيل المثال .dll ) لاستهداف مكتبة مشتركة تم إنشاؤه بواسطة الأمر add_library() مع الخيار SHARED .

يمكن استخدام الخواص المميزة RUNTIME_OUTPUT_DIRECTORY و RUNTIME_OUTPUT_NAME للتحكم في مواقع نصوص الإخراج الموجودة في وقت التشغيل والأسماء في شجرة الإنشاء.

مكتبة المخرجات التحف

قد تكون أحد عناصر الإخراج المكتبي في المكتبة لهدف buildsystem:

  • ملف الوحدة النمطية للتحميل (على سبيل المثال .dll أو .so ) من هدف مكتبة وحدة نمطية تم إنشاؤه بواسطة الأمر add_library() مع خيار MODULE .
  • على الأنظمة الأساسية غير DLL: ملف المكتبة المشتركة (مثل .so أو .dylib ) لاستهداف مكتبة مشتركة مشتركة تم إنشاؤها بواسطة الأمر add_library() مع الخيار SHARED .

يمكن استخدام خصائص LIBRARY_OUTPUT_DIRECTORY و LIBRARY_OUTPUT_NAME للتحكم في مواقع وقطاعات أثرية مخرجات المكتبة في شجرة البناء.

أرشيف الإخراج المخرجات

قد تكون أحد عناصر إنتاج الأرشيف الخاصة ببرنامج buildsystem:

  • ملف مكتبة ثابتة (على سبيل المثال .lib أو .a ) من هدف مكتبة ثابت تم إنشاؤه بواسطة الأمر add_library() مع خيار STATIC .
  • على منصات مكتبة الارتباط الحيوي (DLL): ملف مكتبة الاستيراد (مثل .lib ) لاستهداف مكتبة مشتركة تم إنشاؤه بواسطة الأمر add_library() مع خيار SHARED . لا يمكن ضمان وجود هذا الملف إلا إذا قامت المكتبة بتصدير رمز غير مدار واحد على الأقل.
  • على الأنظمة الأساسية DLL: ملف مكتبة الاستيراد (على سبيل المثال .lib ) من هدف قابل للتنفيذ تم إنشاؤه بواسطة الأمر add_executable() عند ENABLE_EXPORTS الخاصية المستهدفة ENABLE_EXPORTS الخاصة به.

يمكن استخدام خواص ARCHIVE_OUTPUT_DIRECTORY و ARCHIVE_OUTPUT_NAME المخرجات في الأرشيف والأسماء في شجرة ARCHIVE_OUTPUT_NAME .

أوامر Directory-Scoped

يكون target_include_directories() و target_compile_definitions() و target_compile_options() تأثير على هدف واحد فقط في كل مرة. تحتوي الأوامر add_definitions() و add_compile_options() و include_directories() على وظيفة مماثلة ، ولكنها تعمل في نطاق الدليل بدلاً من النطاق المستهدف للراحة.

الأهداف الزائفة

لا تمثل بعض أنواع الأهداف مخرجات نظام buildsystem ، ولكن فقط المدخلات مثل التبعيات الخارجية أو الأسماء المستعارة أو غيرها من الأعمال غير البناءية. لا يتم تمثيل أهداف Pseudo في buildsystem الذي تم إنشاؤه.

الأهداف المستوردة

يمثل هدف IMPORTED تبعية موجودة مسبقًا. عادة ما يتم تحديد هذه الأهداف من خلال حزمة المنبع ، وينبغي أن تعامل على أنها غير قابلة للتغيير. ليس من الممكن استخدام هدف IMPORTED في الجانب الأيسر من target_compile_definitions() ، target_include_directories() ، target_compile_options() أو target_link_libraries() ، لأن ذلك قد يكون محاولة لتعديله. تم تصميم الأهداف IMPORTED ليتم استخدامها فقط في الجانب الأيمن من تلك الأوامر.

قد تحتوي الأهداف IMPORTED على نفس خصائص متطلبات الاستخدام التي يتم نشرها كأهداف ثنائية ، مثل INTERFACE_LINK_LIBRARIES و INTERFACE_POSITION_INDEPENDENT_CODE و INTERFACE_POSITION_INDEPENDENT_CODE و INTERFACE_POSITION_INDEPENDENT_CODE و INTERFACE_POSITION_INDEPENDENT_CODE .

يمكن أيضًا أن تتم قراءة LOCATION من هدف IMPORTED ، على الرغم من أنه نادرًا ما يكون هناك سبب للقيام بذلك. يمكن أوامر مثل add_custom_command() استخدام هدف IMPORTED EXECUTABLE كـ COMMAND القابل للتنفيذ.

نطاق تعريف هدف IMPORTED هو الدليل الذي تم تعريفه فيه. يمكن الوصول إليها واستخدامها من الدلائل الفرعية ، ولكن ليس من الدلائل الأم أو الدلائل الأخوة. يشبه النطاق نطاق متغير cmake.

من الممكن أيضاً تحديد هدف عالمي مستورد يمكن الوصول إليه عالمياً في نظام buildsystem.

راجع cmake-packages(7) لمعرفة المزيد عن إنشاء الحزم باستخدام الأهداف IMPORTED .

أهداف الاسم المستعار

هدف ALIAS هو اسم يمكن استخدامه بالتبادل مع اسم هدف ثنائي في سياقات للقراءة فقط. تعتبر حالة الاستخدام الأساسية لأهداف ALIAS على سبيل المثال ، أو الملفات التنفيذية لاختبار الوحدات المصاحبة للمكتبة ، والتي قد تكون جزءًا من نفس البنية أو بنيت بشكل منفصل بناءً على تكوين المستخدم.

  add_library (lib1 lib1.cpp)
 تثبيت (TARGETS lib1 EXPORT lib1Export $ {dest_args})
 تثبيت (EXPORT lib1Export NAMESPACE Upstream :: $ {other_args})

 add_library (Upstream :: lib1 ALIAS lib1)

في دليل آخر ، يمكننا الربط دون قيد أو شرط مع هدف Upstream::lib1 ، والذي قد يكون هدف IMPORTED من حزمة ، أو هدف ALIAS إذا تم بناؤه كجزء من نفس البنية.

  إذا كان (NOT TARGET Upstream :: lib1)
   find_package (المطلوب lib1)
 إنهاء إذا()
 add_executable (exe1 exe1.cpp)
 target_link_libraries (exe1 Upstream :: lib1)

أهداف ALIAS ليست قابلة للتغيير أو قابلة للتثبيت أو للتصدير. فهي محلية بالكامل لوصف buildsystem. A name can be tested for whether it is an ALIAS name by reading the ALIASED_TARGET property from it:

 get_target_property(_aliased Upstream::lib1 ALIASED_TARGET)
if(_aliased)
  message(STATUS "The name Upstream::lib1 is an ALIAS for ${_aliased}.")
 إنهاء إذا()

مكتبات الواجهة

An INTERFACE target has no LOCATION and is mutable, but is otherwise similar to an IMPORTED target.

It may specify usage requirements such as INTERFACE_INCLUDE_DIRECTORIES , INTERFACE_COMPILE_DEFINITIONS , INTERFACE_COMPILE_OPTIONS , INTERFACE_LINK_LIBRARIES , INTERFACE_SOURCES , and INTERFACE_POSITION_INDEPENDENT_CODE . Only the INTERFACE modes of the target_include_directories() , target_compile_definitions() , target_compile_options() , target_sources() , and target_link_libraries() commands may be used with INTERFACE libraries.

A primary use-case for INTERFACE libraries is header-only libraries.

 add_library(Eigen INTERFACE)
target_include_directories(Eigen INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
  $<INSTALL_INTERFACE:include/Eigen>
 )

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 Eigen)

Here, the usage requirements from the Eigen target are consumed and used when compiling, but it has no effect on linking.

Another use-case is to employ an entirely target-focussed design for usage requirements:

 add_library(pic_on INTERFACE)
set_property(TARGET pic_on PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
add_library(pic_off INTERFACE)
set_property(TARGET pic_off PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)

add_library(enable_rtti INTERFACE)
target_compile_options(enable_rtti INTERFACE
  $<$<OR:$<COMPILER_ID:GNU>,$<COMPILER_ID:Clang>>:-rtti>
 )

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 pic_on enable_rtti)

This way, the build specification of exe1 is expressed entirely as linked targets, and the complexity of compiler-specific flags is encapsulated in an INTERFACE library target.

The properties permitted to be set on or read from an INTERFACE library are:

  • Properties matching INTERFACE_*
  • Built-in properties matching COMPATIBLE_INTERFACE_*
  • EXPORT_NAME
  • IMPORTED
  • NAME
  • Properties matching IMPORTED_LIBNAME_*
  • Properties matching MAP_IMPORTED_CONFIG_*

INTERFACE libraries may be installed and exported. Any content they refer to must be installed separately:

 add_library(Eigen INTERFACE)
target_include_directories(Eigen INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
  $<INSTALL_INTERFACE:include/Eigen>
 )

install(TARGETS Eigen EXPORT eigenExport)
install(EXPORT eigenExport NAMESPACE Upstream::
  DESTINATION lib/cmake/Eigen
 )
install(FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/src/eigen.h
    ${CMAKE_CURRENT_SOURCE_DIR}/src/vector.h
    ${CMAKE_CURRENT_SOURCE_DIR}/src/matrix.h
  DESTINATION include/Eigen
 )

原文